Minha EA faz uma entrada dupla - página 7

 

se eu usar o sono, vou perder carrapatos?

quais serão as conseqüências? podem ser compartilhadas comigo?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

se eu usar o sono, vou perder carrapatos?

quais serão as conseqüências? podem ser compartilhadas comigo?

Depende de sua estratégia. Como esta questão sobre "negócios duplos" só pode ocorrer quando seu código comercial é executado em cada carrapato, você provavelmente tem uma estratégia que depende do carrapato. Portanto, cabe a você avaliar qual pode ser a conseqüência se você perder os carrapatos que chegam durante seu atraso (sono).

 
angevoyageur:

Depende de sua estratégia. Como esta questão sobre "negociações duplas" só pode ocorrer quando seu código de negociação é executado em cada tic, você provavelmente tem uma estratégia que depende do tic. Portanto, cabe a você avaliar qual pode ser a conseqüência se você perder os carrapatos que chegam durante seu atraso (sono).

Portanto, se eu dormir por 800

significa que perco carrapatos para os próximos 800ms? Depois de entrar no meu comércio, meu EA não faz nada, apenas fica ali sentado até TP ou SL ou espera pelo tempo para sair.

Então, minha estratégia está bem se eu usar o sono?

chamar refrescos() me devolve os carrapatos?

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 
doshur:

Então, se eu dormir por 800

significa que perco carrapatos para os próximos 800ms? Depois de entrar no meu comércio, meu EA não faz nada, apenas fica ali sentado até TP ou SL ou espera pelo tempo para sair.

Então, minha estratégia está bem se eu usar o sono?

chamar refrescos() me devolve os carrapatos?

doshur, carrapatos você perde, você perde, não há nenhuma máquina de retorno.

Com relação à documentação emhttps://www.mql5.com/en/docs/common/sleep, a funçãosuspende a execução do Expert Advisor atual ou do script dentro de um intervalo especificado.

Portanto, mesmo os eventos OnTimer serão suspensos, provavelmente porque a EA usa apenas um fio.

Portanto, usar um Sleep fixo não é uma solução definitiva, é apenas "numerologia", ou seja, uma solução alternativa se o atraso for inferior ao seu valor.

E é por isso que proponho um teste de loop PositionSelect após a abertura do negócio, para verificar duas vezes a execução PositionOpen e retornar como uma alternativa melhor do que apenas Sleep(), e que também comprovam a causa do problema (de acordo com os testesangevoyageur).

Documentation on MQL5: Common Functions / Sleep
Documentation on MQL5: Common Functions / Sleep
  • www.mql5.com
Common Functions / Sleep - Documentation on MQL5
 

Isto é o que estou usando agora. Onde devo codificar o trabalho fornecido por figurelli de uma maneira mais elegante

//
         {
            Price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

            if(m_Trade.PositionOpen(Symbol(), ORDER_TYPE_BUY, LotSize, Price, 0, 0))
            {
               Sleep(800);

               if(m_Trade.ResultRetcode() == 10009)
               {
                  Print("Position opened in ", Symbol());

                  return;
               }
               else
               {
                  Print("Error opening position in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
               }
            }
            else
            {
               Print("Error with PositionOpen in ", Symbol(), " - ", m_Trade.ResultComment(), "\n", "Return Code Desc - ", m_Trade.ResultRetcodeDescription());
            }
         }
 
doshur:

Isto é o que estou usando agora. Onde devo codificar o trabalho fornecido por figurelli de uma maneira mais elegante

Olá doshur, eu também estava tendo problemas com entradas duplas em um dos meus EA's. Na verdade, estes problemas estavam ocorrendo somente quando eu estava negociando ativos altamente líquidos. Mesmo depois de definir ordens para serem enviadas em modo assíncrono, a EA estava "aparentemente" esperando muito tempo por uma resposta do servidor para atualizar PositionsTotal()... enquanto isso, outros tiquetaques de entrada estavam desencadeando as condições para enviar uma segunda ordem... no fórum português eu postei uma workaround, que eu gostaria de compartilhar aqui.

A idéia é simples:

//--- global variables
CTrade trade;
bool position_opened=false;

//--- inside OnTick()
if( conditions to open && position_opened==false )
  {
   //--- set the global variable to true to avoid duplicate orders
   position_opened=true;
   trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment");
  }

O único problema com este código é o caso em que o pedido não é aceito pelo servidor, então é preciso "resetar" a variável global... Você poderia usar isto:

MqlTradeResult mresult;

//--- 
if(mresult.retcode==10009 || mresult.retcode==10008)
  {Print("Success!");}
else 
  {
   Print("Error = ",GetLastError());
   ResetLastError();
   //--- Sets the global variable to false
   position_opened=false;
   return;
  }

Assim, no caso da primeira ordem enviada retornar um erro, a variável global será definida como falsa para que a EA possa enviar outra ordem. No entanto, devo dizer que testei este código apenas em ações e futuros, mas não no mercado forex... :-(

 
Malacarne:

Olá doshur, eu também estava tendo problemas com entradas duplas em um dos meus EA's. Na verdade, estes problemas estavam ocorrendo somente quando eu estava negociando ativos altamente líquidos. Mesmo depois de definir ordens para serem enviadas em modo assíncrono, a EA estava "aparentemente" esperando muito tempo por uma resposta do servidor para atualizar PositionsTotal()... enquanto isso, outros tiquetaques de entrada estavam desencadeando as condições para enviar uma segunda ordem... no fórum português eu postei uma workaround, que eu gostaria de compartilhar aqui.

A idéia é simples:

O único problema com este código é o caso em que o pedido não é aceito pelo servidor, então é preciso "resetar" a variável global... Você poderia usar isto:

Assim, no caso da primeira ordem enviada retornar um erro, a variável global será definida como falsa para que a EA possa enviar outra ordem. No entanto, devo dizer que testei este código apenas em ações e futuros, mas não no mercado forex... :-(

Isto parece viável. Vamos ver sefigurelli eangevoyageur têm algum comentário sobre este trabalho...
 
doshur:
Isto parece viável. Vamos ver sefigurelli eangevoyageur têm algum comentário sobre este trabalho...

Esta solução proposta por Malacarne (com alguns ajustes que vou propor) é ótima, já que para mim não é uma alternativa (como Malacarne modestamente se refere), mas uma forma elegante e correta de abordar esta questão.

Na minha opinião, o problema original da entrada dupla não é um bug MT5, mas um bug de codificação, uma vez que a ajuda afirma:

"Aconclusão bem sucedida do método PositionOpen(...) nem sempre significa a execução bem sucedida da operação comercial. É necessário verificar o resultado da solicitação de negociação (código de retorno do servidor de negociação) usandoResultRetcode() e valor, retornado porResultDeal()".

Portanto, sugiro algumas pequenas mudanças para ser mais resistente a qualquer condição de mercado:

1) Teste PostionOpen() também retorna, como o código original, por exemplo:

if (trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")) position_opened=true;

2) Um tratamento mais completo de ResultRetcode(), uma vez que você pode ter outras posições relevantes abertas, como 10010 -TRADE_RETCODE_DONE_PARTIAL - Apenas parte da solicitação foi completada. Além disso, 10008 - TRADE_RETCODE_PLACED - O pedido feito não é um sucesso para mim, apenas 10009 -TRADE_RETCODE_DONE -Pedido completado, e isto são mensagens assíncronas, portanto a segunda parte do código Malacarne poderia considerar isto e/ounegociar bilhete, após o negócio ser executado,também.

De qualquer forma, parece-me que estamos no caminho certo e no corte final agora.

 
Malacarne:

Olá doshur, eu também estava tendo problemas com entradas duplas em um dos meus EA's. Na verdade, estes problemas estavam ocorrendo somente quando eu estava negociando ativos altamente líquidos. Mesmo depois de definir ordens para serem enviadas em modo assíncrono, a EA estava "aparentemente" esperando muito tempo por uma resposta do servidor para atualizar PositionsTotal()... enquanto isso, outros tiquetaques de entrada estavam desencadeando as condições para enviar uma segunda ordem... no fórum português eu postei um workaround, que eu gostaria de compartilhar aqui.

A idéia é simples:

O único problema com este código é o caso em que o pedido não é aceito pelo servidor, então é preciso "resetar" a variável global... Você poderia usar isto:

Assim, no caso da primeira ordem enviada retornar um erro, a variável global será definida como falsa para que a EA possa enviar outra ordem. No entanto, devo dizer que testei este código apenas em ações e futuros, mas não no mercado forex... :-(

É uma abordagem válida, porém você tem que redefinir sua posição da variável global_aberta para falsa quando sua posição é fechada. Onde você está fazendo isso?

Sobre sua implementação, alguns detalhes :

  1. Não há necessidade de redefinir posição_aberta para verdadeiro e depois para falso se houver um erro.
  2. Você está usando um objeto da classe CTrade, portanto não há necessidade de usar uma nova estrutura MqlTradeResult.
  3. Como o figurelli observou em seu post, você tem que verificar o valor retornado de PositionOpen.
  4. O nome da classe é CTrade, não Ctrade. mql5 é sensível a maiúsculas e minúsculas.
  5. position_opened é um bool, não é preciso compará-lo com falso. Se você fizer isso, terá que usar '==' e não '='.

Portanto, aqui está o código modificado(Compilado mas não testado) :

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>

//--- global variables
CTrade trade;
bool position_opened=false;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   bool conditions_to_open;
   ENUM_ORDER_TYPE order_type;
   double lot;
   double price,sl,tp;

//---...set variables

//--- inside OnTick()
   if(conditions_to_open && !position_opened) //-- Or position_opened==false
     {
      if(trade.PositionOpen(_Symbol,order_type,lot,price,sl,tp,"comment")
         && 
         (trade.ResultRetcode()==10009 || trade.ResultRetcode()==10008)) //-- Or others condition according to your needs
        {
         //--- set the global variable to true to avoid duplicate orders
         position_opened=true;
         Print("Success!");
        }
      else
        {
         Print("Error = ",GetLastError(), "trade error = ", trade.ResultRetcode());
         //--- Sets the global variable to false
         // position_opened=false;                                         //-- Not needed as position_opened is already false
         return;
        }

     }
//--- 
  }
//+------------------------------------------------------------------+
 
figurelli:

...

Na minha opinião, o problema original da entrada dupla não é um bug MT5, mas um bug de codificação, uma vez que a ajuda afirma:

"Aconclusão bem sucedida do método PositionOpen(...) nem sempre significa a execução bem sucedida da operação comercial. É necessário verificar o resultado da solicitação de negociação (código de retorno do servidor de negociação) usandoResultRetcode() e valor, retornado porResultDeal()".

Não creio que esteja relacionado com a questão deste tópico. O problema que recebemos é no caso de uma solicitação ter sido preenchida com sucesso e uma posição ser aberta. Mas esta posição é aberta no servidor comercial, o problema que encontramos é quando há um atraso mais importante como de costume e o terminal MT5 é notificado desta nova posição DEPOIS de um novo tick já ter sido processado.

Não é um bug, pois foi projetado desta forma. MAS, na minha opinião, é um defeito projetado para uma plataforma que permite explicitamente solicitações comerciais síncronas e assíncronas. Estamos falando aqui de uma solicitação que deveria ser síncrona, mas na verdade não é realmente síncrona, pois quando você recebe a resposta do servidor para a solicitação (tradeRetCode no código acima) ainda temos que esperar que a plataforma MT5 seja informada e atualizada sobre os resultados da negociação. (Eu entendi tudo isso com este tópico).

Portanto, sugiro algumas pequenas mudanças para ser mais resiliente a qualquer condição de mercado:

1) Test PostionOpen() retorna também, como o código original, por exemplo:

2) Um tratamento mais completo do ResultRetcode(), uma vez que você pode ter outras posições relevantes abertas, como 10010 -TRADE_RETCODE_DONE_PARTIAL - Apenas parte da solicitação foi completada. Além disso, 10008 - TRADE_RETCODE_PLACED - O pedido feito não é um sucesso para mim, apenas 10009 -TRADE_RETCODE_DONE -Pedido completado, e isto são mensagensassíncronas, portanto a segunda parte do código Malacarne poderia considerar isto e/ounegociar bilhete, após o negócio ser executado,também.

De qualquer forma, parece-me que estamos no caminho certo e no corte final agora.

Naturalmente, você está absolutamente certo que é preciso verificar o valor retornado de PositionOpen AND the return code of the trade result. Entretanto, o ResultRetCode é síncrono, é a atualização do banco de dados MT5 sobre posição (negócio e ordem) que é assíncrono. O teste que fiz com sua proposta demonstrou isto, pois uso, é claro, um código que verificou o valor retornado do pedido de troca.