Discussão do artigo "A Implementação de um Modo Multi-currency (múltiplas moedas) no MetaTrader 5" - página 5

 
Lazarev:

Diga-me,

1. se eu precisar apenas de Bid e Ask de outras moedas, é justo usar "espiões"?

2. é apenas uma ideia, não há possibilidade na função onChartEvent de verificar eventos de outras moedas e não apenas da moeda atual?

3. é possível definir o valor do cronômetro como menor que um no evento onTimer, de modo que ele baixe o valor das cotações com muito mais frequência e, consequentemente, fique atrasado em relação à hora do último tique pelo tempo mínimo?

4. ou é possível usar "CHARTEVENT_CUSTOM+n" para verificar, no meu caso, o cruzamento de mashes em outros gráficos?

1. Usando.

2. Há uma opção. O evento de outra moeda deve ser enviado para o gráfico em que o EA com OnChartEvent() está definido.

3. Não. Um é o mínimo.

4. Pode.

 

Criei um simples "indicador espião" SendEvent.mq5, que envia um evento quando chega uma nova cotação:

#property indicator_chart_window
#property indicator_plots 0
int OnInit()
  {
   return(0);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   EventChartCustom(0,1,0,0,_Symbol);
   return(rates_total);
  }

Criei um Expert Advisor simples que recebe eventos desse indicador e tenta fazer uma operação de negociação (aqui está uma parte, o texto completo está no arquivo anexo):

void OnChartEvent(const int id, // Manipulador de eventos ChartEvent
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)            // sparam contém o nome do instrumento
  {
      // solicitar Digit, Point, Ask, Bid para o instrumento para o qual o evento ocorreu
      if(!SymbolInfoInteger(sparam,SYMBOL_DIGITS,dig)) Print("SymbolInfoInteger(SYMBOL_DIGITS) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_POINT,p)) Print("SymbolInfoDouble(SYMBOL_POINT) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_BID,Bid)) Print("SymbolInfoDouble(SYMBOL_BID) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_ASK,Ask)) Print("SymbolInfoDouble(SYMBOL_ASK) ERROR!");
      d=(int)dig;
      if(1>0) // nós sempre compramos
        {
         q.action=TRADE_ACTION_DEAL; // preencher a estrutura MqlTradeRequest e tentar fazer uma operação de negociação
         q.symbol=sparam; // sparam contém o nome da ferramenta
         q.volume=Lot;
         q.price=NormalizeDouble(Ask,d);
         q.sl=NormalizeDouble(Ask-p*StopLoss,d);
         q.tp=NormalizeDouble(Ask+p*TakeProfit,d);
         q.deviation=0;
         q.type=ORDER_TYPE_BUY;
         q.type_filling=ORDER_FILLING_FOK;
         // verificar as propriedades atuais da ferramenta
         Print("Bid=",DoubleToString(Bid,8),", Ask=",DoubleToString(Ask,8),", Digits=",d,", Points=",DoubleToString(p,8));
         // verificar a estrutura da solicitação de negociação que enviaremos
         Print("q.action=",q.action,", q.symbol=",q.symbol,", q.volume=",q.volume,", q.price=",DoubleToString(q.price,d),", q.sl=",DoubleToString(q.sl,d),", q.tp=",DoubleToString(q.tp,d),", q.deviation=",q.deviation,", q.type=",q.type,", q.type_filling=",q.type_filling);
         Print(OrderCheck(q,ch));                                  // verificar se uma operação comercial pode ser realizada
         Print("ch.retcode=",ch.retcode,", ch.comment=",ch.comment); // resultado
         Print("OrderSend:",OrderSend(q,s));                        // tentativa de fazer uma operação de comércio
         Print("s.retcode=",s.retcode,", s.comment=",s.comment);     // resultado
        }
      if(0>0) // se a condição for corrigida, nós venderemos
        {
         // аналогично для продажи
        }
     }
  }

O Expert Advisor recebe eventos do indicador, mas no testador (com e sem visualização) não consegue realizar uma operação de negociação - o erro "Invalid Request" é retornado, código de retorno 10013. Em tempo real, ele funciona normalmente. Se a operação de negociação no Expert Advisor for executada a partir de OnTick() em vez de OnChartEvent(), também funcionará bem.

Inseri o envio da solicitação de negociação no modelo do Expert Advisor oferecido pelo autor do artigo no CodeBase - as operações de negociação também não funcionam (o mesmo erro).

Alguém pode me dizer qual é o motivo? Li neste tópico que OnChartEvent() não é processado no testador, mas, nesse caso, os eventos enviados pelo indicador são processados no testador, mas é impossível executar uma operação de negociação a partir de OnChartEvent() no testador.

Arquivos anexados:
ea.mq5  4 kb
SendEvent.mq5  1 kb
[Excluído]  
zdd:

Criei um simples "indicador-espião" SendEvent.mq5, que envia um evento quando chega uma nova cotação:

Criei um Expert Advisor simples que recebe eventos desse indicador e tenta fazer uma operação de negociação (apresento uma parte dele, o texto completo está no arquivo anexo):

O Expert Advisor recebe eventos do indicador, mas no testador (com e sem visualização) não consegue realizar uma operação de negociação - o erro "Invalid Request" é retornado, código de retorno 10013. Em tempo real, ele funciona normalmente. Se uma operação de negociação no Expert Advisor for executada a partir de OnTick() em vez de OnChartEvent(), também funcionará bem.

Inseri o envio da solicitação de negociação no modelo do Expert Advisor oferecido pelo autor do artigo no CodeBase - as operações de negociação também não funcionam (mesmo erro).

Alguém pode me dizer qual é o motivo? Li neste tópico que OnChartEvent() não é processado no testador, mas, nesse caso, os eventos enviados pelo indicador são processados no testador, mas é impossível executar uma operação de negociação a partir de OnChartEvent() no testador.

Tente trazer meu peixe à minha mente. É claro que a lógica não está completa e é muito burra, mas parece ser muito semelhante ao que você precisa.

Pelo menos as posições do mercado são abertas tanto no testador quanto na demonstração.

Não sei por que (estou com preguiça de descobrir), mas seu exemplo me deu 10013 em qualquer situação.

PS

É melhor vincular-se a objetos padrão (como CAccountInfo e CTrade). Mas se você tiver paciência para escrever tudo sozinho, ficarei muito feliz.

A propósito, é melhor pegar a implementação do espião no artigo ou fazer uma cópia modificável (eu, por exemplo, sugiro substituir este ano "(long)_Period" pela data-hora do envio do evento ou outras informações úteis). Sua variante é, de certa forma, bastante "crua".

Arquivos anexados:
DemoEA.mq5  20 kb
 
Interesting:

Veja se você consegue fazer meu peixe funcionar. A lógica está incompleta e é muito obtusa, mas parece ser muito semelhante ao que você precisa.

Obrigado, entendi. Se você declarar as estruturas MqlTradeRequest e MqlTradeResult em nível global, isso funcionará!
 
Muito obrigado pelo artigo!
 

Estou tentando obter preços para três pares: EURUSD, EURGBP e GBPUSD. Tudo funciona bem quando seleciono "Todos os ticks" ou "Somente preços de abertura" no testador de estratégia. Mas se eu escolher "Every tick based on real ticks", por algum motivo, vários eventos "New Bar" podem ocorrer em um minuto para um instrumento.

Para repetir, você pode selecionar um intervalo, por exemplo, de 2016.07.15 a 2016.07.19. Aqui está um exemplo de registro, observe o 7º minuto e o 9º minuto:

2016.07.15 00:05:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333

2016.07.15 00:05:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:05:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33399

2016.07.15 00:06:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8334

