OrderSend error 10016 invalid stops

 

Fala pessoal, bom dia.

Defini como trailing stop a média móvel. Logo, quando realizo o teste no Backtest o stop movimenta conforme a média definida.

Contudo, quando vou para a conta demo recebo a seguinte mensagem: "OrderSend error 10016 invalid stops". Já alterei período, o shift, o modelo da média e continua aconcendo este problema.

Olhei o stop mínimo permitido pela corretora e os valores adotados pela média estão conforme estipulado. Segue abaixo o código:

// Tralling Stop Moving Average
   if(UseTrailingStop==true && PositionTypeTito(_Symbol)!=-1 && Type=="moving")
   {if(PositionTypeTito() == POSITION_TYPE_BUY)
     {TrailingStopPrice(_Symbol,ma20[1],MinimumProfit);}
   if(PositionTypeTito() == POSITION_TYPE_SELL)
     {TrailingStopPrice(_Symbol,ma17[1],MinimumProfit);}  

 Segue a função TrailingStopPrice()

//+------------------------------------------------------------------+
//|Tralling Stop Price                                               |
//+------------------------------------------------------------------+
bool TrailingStopPrice(string pSymbol,double pTrailPrice,int pMinProfit=0)
  {
  if(PositionSelect(pSymbol) == true && pTrailPrice > 0)
        {
           MqlTradeRequest request;
      MqlTradeResult result;
      ZeroMemory(request);
                request.action = TRADE_ACTION_SLTP;
                request.symbol = pSymbol;
                
                long posType = PositionGetInteger(POSITION_TYPE);
                double currentStop = PositionGetDouble(POSITION_SL);
                double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                
                double point = SymbolInfoDouble(pSymbol,SYMBOL_POINT);
                int digits = (int)SymbolInfoInteger(pSymbol,SYMBOL_DIGITS);
                
        
                double minProfit = pMinProfit * point;
                                
                currentStop = NormalizeDouble(currentStop,digits);
                pTrailPrice = NormalizeDouble(pTrailPrice,digits);
                
                double currentProfit;
                btp=openPrice+TP*Point();
      btp=NormalizeDouble(btp,Digits());
      stp=openPrice-TP*Point();
      stp=NormalizeDouble(stp,Digits());
                
                int retryCount = 0;
                int checkRes = 0;
                
                double bid = 0, ask = 0;
                
                do 
                {
                        if(posType == POSITION_TYPE_BUY)
                        {
                                bid = SymbolInfoDouble(pSymbol,SYMBOL_BID);
                                currentProfit = bid - openPrice;
                                if(pTrailPrice > currentStop && currentProfit >= minProfit) 
                                {
                                        request.sl = pTrailPrice;
                                        request.tp = btp;
                                        bool sent = OrderSend(request,result);
                                }
                                else return(false);
                        }
                        else if(posType == POSITION_TYPE_SELL)
                        {
                                ask = SymbolInfoDouble(pSymbol,SYMBOL_ASK);
                                currentProfit = openPrice - ask;
                                if((pTrailPrice < currentStop  || currentStop == 0) && currentProfit >= minProfit)
                                {
                                        request.sl = pTrailPrice;
                                        request.tp = stp;
                                        bool sent = OrderSend(request,result);
                                }
                                else return(false);
                        }
                        
                        checkRes = CheckReturnCode(result.retcode);
                
                        if(checkRes == CHECK_RETCODE_OK) break;
                        else if(checkRes == CHECK_RETCODE_ERROR)
                        {
                                string errDesc = TradeServerReturnCodeDescription(result.retcode);
                                Alert("Trailing stop: Error ",result.retcode," - ",errDesc);
                                break;
                        }
                        else
                        {
                                Print("Server error detected, retrying...");
                                Sleep(RETRY_DELAY);
                                retryCount++;
                        }
                }
                while(retryCount < MAX_RETRIES);
        
                if(retryCount >= MAX_RETRIES)
                {
                        string errDesc = TradeServerReturnCodeDescription(result.retcode);
                        Alert("Max retries exceeded: Error ",result.retcode," - ",errDesc);
                }
                
                string errDesc = TradeServerReturnCodeDescription(result.retcode);
                Print("Trailing stop: ",result.retcode," - ",errDesc,", Old SL: ",currentStop,", New SL: ",request.sl,", Bid: ",bid,", Ask: ",ask,", Stop Level: ",SymbolInfoInteger(pSymbol,SYMBOL_TRADE_STOPS_LEVEL));
                
                if(checkRes == CHECK_RETCODE_OK) return(true);
                else return(false);
        }
        else return(false);
} 

Se alguém puder me ajudar, ficaria muito grato.

 
tito.vinicius:


Bom dia,

Vou dar uma sugestão. Para normalizar os preços de um ativo para tickSize correto faça como mostrado abaixo.

SymbolInfoInteger(_Symbol,SYMBOL_DIGITS,digits);
SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_SIZE,tickSize);

