Erro ao colocar stop loss

 

Estou tendo um problema bem estranho ao tentar a colocação de um stop loss "hard", como medida de segurança em meus EAs, que operam com stop loss "soft", enviado pelo código como market order.

Criei um EA super simplificado (e idiota, obviamente não é para ser usado em operações reais) para possibilitar a verificação do meu problema. Ia postar tudo no fórum internacional, mas pensei seria mais difícil receber ajuda por lá.

Executando este EA com Mini Índice (WINJ23), em conta hedging, para, por exemplo, a sexta-feira passada, 03/03/2023, ele executa as ordens de compra e venda corretamente em várias tentativas.

Se faço o mesmo para a quinta feira, 02/03/2023, ele, ou falha já na primeira tentativa, ou então processa a primeira tentativa corretamente e falha em todas as tentativas seguintes, fechando a Position que acabou de ser aberta, sabe-se lá por quê.

O código é bem simples e está comentado, então creio que será fácil testá-lo.

Agradeço muito se alguém puder me ajudar.

//+------------------------------------------------------------------+
//|                                           PositionsTotalZero.mq5 |
//|                            Trading Brazil IBovespa Index Futures |
//+------------------------------------------------------------------+

//--- Includes
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
//---

//--- Classes Instantiation
CTrade         ciTrade;
CPositionInfo  ciPosition;
//---

ENUM_POSITION_TYPE enPositionType;

int prMagicNo = 100;

datetime FirstTime = 0;
datetime CurrentTime = 0;
bool PositionOpened = false;
bool PositionClosed = false;
double OrderPrice = 0;
double ProtectStoploss = 0;
bool OrderPlaced = false;
int OrderReturnCode = 0;
string OrderReturnDescription = "";
string PositionSymbol = "";
int PositionMagicNo = 0;
ulong PositionTicket = 0;
int PositionCount = 0;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
   ciTrade.SetExpertMagicNumber(prMagicNo);
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   if (FirstTime == 0)
   {
      FirstTime = TimeCurrent();
   }
   
   CurrentTime = TimeCurrent();

   if(TimeToString(CurrentTime, TIME_MINUTES) > TimeToString(FirstTime + 1800, TIME_MINUTES)
   && !PositionOpened)
   {
      SendBuyOrder();
      PositionOpened = true;
   }

   if(TimeToString(CurrentTime, TIME_MINUTES) > TimeToString(FirstTime + 7200, TIME_MINUTES)
   && !PositionClosed)
   {
      CloseBuyOrder();
      PositionClosed = true;
   }
   
   int PositionsQt = PositionsTotal();
   Comment ("PositionsTotal = " + PositionsQt);
}

void SendBuyOrder()
{
   OrderReturnCode = 0;
   OrderReturnDescription = "";
   OrderPlaced = false;
   
   if (!OrderPlaced)
   {
      for(int i=PositionsTotal()-1; i>=0; i--)
      {
         if (ciPosition.SelectByIndex(i))
         {
            PositionSymbol = ciPosition.Symbol();
            PositionMagicNo = ciPosition.Magic();
            enPositionType = ciPosition.Type();
            PositionTicket = ciPosition.Ticket();

            if (PositionSymbol == _Symbol && PositionMagicNo == prMagicNo)
            {
               PositionCount += 1;
            }
         }
      }   

      if(PositionCount == 0)
      {
         OrderPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         
         //1st option
         //No stop loss, all is ok, Position will be closed on scheduled CloseBuyOrder()
         //ciTrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,OrderPrice,NULL,NULL,NULL);
         
         //2nd option
         //With stop loss value, scheduled CloseBuyOrder() sometimes will not be executed as PositionsTotal() will be zero on next tick after PositionOpen (why???) 
         ProtectStoploss = SymbolInfoDouble(_Symbol, SYMBOL_ASK)-800; //Or any value well below OrderPrice
         ciTrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,OrderPrice,ProtectStoploss,NULL,NULL);
         
         OrderReturnCode = ciTrade.ResultRetcode();
         OrderReturnDescription = ciTrade.ResultRetcodeDescription();
      }

      if (OrderReturnCode == TRADE_RETCODE_PLACED || OrderReturnCode == TRADE_RETCODE_DONE)
      {
         OrderPlaced = true;
      }
   }   
}

void CloseBuyOrder()
{
   OrderReturnCode = 0;
   OrderReturnDescription = "";
   OrderPlaced = false;
   
   if (!OrderPlaced )
   {
      for(int i=PositionsTotal()-1; i>=0; i--)
      {
         if (ciPosition.SelectByIndex(i))
         {
            PositionSymbol = ciPosition.Symbol();
            PositionMagicNo = ciPosition.Magic();
            enPositionType = ciPosition.Type();
            PositionTicket = ciPosition.Ticket();

            if (PositionSymbol == _Symbol && PositionMagicNo == prMagicNo)
            {
               ciTrade.PositionClose(PositionTicket);
               OrderReturnCode = ciTrade.ResultRetcode();
               OrderReturnDescription = ciTrade.ResultRetcodeDescription();
            }
         }
      }   

      if (OrderReturnCode == TRADE_RETCODE_PLACED || OrderReturnCode == TRADE_RETCODE_DONE)
      {
         OrderPlaced = true;
      }
   }
}
//+------------------------------------------------------------------+
 
IvanBr:

Estou tendo um problema bem estranho ao tentar a colocação de um stop loss "hard", como medida de segurança em meus EAs, que operam com stop loss "soft", enviado pelo código como market order.

Criei um EA super simplificado (e idiota, obviamente não é para ser usado em operações reais) para possibilitar a verificação do meu problema. Ia postar tudo no fórum internacional, mas pensei seria mais difícil receber ajuda por lá.

Executando este EA com Mini Índice (WINJ23), em conta hedging, para, por exemplo, a sexta-feira passada, 03/03/2023, ele executa as ordens de compra e venda corretamente em várias tentativas.

Se faço o mesmo para a quinta feira, 02/03/2023, ele, ou falha já na primeira tentativa, ou então processa a primeira tentativa corretamente e falha em todas as tentativas seguintes, fechando a Position que acabou de ser aberta, sabe-se lá por quê.

O código é bem simples e está comentado, então creio que será fácil testá-lo.

Agradeço muito se alguém puder me ajudar.

Stop e preço não estão normalizados. Voce precisa normalizar eles. Eu normalizo até o ask/bid, mas se quiser so normalizar o stop já provavelmente some seu erro.

 

Obrigado pela sugestão, Ricardo, mas o problema continua mesmo com os valores normalizados com 0, 1 ou 2 dígitos a Posição continua sendo zerada na segunda tentativa:

OrderPrice = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK),0);    //ou ,1) ou ,2)

ProtectStoploss = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK)-800,0);      //ou ,1) ou ,2)

Tentei também, sem sucesso:

int OrderPrice = 0;

int ProtectStoploss = 0;

OrderPrice = int(SymbolInfoDouble(_Symbol, SYMBOL_ASK));

ProtectStoploss = int(SymbolInfoDouble(_Symbol, SYMBOL_ASK)-800);

Vou tentar amanhã, em operação real ( só 1 contrato :) ), com os valores normalizados, vamos ver o que acontece.

 
IvanBr #:

Obrigado pela sugestão, Ricardo, mas o problema continua mesmo com os valores normalizados com 0, 1 ou 2 dígitos a Posição continua sendo zerada na segunda tentativa:

OrderPrice = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK),0);    //ou ,1) ou ,2)

ProtectStoploss = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK)-800,0);      //ou ,1) ou ,2)

Tentei também, sem sucesso:

int OrderPrice = 0;

int ProtectStoploss = 0;

OrderPrice = int(SymbolInfoDouble(_Symbol, SYMBOL_ASK));

ProtectStoploss = int(SymbolInfoDouble(_Symbol, SYMBOL_ASK)-800);

Vou tentar amanhã, em operação real ( só 1 contrato :) ), com os valores normalizados, vamos ver o que acontece.

Não é isso, olha o codigo do CSymbol que tem o normalizePrice. Quando falei normalizado seria normalizado ao tick, por exemplo tu recupera o ((int)(preço / tick_size) * tick_size)