2016.07.15 00:06:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:06:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33382

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33381

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33384

2016.07.15 00:08:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83329

2016.07.15 00:08:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11167

2016.07.15 00:08:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

2016.07.15 00:09:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33396

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

Qual é a razão para esse comportamento ao selecionar o modo "All ticks based on real ticks"?
 
ooparadise:

Estou tentando obter preços para três pares: EURUSD, EURGBP e GBPUSD. Tudo funciona bem quando seleciono "Todos os ticks" ou "Somente preços de abertura" no testador de estratégia. Mas se eu escolher "Every tick based on real ticks", por algum motivo, vários eventos "New Bar" podem ocorrer em um minuto para um instrumento.

Para repetir, você pode selecionar um intervalo, por exemplo, de 2016.07.15 a 2016.07.19. Aqui está um exemplo de registro, observe o 7º minuto e o 9º minuto:

Qual é a razão para esse comportamento ao selecionar o modo "Todos os ticks baseados em ticks reais"?

Como você captura o evento "Nova barra"? Na versão 1375, a precisão da chegada do tique foi aprimorada para milissegundos:

Testador: Adicionado suporte para tempo com precisão de milissegundos. Anteriormente, no testador de estratégia, o quantum de tempo era de um segundo.

  • As funções EventSetMillisecondTimer e Sleep agora funcionam com mais precisão no testador de estratégias.
  • A precisão do envio de ticks no teste de Expert Advisors de várias moedas aumentou. Anteriormente, se vários ticks fossem colocados em um segundo (o volume de ticks de uma barra de minutos é superior a 60), todos eles eram atribuídos ao mesmo tempo. Ao testar os Expert Advisors de uma única moeda, isso não tem muita importância, pois os ticks são simplesmente passados para o Expert Advisor sequencialmente. Entretanto, ao testar vários pares, é importante saber qual tique do par veio primeiro. Anteriormente, os ticks de cada símbolo eram transmitidos ao Expert Advisor sequencialmente: primeiro todos os ticks de um símbolo por um segundo, depois todos os ticks de outro símbolo. Agora, eles são transmitidos levando-se em conta os milissegundos.

    Ao testar com ticks reais, os milissegundos são retirados dos dados originais do tick. Ao gerar ticks, os milissegundos são soletrados de acordo com o volume do tick. Por exemplo, se houver 3 ticks em um segundo, serão atribuídos a eles os tempos 000, 333 e 666 milissegundos.
 

Eu pego umanova barra da forma como está escrito no artigo. Ou seja, o indicador envia o evento "New Bar" dessa forma (em comparação com o tempo anterior, minutos, horas, dias, meses):

   double price_current=price[rates_total-1];

   TimeCurrent(time);

   if(prev_calculated==0)

     {

      EventCustom(CHARTEVENT_INIT,price_current);

      prev_time=time; 

      return(rates_total);

     }

//--- new tick

   if((flag_event & CHARTEVENT_TICK)!=0) EventCustom(CHARTEVENT_TICK,price_current);       


//--- check change time

   if(time.min==prev_time.min && 

      time.hour==prev_time.hour && 

      time.day==prev_time.day &&

      time.mon==prev_time.mon) return(rates_total);


//--- new minute

   if((flag_event & CHARTEVENT_NEWBAR_M1)!=0) EventCustom(CHARTEVENT_NEWBAR_M1,price_current); 

ATUALIZAÇÃO: O problema desapareceu ao instalar a compilação 1375.

 

Obrigado por esse artigo enorme. Até agora, eu não tinha ouvido falar do EventChartCustom. Eu estava tentando outros eventos de gráfico, mas eles só levavam em conta eventos causados por ação humana. Isso resolve muitas coisas.

A propósito, eu trabalho com MQL4, e 98% das vezes é a mesma coisa.

Abraços

 

Muito obrigado por isso, é muito útil. Excelente trabalho!