Erro: [failed modify] (take profit, robô de GAP)

 

Bom dia/boa tarde/boa noite senhoras e senhores.


Gostaria de saber se algum de vocês poderia me ajudar com um de meus bebês. Trata-se de um robô de GAP para míni-índice (atual WINV22), e minha dúvida é em referência ao seguinte ao erro "failed modify, sl: 0, tp: 0 -> sl: x , tp: y [invalid stops]", como vocês podem observar na imagem log1, anexada neste tópico. Algumas vezes ele executa o Position Modify, e algumas não, marquei essas linhas de mensagem como azul na imagem. Engraçado que: ao gerar backtests no WIN$, ele roda normalmente como desejo, quando passo para o ao vivo em conta simulador no WINV22 ou até mesmo nos backtests, recebo essa mensagem de erro.


Este EA identifica as 9:05 o fechamento e abertura de mercado, analisando se a diferença de pontos entre eles é maior que a desejada para o GAP. Para calcular o take profit, utilizo as highs/lows das velas de fechamento e abertura. Após o cálculo, divido por 2 e possuo o resultado desejado do alvo.


NÃO TENHO CERTEZA SE O ERRO É ISSO MESMO: Percebi que isso ocorria quando em algumas dessas divisões, um dos valores das high/lows era par, e o outro ímpar, e, ao dividir por 2, retornava o valor indesejado de 0.5 a mais, busquei arredonda-lo para zero com os códigos MathRound/Mathfloor para respeitar o _Digits do WINV (.0). Como podem observar nas imagens log2 e log3, o valor foi arredondado, porém o erro continuou persistindo. Já nas divisões com ambas variáveis pares ou impares, como resultado da soma dos últimos números sendo sempre par, sua divisão por 2 sempre será um número inteiro. Rodei backtests maiores e percebi que realmente esse erro não acontecia quando as variáveis eram iguais.


Está é a linha de código que utilizo para efetuar o cálculo do take profit (declarada como uma função no global, dentro de onTick): 

//=================TAKE PROFIT E STOPP LOSS=============================
 void addTakeStop (double novoSL, double novoTP){
 
 for(int i = PositionsTotal() -1; i>=0; i--){
 string symbol = PositionGetSymbol(i);
 
 if(symbol == Symbol()){
 
 ulong ticket = PositionGetInteger(POSITION_TICKET);
 double precoEntrada = PositionGetDouble(POSITION_PRICE_OPEN);
 
 
 if(rates[2].close != rates[1].open){

  double calculo_gap = rates[2].close - rates[1].open;
    
  if(calculo_gap > Tamanho_GAP){
  
        double gap = rates[2].high - rates[1].low;
        
        if(gap > 0 && gap > Tamanho_GAP){
        
        //Print("O valor do GAP é de: ", gap);
        
        double TPCompra = gap/ 2; 
        
        //Print("O valor do TP (gap/2) é: ", TPCompra);
       
        double arredonda_TP = MathFloor(TPCompra);
        
        //Print("O valor do TP arredondado é: ", arredonda_TP);
   
              
 if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){
 
 
 novoSL = NormalizeDouble(precoEntrada - (Stop_Loss * _Point), _Digits);
 novoTP = NormalizeDouble(precoEntrada + (arredonda_TP * _Point), _Digits);

  Trade.PositionModify(ticket, novoSL, novoTP);
  
   //Print("O valor final do TP é: ", novoTP);
   
   }  
  }
 }
     else if(calculo_gap < (Tamanho_GAP * -1)){
   
        double gap = rates[2].low - rates[1].high;
        
        if(gap < 0 && gap < Tamanho_GAP * -1){
        
        //Print("O valor do GAP é de: ", gap);
        
        double NovoTPGap = gap / 2;
        
        //Print("O valor do TP (gap/2) é: ", (NovoTPGap));
       
        double arredonda_TP = MathFloor(NovoTPGap);
        
        //Print("O valor do TP arredondado é: ", arredonda_TP);
        
        double inversaoTP = NovoTPGap * -1;
        
     
  if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){

 novoSL = NormalizeDouble(precoEntrada + (Stop_Loss * _Point), _Digits);
 novoTP = NormalizeDouble(precoEntrada - (inversaoTP * _Point), _Digits);

   Trade.PositionModify(ticket, novoSL, novoTP);
   
  //Print("O valor final do TP é: ", novoTP);
 
         }
       }
    }
 }
     }
        }
           }


Percebi também que na mensagem de erro possui uma diferença no valor da posição da compra/venda (porém não sei o que fazer com tal informação):


Quando acerta -> "Position Modified [#n sell 2 WINV22 POSIÇÃO sl: x, tp: y".

Quando erra -> "Failed Modify #n sell 2 WINV22 sl: 0, tp: 0 -> sl: x, tp: y [invalid stops]". Detalhe, mesmo na mensagem de erro, o valor calculado do take profit e do stop loss estão certos.


Espero que algum ser consiga iluminar meus caminhos com vossas ideias/sugestões, e que possa me mostrar aquilo que não estou vendo de errado, para que de fato possa resolver esse problema. Desde já, agradeço a atenção e o carinho caso tenha lido todo este tópico.


Um grande abraço,

Christian Alves.

Arquivos anexados:
log1.jpg  457 kb
log2.jpg  369 kb
log3.jpg  392 kb
 
Christian Alves:

. . .


Boa noite Christian!!


Utilize a função NormalizePrice(), abaixo, em vez de NormalizeDouble() pra ver se resolve...

//+--------------------------------------------------------------------------------------------------------------------+
//| This function normalizes and adjusts the price to the TICK SIZE                                                    |
//+--------------------------------------------------------------------------------------------------------------------+
double NormalizePrice(double price)
  {
//--- Get the minimal price change
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

//--- Return the price normalized
   if(tick_size == 0.0)
     {
      return(NormalizeDouble(price, _Digits));
     }

//--- Return the price normalized and adjusted to the TICK SIZE
   return(NormalizeDouble(MathRound(price / tick_size) * tick_size, _Digits));
  }
 
Vinicius de Oliveira #:


Boa noite Christian!!


Utilize a função NormalizePrice(), abaixo, em vez de NormalizeDouble() pra ver se resolve...

Boa noite! Muito obrigado pela ajuda meu irmão, acabei conseguindo alcançar meu objetivo através do código MathMod.


double divisao_compra = gap/ 2;   
        
double diferenca_compra = MathMod(divisao_compra, 5); 


Todas as vezes que a variável retornava um valor diferente de um divisível de 5, ele arredondava-o. 


Agradeço pela atenção, grande abraço!

 
Christian Alves #:

Boa noite! Muito obrigado pela ajuda meu irmão, acabei conseguindo alcançar meu objetivo através do código MathMod.



Todas as vezes que a variável retornava um valor diferente de um divisível de 5, ele arredondava-o. 


Agradeço pela atenção, grande abraço!


Abraço, bons trades!! 👍