preco=NormalizeDouble(MathRound(preco/tickSize)*tickSize,digits);

 
Rogerio Giannetti Torres:

Bom dia,

Vou dar uma sugestão. Para normalizar os preços de um ativo para tickSize correto faça como mostrado abaixo.

Obrigado pela ajuda Rogério. Funcionou perfeitamente.

Mais uma vez muito obrigado.

 
tito.vinicius:

Obrigado pela ajuda Rogério. Funcionou perfeitamente.

Mais uma vez muito obrigado.

   Oi, 


   Aproveitando o ensejo, o que seria esse tickSize eu não entendi? Por que tudo isso pra enviar o preço?

 
Nelson Silva:

   Oi, 


   Aproveitando o ensejo, o que seria esse tickSize eu não entendi? Por que tudo isso pra enviar o preço?

Bom dia Nelson

o tamanho do tick, tradução literal para tick size, define como o preço de um instrumento se movimenta. Exemplos:

Cotação de ações o tick size é 0,01 então os preços para ações se movimentam de 0,01 em 0,01 centavos:  12,21 -> 12,22 - 12,23

Cotação do DOL/BRL na B3 o tick size é 0,50 então os preços se movimentam de 0,50 em 0,50 centavos: 4 090,00 --> 4090,50 --> 4091,00

Cotação do contrato de futuros INDICE o tick size é de 5 pontos então os preços se movem de 5 em 5 pontos  103100 --> 103105 --> 103010.

Cotação do MINI S&P 500 o tick size é de 0,25 então os preços se movem de 0,25 de 0,25 centavos: 2992,00 --> 2992,25 --> 2992,50.

Só podemos emitir ordens com os valores de preço com tick size correto , isso vale para preço da ordem, preço do stop loss e preço do take profit.

At.te

Rogério.

 
Rogerio Giannetti Torres:

Bom dia Nelson

o tamanho do tick, tradução literal para tick size, define como o preço de um instrumento se movimenta. Exemplos:

Cotação de ações o tick size é 0,01 então os preços para ações se movimentam de 0,01 em 0,01 centavos:  12,21 -> 12,22 - 12,23

Cotação do DOL/BRL na B3 o tick size é 0,50 então os preços se movimentam de 0,50 em 0,50 centavos: 4 090,00 --> 4090,50 --> 4091,00

Cotação do contrato de futuros INDICE o tick size é de 5 pontos então os preços se movem de 5 em 5 pontos  103100 --> 103105 --> 103010.

Cotação do MINI S&P 500 o tick size é de 0,25 então os preços se movem de 0,25 de 0,25 centavos: 2992,00 --> 2992,25 --> 2992,50.

Só podemos emitir ordens com os valores de preço com tick size correto , isso vale para preço da ordem, preço do stop loss e preço do take profit.

At.te

Rogério.

   Vlw, Rogério!

   Ainda não precisei usar essa opção nos Eas que desenvolvi, maioria no índice.

   Vou verificar isso aí pra questões de compatibilidade futuras.

 
Nelson Silva:

   Vlw, Rogério!

   Ainda não precisei usar essa opção nos Eas que desenvolvi, maioria no índice.

   Vou verificar isso aí pra questões de compatibilidade futuras.

Fala Nelson, blz?


E depois da dica do Rogério, daí me dei conta como faz sentido a lógica explicada por ele. Como o gatilho de compra e venda do meu EA era média móveis, os valores resultantes das médias não eram redondos conforme o Tick Size do DOL/BRL ( Cotação do DOL/BRL na B3 o tick size é 0,50 então os preços se movimentam de 0,50 em 0,50 centavos: 4 090,00 --> 4090,50 --> 4091,00). Logo, o preço do meu trailing stop não condizia com tick size do ativo. DAndo o erro 10016. Talvez ainda não aconteceu contigo pq o vc deve estar usando o preço como gatilho de compra e venda.

 
tito.vinicius:

Fala Nelson, blz?


E depois da dica do Rogério, daí me dei conta como faz sentido a lógica explicada por ele. Como o gatilho de compra e venda do meu EA era média móveis, os valores resultantes das médias não eram redondos conforme o Tick Size do DOL/BRL ( Cotação do DOL/BRL na B3 o tick size é 0,50 então os preços se movimentam de 0,50 em 0,50 centavos: 4 090,00 --> 4090,50 --> 4091,00). Logo, o preço do meu trailing stop não condizia com tick size do ativo. DAndo o erro 10016. Talvez ainda não aconteceu contigo pq o vc deve estar usando o preço como gatilho de compra e venda.

     Realmente,

    

     Eu vou construir um trailiing pela MédiaMóvel e simular essa situação, interessante, o trailing que eu to usando nos Eas é somente com passo.

Razão: