OnTradeTransaction Volume Errado

 
Olá, desenvolvi um EA (conta Netting) que utiliza ordens pendentes SellLimit e BuyLimit no lugar do TakeProfit nativos do MT5. O motivo disso foi evitar as derrapagens que ocorrem quando utilizamos o TP e SP do MT5, uma vez que eles encerram as posições a mercado e não com ordens no book.

O EA coloca Ordens BuyLimit e SellLimit no gráfico para entrada na operação e quando uma dessas ordens é executada ele coloca uma ordem inversa (BuyLimit ou SellLimit) para sair da operação, funcionando como um TakeProfit. Quando essa ordem de saida é executada ele recoloca a ordem de entrada no mesmo lugar de antes e com mesmo volume de contratos.

Acontece que utilizei a função OnTradeTransaction para essa manipulação das ordens e ocorre tudo corretamente em conta DEMO e em conta REAL com 1 contrato de volume.

O problema ocorre quando tento utilizar mais de 1 contrato de volume na conta REAL. O EA executa uma ordem de entrada com 4 contratos e as vezes coloca uma ordem de saida com apenas 3 contratos, ou as vezes ele coloca a saida com a quantidade de contratos correta, mas quando ela é executada a recolocação da ordem de entrada é que acaba tendo menos contratos.

Minha desconfiança é que possa existir algum erro na forma que estou utilizando o enum DEAL_VOLUME, entretando eu não consegui identificar qual seria o erro de lógica.

Pontos importantes: 1- O bug sempre é com uma quantidade menor de contratos, nunca ocorreu de colocar mais contratos.
       2- O bug não ocorre em conta Demo e no Testador de Estratégias.
       3- Na conta real as vezes é colocada a quantidade correta de contratos e as vezes ocorre o bug.
       4- Se utilizar o EA por muito tempo o bug vai ocorrendo sempre diminuindo os contratos até que uma hora reste apenas 1 contrato.

Segue código da OnTradeTransaction (O restante do código do EA não tem nenhuma ligação com essa função)


//+-------------------------------------------------------------------------+
//| RECOLOCA A ORDEM EM CASO DE OPERAÇÃO COM LUCRO    |
//+-------------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
{
//--- get transaction type as enumeration value 
   ENUM_TRADE_TRANSACTION_TYPE type = trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD && closePosition==false) // Se closePosition == True, não precisa abrir novas ordens 
     {
      long     deal_entry        =0;
      string   deal_symbol       ="";
      long     deal_type         =0;
      double   deal_volume       =0;
      double   deal_price        =0;
      
      if(HistoryDealSelect(trans.deal))
        {
         deal_entry  = HistoryDealGetInteger(trans.deal,DEAL_ENTRY);         
         deal_symbol = HistoryDealGetString (trans.deal,DEAL_SYMBOL);
         deal_type   = HistoryDealGetInteger(trans.deal,DEAL_TYPE);
         deal_volume = HistoryDealGetDouble (trans.deal,DEAL_VOLUME);
         deal_price  = HistoryDealGetDouble (trans.deal,DEAL_PRICE);         
        }
      else 
         return;
         
          
       if(deal_symbol==Symbol())
       {                

         //RECOLOCAÇÃO DE ORDENS ACIMA DA ABERTURA                      
            if(preco.last>=value_open)
            {
               //-- Recoloca a ordem de venda 
               if(deal_entry==DEAL_ENTRY_OUT && deal_type==DEAL_TYPE_BUY)
               {
                 trade.SellLimit(deal_volume,deal_price+take*Point(),_Symbol,0,0,0,0,"Venda Recolocada");       
                 Print("■ Venda Recolocada - Contratos = ", deal_volume, " - Preço ",deal_price+take*Point());
               }
                     //Recoloca Saida da Venda
                     if(deal_entry==DEAL_ENTRY_IN && deal_type==DEAL_TYPE_SELL)
                      {
                       trade.BuyLimit(deal_volume,deal_price-take*Point(),_Symbol,0,0,0,0,"Saida da Venda");    // Saida da Venda 
                       Print("■ Gain da venda colocado no preço : ",deal_price-take*Point());
                      }                                             
            }
         //RECOLOCAÇÃO DE ORDENS ABAIXO DA ABERTURA            
            if(preco.last<value_open)
            {        
               //-- Recolca a ordem de compra
               if(deal_entry==DEAL_ENTRY_OUT && deal_type==DEAL_TYPE_SELL)
               {
                 trade.BuyLimit(deal_volume,deal_price-take*Point(),_Symbol,0,0,0,0,"Compra Recolocada");
                 Print("■ Compra Recolocada - Contratos = ",deal_volume, " - Preço ",deal_price-take*Point());
               } 
                     //Recoloca Saida da Compra
                    if(deal_entry==DEAL_ENTRY_IN && deal_type==DEAL_TYPE_BUY)
                      {               
                       trade.SellLimit(deal_volume,deal_price+take*Point(),_Symbol,0,0,0,0,"Saida da Compra");   // Saida da Compra
                       Print("■ Gain da compra colocado no preço : ",deal_price+take*Point());
                      }
            }
      }
}

Se alguém puder me ajudar e precisarem de mais informações eu agradeço.
Documentação sobre MQL5: Elementos Básicos da Linguagem / Funções / Funções de Manipulação de Evento
Documentação sobre MQL5: Elementos Básicos da Linguagem / Funções / Funções de Manipulação de Evento
  • www.mql5.com
Funções de Manipulação de Evento - Funções - Elementos Básicos da Linguagem - Referência MQL5 - Referência sobre algorítimo/automatização de negociação na linguagem para MetaTrader 5
 
Tiago Silvano Souza Felipe:
Olá, desenvolvi um EA (conta Netting) que utiliza ordens pendentes SellLimit e BuyLimit no lugar do TakeProfit nativos do MT5. O motivo disso foi evitar as derrapagens que ocorrem quando utilizamos o TP e SP do MT5, uma vez que eles encerram as posições a mercado e não com ordens no book.

O EA coloca Ordens BuyLimit e SellLimit no gráfico para entrada na operação e quando uma dessas ordens é executada ele coloca uma ordem inversa (BuyLimit ou SellLimit) para sair da operação, funcionando como um TakeProfit. Quando essa ordem de saida é executada ele recoloca a ordem de entrada no mesmo lugar de antes e com mesmo volume de contratos.

Acontece que utilizei a função OnTradeTransaction para essa manipulação das ordens e ocorre tudo corretamente em conta DEMO e em conta REAL com 1 contrato de volume.

O problema ocorre quando tento utilizar mais de 1 contrato de volume na conta REAL. O EA executa uma ordem de entrada com 4 contratos e as vezes coloca uma ordem de saida com apenas 3 contratos, ou as vezes ele coloca a saida com a quantidade de contratos correta, mas quando ela é executada a recolocação da ordem de entrada é que acaba tendo menos contratos.

Minha desconfiança é que possa existir algum erro na forma que estou utilizando o enum DEAL_VOLUME, entretando eu não consegui identificar qual seria o erro de lógica.

Pontos importantes: 1- O bug sempre é com uma quantidade menor de contratos, nunca ocorreu de colocar mais contratos.
       2- O bug não ocorre em conta Demo e no Testador de Estratégias.
       3- Na conta real as vezes é colocada a quantidade correta de contratos e as vezes ocorre o bug.
       4- Se utilizar o EA por muito tempo o bug vai ocorrendo sempre diminuindo os contratos até que uma hora reste apenas 1 contrato.

Segue código da OnTradeTransaction (O restante do código do EA não tem nenhuma ligação com essa função)



Se alguém puder me ajudar e precisarem de mais informações eu agradeço.

Como voce controla a variável close_position? Pense so mesmo que venda a mercado 3 no mini indice com a liquidez que ele tem pode ocorrer de 1 a 3 negócios nessa sua ordem instanteneamente e isso refleteria em 3 chamadas a essa função. Coisa que em demo ou no testador nao ocorre.

 
Ricardo Rodrigues Lucca #:

Como voce controla a variável close_position? Pense so mesmo que venda a mercado 3 no mini indice com a liquidez que ele tem pode ocorrer de 1 a 3 negócios nessa sua ordem instanteneamente e isso refleteria em 3 chamadas a essa função. Coisa que em demo ou no testador nao ocorre.

Olá, primeiramente muito obrigado pela atenção e ajuda. A variável Close_position é controlada quando há mudança do operacional pelo painel que criei e também quando o robô encerra pelo stoploss financeiro ou limite de horário. Não será esse o motivo do bug, por isso não dei destaque na solicitação da ajuda.

 
Tiago Silvano Souza Felipe #:

Olá, primeiramente muito obrigado pela atenção e ajuda. A variável Close_position é controlada quando há mudança do operacional pelo painel que criei e também quando o robô encerra pelo stoploss financeiro ou limite de horário. Não será esse o motivo do bug, por isso não dei destaque na solicitação da ajuda.

Poderia so pra tornar o entendimento mais claro falar dessas 3 outras variaveis externas: preco.last, value_open e o take?

Por essa porção de código parece que seria uma especie de grid que tu iria comprando quando ta caindo em relação ao last e vendendo quando ta acima, pensou em nesses ifs do preco.last colocar uma mensagem, para verificar que não houve a condição ou alguma especie de "passei por aqui" na função? Outro ponto que as vezes pode ter havido DEAL_ENTRY_INOUT, mas dai voce teria percebido acredito que o problema so ocorreria quando virá a mão... Tem como fazer um foreach no historico e verificar que nao houve esse tipo de deal?