Conta real, envio de 2 ordens quando executado [Resolvido]

Para adicionar comentários, por favor Faça o login ou registrar
maronezzi
43
maronezzi  

Caros,

Criei um script de negociação automatizado, quando executo ele em conta demo funciona normal, mas quando executo na conta real para cada comando de BUY ou SELL é executado duas vezes.

Segue o código de Buy como exemplo:

        if (OpenBuyOrder() == 0)
               {
                  double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)];
                  double price;  
                  price        = high[rates_total1-2]; // price for opening
                  price = NormalizeDouble(price/5,0) * 5;
                  
                  MqlTradeRequest request={0};
                  MqlTradeResult  result={0};
                  
                  request.action   = TRADE_ACTION_PENDING;                            
                  request.symbol   = Symbol();                                         
                  request.volume   = volumeOp;                                        
   
                  request.magic    = EXPERT_MAGIC_BUY;                                 
                  double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);               
                  int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);               
                  
                  request.type = ORDER_TYPE_BUY_STOP;                                
                  request.type_filling =        ORDER_FILLING_RETURN;
                  request.type_time    = ORDER_TIME_DAY;
                  request.expiration = ORDER_TIME_GTC;
                  request.sl = SL_buy;
                  request.tp = NormalizeDouble((high[rates_total1-2] + tpMax)/5,0) * 5;
      
                  request.price = NormalizeDouble(price,digits);                      
                  
                  //--- send the request
                  if(!OrderSend(request,result))
                     PrintFormat("OrderSend error %d",GetLastError());                 
                  //--- information about the operation
                  PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
                  Sleep(5000);
                  ZeroMemory(request);
                  ZeroMemory(result);
                  candleOperado = candleCounter;
                  }
               }





Agradeço a ajuda.

Trader_Patinhas
1166
Trader_Patinhas  
maronezzi:

Caros,

Criei um script de negociação automatizado, quando executo ele em conta demo funciona normal, mas quando executo na conta real para cada comando de BUY ou SELL é executado duas vezes.

Segue o código de Buy como exemplo:





Agradeço a ajuda.

@maronezzi

Isoladamente, este trecho de código que vc postou com certeza só vai enviar a ordem 1 vez. O que deve estar acontecendo é que esse trecho está sendo executado mais de 1 vez. Teria que ver o restante do código pra entender por que.

Vc relata que isso acontece na conta real, mas não na conta demo. Isso já nos dá uma boa pista, pois talvez o problema esteja relacionado ao tempo que leva entre o envio da ordem por meio do comando OrderSend() e essa ordem ser recebida e confirmada pela bolsa e aparecer listada quando você consultar os dados do terminal usando OrdersTotal(), OrderSelect(), etc.

Na conta real, esse processo leva alguns centésimos ou décimos de segundo, enquanto que na conta demo esse processo será instantâneo, pois ele não envia de verdade a ordem pra bolsa, apenas altera o seu ambiente (OrdersTotal(), OrderSelect(), etc.) como se a ordem tivesse sido enviada.

Suponhamos, por exemplo, que no evento OnTick() vc tenha uma lógica que envia uma nova ordem sempre que OrdersTotal() for igual a zero. Nesse caso, poderia acontecer o seguinte na conta real: vc envia uma ordem num evento Ontick() e ela leva alguns décimos de segundo para ser registrada, de modo que, se um segundo evento OnTick() chegar nesse meio tempo, OrdersTotal() ainda estará retornando zero e nesse caso a lógica de processamento do evento Ontick() vai enviar a ordem pela segunda vez.

Já na conta demo isso não aconteceria, pois, como o servidor demo não envia as ordens de verdade, apenas atualiza o ambiente como se a ordem tivesse sido enviada, OrdersTotal() já passa a retornar 1 assim que o comando OrderSend() é executado, antes mesmo de sair do primeiro evento OnTick().

Não sei como é a sua lógica de processamento. Teria que ver o restante do seu código. Verifique se a lógica de processamento que você usa para enviar as ordens tem o tipo de vulnerabilidade que descrevi acima.

Rogerio Giannetti Torres
3257
Rogerio Giannetti Torres  

Olá Maronezzi,

muito estranho mesmo, tem um comando Sleep(5000) e a hora das mensagens do "SEND"  estão no mesmo instante!  

Tem também um "}" não indentado no trecho postado, esse trecho postado você alterou antes de enviar?

At.te

Rogério

Trader_Patinhas
1166
Trader_Patinhas  
Rogerio Giannetti Torres:

Olá Maronezzi,

muito estranho mesmo, tem um comando Sleep(5000) e a hora das mensagens do "SEND"  estão no mesmo instante!  

Tem também um "}" não indentado no trecho postado, esse trecho postado você alterou antes de enviar?

At.te

Rogério

@Rogerio Giannetti Torres,

Eu não tinha reparado o Sleep(5000). Muito estranho mesmo!!!

Isso derruba completamente a minha hipótese, pois, se o código estivesse sendo executado duas vezes seguidas, deveria haver uma distância de 5 segundos entre as 2 ordens. 

@maronezzi, esse Sleep(5000) já estava inserido no código quando o problema aconteceu? Ou vc colocou depois?

Uma outra hipótese: será que você estava com 2 instâncias do mesmo robô operando simultaneamente no WINQ18 em 2 janelas distintas? Isso já aconteceu comigo (em conta demo, felizmente).

Vc consegue reproduzir o problema ? 

maronezzi
43
maronezzi  
Trader_Patinhas:

@Rogerio Giannetti Torres,

Eu não tinha reparado o Sleep(5000). Muito estranho mesmo!!!

Isso derruba completamente a minha hipótese, pois, se o código estivesse sendo executado duas vezes seguidas, deveria haver uma distância de 5 segundos entre as 2 ordens. 

@maronezzi, esse Sleep(5000) já estava inserido no código quando o problema aconteceu? Ou vc colocou depois?

Uma outra hipótese: será que você estava com 2 instâncias do mesmo robô operando simultaneamente no WINQ18 em 2 janelas distintas? Isso já aconteceu comigo (em conta demo, felizmente).

Vc consegue reproduzir o problema ? 

@Rogerio Giannetti Torres e @Trader_Patinhas, obrigado pelas prontas respostas.

Respondendo as perguntas, esse código é o que esta rodando, o erro é repetido toda as vezes que entra a opção de Buy ou Sell, e quando executa o PositionClose() ele fecha abre e fecha as posições.

Eu postei a pergunta, porque mesmo com o Sleep(5000) o erro continua e o tempo da operação como vocês observaram não obedece ele.


O meu script roda em uma VPS, mas na primeira vez que rodei a latência estava bem baixa, na casa de 56ms. Também rodei o backtest com vários valores de latência, mas o erro não acontece.

Eu tenho rodado a conta rela da XP e uso as contas demo da Clear para os teste, portanto não vejo dois scprits rodando em paralelo.

Antes de rodar na conta Real, deixei por vários dias rodando em conta Demo, mas o erro não acontece.

Vou postar o código, mas não sou um programador muito experiente, portanto podem ter coisas que poderiam ser otimizadas, com o tempo vou corrigindo elas.


#include <Trade\Trade.mqh>
CTrade trade;
//+------------------------------------------------+
//|  Declaration of constants                      |
//+------------------------------------------------+

#define EXPERT_MAGIC_BUY 123456  // MagicNumber of the expert
#define EXPERT_MAGIC_SELL 654321  // MagicNumber of the expert
#define rates_total Bars(_Symbol, ENUM_TIMEFRAMES(_Period) )

input double volumeOp = 5;


//+------------------------------------------------+

//---- declaration of the integer variables for the start of data calculation
int  min_rates_total;
//---- declaration of a variable for storing the Fibo level
double level;

double high[],low[],open[],close[];
long tick_volume[], volume[];
datetime time[];
datetime timedest[];

//int rates_total;
int prev_calculated;
string compra, venda;
double tp1,tp2,tp3;
double NsLVend, NsLComp ;
double candleOperadoStop = 0;


//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum DATE_TYPE
  {
   DAILY,
   WEEKLY,
   MONTHLY
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum PRICE_TYPE
  {
   OPEN,
   CLOSE,
   HIGH,
   LOW,
   OPEN_CLOSE,
   HIGH_LOW,
   CLOSE_HIGH_LOW,
   OPEN_CLOSE_HIGH_LOW
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
datetime CreateDateTime(DATE_TYPE nReturnType=DAILY,datetime dtDay=D'2000.01.01 00:00:00',int pHour=0,int pMinute=0,int pSecond=0)
  {
   datetime    dtReturnDate;
   MqlDateTime timeStruct;

   TimeToStruct(dtDay,timeStruct);
   timeStruct.hour = pHour;
   timeStruct.min  = pMinute;
   timeStruct.sec  = pSecond;
   dtReturnDate=(StructToTime(timeStruct));

   if(nReturnType==WEEKLY)
     {
      while(timeStruct.day_of_week!=0)
        {
         dtReturnDate=(dtReturnDate-86400);
         TimeToStruct(dtReturnDate,timeStruct);
        }
     }

   if(nReturnType==MONTHLY)
     {
      timeStruct.day=1;
      dtReturnDate=(StructToTime(timeStruct));
     }

   return dtReturnDate;
  }

int OpenBuyOrder()
{
   int total=OrdersTotal();
   int count=0;
   ulong    ticket;
   double   open_price;
   double   initial_volume;
   datetime time_setup;
   string   symbol;
   string   type;
   long     order_magic;
   long     positionID;  
     for(uint i=0;i<total;i++)
     {
      //--- voltar ticket ordem por sua posição na lista
      if((ticket=OrderGetTicket(i))>0)
        {
         //--- retorna propriedades de uma Ordem
         open_price    =OrderGetDouble(ORDER_PRICE_OPEN);
         time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP);
         symbol        =OrderGetString(ORDER_SYMBOL);
         order_magic   =OrderGetInteger(ORDER_MAGIC);
         positionID    =OrderGetInteger(ORDER_POSITION_ID);
         initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL);
         type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE)));
         
         if(order_magic==EXPERT_MAGIC_BUY)
         {
            count++; 
         } 
        }
     }
return(count);
}

int OpenSellOrder()
{
   int total=OrdersTotal();
   int count=0;
   ulong    ticket;
   double   open_price;
   double   initial_volume;
   datetime time_setup;
   string   symbol;
   string   type;
   long     order_magic;
   long     positionID;  
     for(uint i=0;i<total;i++)
     {
      //--- voltar ticket ordem por sua posição na lista
      if((ticket=OrderGetTicket(i))>0)
        {
         //--- retorna propriedades de uma Ordem
         open_price    =OrderGetDouble(ORDER_PRICE_OPEN);
         time_setup    =(datetime)OrderGetInteger(ORDER_TIME_SETUP);
         symbol        =OrderGetString(ORDER_SYMBOL);
         order_magic   =OrderGetInteger(ORDER_MAGIC);
         positionID    =OrderGetInteger(ORDER_POSITION_ID);
         initial_volume=OrderGetDouble(ORDER_VOLUME_INITIAL);
         type          =EnumToString(ENUM_ORDER_TYPE(OrderGetInteger(ORDER_TYPE)));
         //--- preparar e apresentar informações sobre a ordem
         
         if(order_magic==EXPERT_MAGIC_SELL)
         {
            count++; 
         } 
        }
     }
return(count);

}

void CloseAll()
{
   CTrade trade;
   for (int i=PositionsTotal()-1;i>=0; i--)
   {
      {                
         if(!trade.PositionClose(PositionGetSymbol(i),5))
         {
            Print(PositionGetSymbol(i), "PositionClose() method failed. Return code=",trade.ResultRetcode(),
            ". Code description: ",trade.ResultRetcodeDescription());
         } else {
            Print(PositionGetSymbol(i), "PositionClose() method executed successfully. Return code=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
               Sleep(5000);
         }
      }
   }
} 

input   PRICE_TYPE          Price_Type              = CLOSE_HIGH_LOW;
input   bool                Enable_Daily            = true;
bool        Show_Daily_Value    = true;
double      VWAP_Buffer_Daily;

double      nPriceArr[];
double      nTotalTPV[];
double      nTotalVol[];
double      nSumDailyTPV = 0, nSumWeeklyTPV = 0, nSumMonthlyTPV = 0;
double      nSumDailyVol = 0, nSumWeeklyVol = 0, nSumMonthlyVol = 0;

int         nIdxDaily=0,nIdxWeekly=0,nIdxMonthly=0,nIdx=0;
bool        bIsFirstRun=true;
ENUM_TIMEFRAMES LastTimePeriod=PERIOD_MN1;
string      sDailyStr   = "";
datetime    dtLastDay=CreateDateTime(DAILY),dtLastWeek=CreateDateTime(WEEKLY),dtLastMonth=CreateDateTime(MONTHLY);

input double tpMax = 100;
input double tpMin = 100;
input double imarap = 9;
input double imalenta = 21;
input double slcomprado = 1;
input double slvendido = 1;

input   bool                ordemcompra            = true;
input   bool                ordemvenda            = true;

input string  horainicioOp = "11:00";
input string  horafimOp = "15:00";

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   double Bid=NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
   double Ask=NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);

   MqlTradeRequest request={0};
   MqlTradeResult  result={0};


   // Contador de Candles
   MqlRates priceData[];
   ArraySetAsSeries(priceData, true);
   CopyRates(_Symbol, _Period, 0, 3, priceData);
   static int candleCounter;
   static int candleAnterior;
   static datetime timeStampLastCheck;
   datetime timeStampCurrentCandle;
   timeStampCurrentCandle = priceData[0].time;
   string dateStampCurrentCandle=TimeToString(timeStampCurrentCandle,TIME_DATE);
   static string dateStampLastCheck;


   if (timeStampCurrentCandle != timeStampLastCheck)
      {
      timeStampLastCheck = timeStampCurrentCandle;
      candleCounter = candleCounter + 1;
      if (dateStampCurrentCandle != dateStampLastCheck)
         {
         dateStampLastCheck = dateStampCurrentCandle;
         candleCounter = 0;
         }
      }


   //Entrada de valores
   CopyHigh(_Symbol,_Period,0,rates_total,high);
   CopyLow(_Symbol,_Period,0,rates_total,low);
   CopyOpen(_Symbol,_Period,0,rates_total,open);
   CopyClose(_Symbol,_Period,0,rates_total,close);
   CopyTime(_Symbol,_Period,0,rates_total,time);
   CopyTickVolume(_Symbol,_Period,0,rates_total ,tick_volume);
   CopyRealVolume(_Symbol,_Period,0,rates_total ,volume);

   prev_calculated = BarsCalculated(rates_total);
//---- indexing elements in arrays as timeseries
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(time,false);
   ArraySetAsSeries(tick_volume,false);
   ArraySetAsSeries(volume,false);

//---- declarations of local variables
   static uint buycount=0,sellcount=0;
   double maxHigh3,minLow3;
   int rates_total1 = rates_total;

// invert o array low
   double lowinverse[];

   int size = ArraySize(low);
   ArrayResize(lowinverse, size);

    for ( int i=0; i<size; i++ )
    {
        lowinverse[size-i-1] = low[i];
    }

// invert o array low
   double highinverse[];

   size = ArraySize(high);
   ArrayResize(highinverse, size);

    for ( int i=0; i<size; i++ )
    {
        highinverse[size-i-1] = high[i];
    } 

//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************

double mediamovelrap[], mediamovellenta[];
int mediamovelrapdef = iMA(_Symbol, _Period, imarap, 0, MODE_EMA, PRICE_CLOSE);
int mediamovellentadef = iMA(_Symbol, _Period, imalenta, 0, MODE_SMA, PRICE_CLOSE);

ArraySetAsSeries(mediamovelrap, true);
ArraySetAsSeries(mediamovellenta, true);

CopyBuffer(mediamovelrapdef, 0, 0, 3, mediamovelrap);
CopyBuffer(mediamovellentadef, 0, 0, 3, mediamovellenta);

if (candleCounter != candleAnterior)
   {
  if(PERIOD_CURRENT!=LastTimePeriod)
     {
      bIsFirstRun=true;
      LastTimePeriod=PERIOD_CURRENT;
     }

   if(rates_total!=prev_calculated || bIsFirstRun)
     {
      ArrayResize(nPriceArr,rates_total);
      ArrayResize(nTotalTPV,rates_total);
      ArrayResize(nTotalVol,rates_total);

      if(Enable_Daily)   {nIdx = nIdxDaily;   nSumDailyTPV = 0;   nSumDailyVol = 0;}

      for(; nIdx<rates_total; nIdx++)
        {
         if(CreateDateTime(DAILY,time[nIdx])!=dtLastDay)
           {
            nIdxDaily=nIdx;
            nSumDailyTPV = 0;
            nSumDailyVol = 0;
           }
         nPriceArr[nIdx] = 0;
         nTotalTPV[nIdx] = 0;
         nTotalVol[nIdx] = 0;
         switch(Price_Type)
           {
            case OPEN_CLOSE_HIGH_LOW:
               nPriceArr[nIdx]=(open[nIdx]+close[nIdx]+high[nIdx]+low[nIdx])/4;
               break;
            default:
               nPriceArr[nIdx]=(close[nIdx]+high[nIdx]+low[nIdx])/3;
               break;
           }
         if(tick_volume[nIdx])
           {
            nTotalTPV[nIdx] = (nPriceArr[nIdx] * tick_volume[nIdx]);
            nTotalVol[nIdx] = (double)tick_volume[nIdx];
              } else if(volume[nIdx]) {
            nTotalTPV[nIdx] = (nPriceArr[nIdx] * volume[nIdx]);
            nTotalVol[nIdx] = (double)volume[nIdx];
           }

         if(Enable_Daily && (nIdx>=nIdxDaily))
           {
            nSumDailyTPV += nTotalTPV[nIdx];
            nSumDailyVol += nTotalVol[nIdx];

            if(nSumDailyVol)
               VWAP_Buffer_Daily=(nSumDailyTPV/nSumDailyVol);

            if((sDailyStr!="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily,_Digits)) && Show_Daily_Value)
              {
               sDailyStr="VWAP Daily: "+(string)NormalizeDouble(VWAP_Buffer_Daily,_Digits);
               ObjectSetString(0,"VWAP_Diario",OBJPROP_TEXT,sDailyStr);
                }
              }
         dtLastDay=CreateDateTime(DAILY,time[nIdx]);
        }
      bIsFirstRun=false;
     }
     
     }



maronezzi
43
maronezzi  
maronezzi:

@Rogerio Giannetti Torres e @Trader_Patinhas, obrigado pelas prontas respostas.

Respondendo as perguntas, esse código é o que esta rodando, o erro é repetido toda as vezes que entra a opção de Buy ou Sell, e quando executa o PositionClose() ele fecha abre e fecha as posições.

Eu postei a pergunta, porque mesmo com o Sleep(5000) o erro continua e o tempo da operação como vocês observaram não obedece ele.


O meu script roda em uma VPS, mas na primeira vez que rodei a latência estava bem baixa, na casa de 56ms.

Eu tenho rodado a conta rela da XP e uso as contas demo da Clear para os teste, portanto não vejo dois scprits rodando em paralelo.

Antes de rodar na conta Real, deixei por vários dias rodando em conta Demo, mas o erro não acontece.

Vou postar o código, mas não sou um programador muito experiente, portanto podem ter coisas que poderiam ser otimizadas, com o tempo vou corrigindo elas.


//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************
//*************************************************************************************************************


//--- declare and initialize the trade request and result of trade request

string horadata = TimeToString(TimeLocal(),TIME_MINUTES);
   

//*************************************************************************************************************
//*************************************************************************************************************

int posicaoTotal = PositionsTotal();
static int candleOperado;
/*
*/
//****************************************************************************************************************
//****************************************************************************************************************
if (ordemcompra == true)
{
   //Exclui ordem de compra abaixo da MM e Vwap
   if (OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter && high[rates_total1-2] < VWAP_Buffer_Daily && high[rates_total1-2] < mediamovelrap[1]
        && Ask < high[rates_total1-2])
      {
      
      for(int i=0; i<OrdersTotal(); i++)
         {
         ulong order_ticket=OrderGetTicket(i); // bilhete da ordem
         ulong magic=OrderGetInteger(ORDER_MAGIC); 
         
         if(magic==EXPERT_MAGIC_BUY)
            {
            ZeroMemory(request);
            ZeroMemory(result);        
            //--- setting the operation parameters     
            request.action=TRADE_ACTION_REMOVE;                   // type of trade operation
            request.order = order_ticket;                         // order ticket
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
            Sleep(5000);
            ZeroMemory(request);
            ZeroMemory(result);
            candleOperado = candleCounter;
            }
         }
      }
         
   //Altera a ordem de compra       
      if (high[rates_total1-2] <= high[rates_total1-3] && OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter)
         {
         //-- declaração e inicialização do pedido e o seu resultado
          
         //--- iterar todas as ordens pendentes colocadas
          for(int i=0; i<OrdersTotal(); i++)
          {
             //--- parâmetros da ordem
             ulong order_ticket=OrderGetTicket(i); // bilhete da ordem
             string order_symbol=Symbol(); // símbolo
             int digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS); // número de signos depois da coma
             ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumber da ordem
             double volume=OrderGetDouble(ORDER_VOLUME_CURRENT); // volume atual da ordem
             double sl=OrderGetDouble(ORDER_SL); // Stop Loss atual da ordem
             double tp=OrderGetDouble(ORDER_TP); // Take Profit atual da ordem
             ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // tipo de ordem
             double price; // preço de ativação da ordem
             double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT); // tamanho do ponto

             if(magic==EXPERT_MAGIC_BUY)
             {
                MqlTradeRequest request={0};
                MqlTradeResult  result={0};
                
                double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)];
                price        = high[rates_total1-2]; // price for opening
                price = NormalizeDouble(price/5,0) * 5;
                
                request.type_filling =  ORDER_FILLING_RETURN;
                request.expiration = ORDER_TIME_GTC;
                request.action=TRADE_ACTION_MODIFY; // tipo de operação de negociação
                request.order = OrderGetTicket(i); // bilhete da ordem
                request.symbol =Symbol(); // símbolo
                //--- definição do nível de preços Take Profit e Stop Loss da ordem dependendo do seu tipo
                if(type==ORDER_TYPE_BUY_STOP)
                {
                   request.type = ORDER_TYPE_BUY_STOP; 
                   request.tp = NormalizeDouble((high[rates_total1-2] + tpMax)/5,0) * 5;
                   //request.sl = low[rates_total1-2];
                   //if (OpenSellOrder() >= 1)
                   //   request.sl = 10 + NormalizeDouble(low[rates_total1-2]/5,0) * 5;
                   //else
                      request.sl = SL_buy;
                   

                   request.price = NormalizeDouble(price,digits);  
                
                //--- envio do pedido
                if(!OrderSend(request,result))
                  PrintFormat("OrderSend error %d",GetLastError()); // se não foi possível enviar o pedido, exibir o código de erro 
                //--- informações sobre a operação 
                PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
                Sleep(5000);
                candleOperado = candleCounter;
                //--- zerado dos valores do pedido e o seu resultado
                ZeroMemory(request);
                ZeroMemory(result);
                }
              }
            }

          }
   
   
   //Compra
   if(high[rates_total1-2] >= VWAP_Buffer_Daily && high[rates_total1-2] >= mediamovelrap[1] && high[rates_total1-2] >= mediamovellenta[1]
        && low[rates_total1-2] < VWAP_Buffer_Daily && low[rates_total1-2] < mediamovelrap[1]
        && PositionsTotal() == 0 && candleCounter != candleAnterior && candleOperado != candleCounter && Ask < high[rates_total1-2])
      { 
         if ((StringSubstr(horadata,0,5) >= horainicioOp) && (StringSubstr(horadata,0,5) <= horafimOp) )
               {
               if (OpenBuyOrder() == 0)
               {
                  double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)];
                  double price;  
                  price        = high[rates_total1-2]; // price for opening
                  price = NormalizeDouble(price/5,0) * 5;
                  
                  MqlTradeRequest request={0};
                  MqlTradeResult  result={0};
                  
                  request.action   = TRADE_ACTION_PENDING;                             // type of trade operation
                  request.symbol   = Symbol();                                         // symbol
                  request.volume   = volumeOp;                                         // volume of 0.1 lot
   
                  request.magic    = EXPERT_MAGIC_BUY;                                     // MagicNumber of the order
                  double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // value of point
                  int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // number of decimal places (precision)
                  
                  request.type = ORDER_TYPE_BUY_STOP;                                // order type
                  request.type_filling =        ORDER_FILLING_RETURN;
                  request.type_time    = ORDER_TIME_DAY;
                  request.expiration = ORDER_TIME_GTC;
                  
                  request.sl = SL_buy;
                  request.tp = NormalizeDouble((high[rates_total1-2] + tpMax)/5,0) * 5;
                                                                       // order triggering price
      
                  //--- checking the type of operation
                  

                  request.price = NormalizeDouble(price,digits);                      // normalized opening price
                  
                  //--- send the request
                  if(!OrderSend(request,result))
                     PrintFormat("OrderSend error %d",GetLastError());                 // if unable to send the request, output the error code
                  //--- information about the operation
                  PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
                  Sleep(5000);
                  ZeroMemory(request);
                  ZeroMemory(result);
                  candleOperado = candleCounter;
                  }
               }
         }
   
   //Stop para comprado
      
   if (low[rates_total1-2] > low[rates_total1-3] && PositionsTotal() > 0 && candleCounter != candleAnterior && candleOperado != candleCounter)
      {
       for(int i=0; i<PositionsTotal(); i++)
         {
         ulong  position_ticket=PositionGetTicket(i);// ticket of the position
         string position_symbol=PositionGetString(POSITION_SYMBOL); // symbol 
         int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal places
         ulong  magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position
         double volume=PositionGetDouble(POSITION_VOLUME);    // volume of the position
         double sl=PositionGetDouble(POSITION_SL);  // Stop Loss of the position
         double tp=PositionGetDouble(POSITION_TP);  // Take Profit of the position
         ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);  // type of the position
         double SL_buy = lowinverse[ArrayMinimum(lowinverse,1,slcomprado)];
         SL_buy = NormalizeDouble(SL_buy/5,0) * 5;
         //--- if the MagicNumber matches, Stop Loss and Take Profit are not defined
         if(magic==EXPERT_MAGIC_BUY && type==POSITION_TYPE_BUY && sl != SL_buy)
           {                 
            
            MqlTradeRequest request;
            MqlTradeResult  result;
            ZeroMemory(request);
            ZeroMemory(result);
            //--- setting the operation parameters
            request.action  = TRADE_ACTION_SLTP; // type of trade operation
            request.position= position_ticket;   // ticket of the position
            request.symbol  = position_symbol;     // symbol 
            request.tp      = NormalizeDouble(tp/5,0) * 5;
            request.sl = NormalizeDouble(SL_buy/5,0) * 5;
            request.magic=EXPERT_MAGIC_BUY;         // MagicNumber of the position
            //--- output information about the modification
            PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
            Sleep(5000);
            ZeroMemory(request);
            ZeroMemory(result);
            candleOperado = candleCounter;
            }
         }
         
   }
}
maronezzi
43
maronezzi  
maronezzi:
//****************************************************************************************************************
//****************************************************************************************************************

if (ordemvenda == true)
{

   //Exclui ordem de venda abaixo da MM e Vwap
   if (OrdersTotal() > 0 && candleAnterior != candleCounter && candleOperado != candleCounter && low[rates_total1-2] > VWAP_Buffer_Daily && low[rates_total1-2] > mediamovelrap[1]
        && Ask > low[rates_total1-2])
      {
      double NsVendaLs = highinverse[ArrayMaximum(highinverse,1,slvendido)];
      for(int i=0; i<OrdersTotal(); i++)
         {
         ulong order_ticket=OrderGetTicket(i); // bilhete da ordem
         ulong magic=OrderGetInteger(ORDER_MAGIC); 
         
         if(magic==EXPERT_MAGIC_SELL)
            {
            ZeroMemory(request);
            ZeroMemory(result);        
            //--- setting the operation parameters     
            request.action=TRADE_ACTION_REMOVE;                   // type of trade operation
            request.order = order_ticket;                         // order ticket
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
            Sleep(5000);
            ZeroMemory(request);
            ZeroMemory(result);
            candleOperado = candleCounter;
            }
         }
      }
         
   //Altera a ordem de venda
      if (low[rates_total1-2] >= low[rates_total1-3] && candleAnterior != candleCounter && candleOperado != candleCounter && OpenSellOrder() > 0)
         {
         //-- declaração e inicialização do pedido e o seu resultado
          
         //--- iterar todas as ordens pendentes colocadas
          for(int i=0; i<OrdersTotal(); i++)
          {//
             //--- parâmetros da ordem
             ulong order_ticket=OrderGetTicket(i); // bilhete da ordem
             string order_symbol=Symbol(); // símbolo
             int digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS); // número de signos depois da coma
             ulong magic=OrderGetInteger(ORDER_MAGIC); // MagicNumber da ordem
             double volume=OrderGetDouble(ORDER_VOLUME_CURRENT); // volume atual da ordem
             double sl=OrderGetDouble(ORDER_SL); // Stop Loss atual da ordem
             double tp=OrderGetDouble(ORDER_TP); // Take Profit atual da ordem
             ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // tipo de ordem
             double price; // preço de ativação da ordem
             double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT); // tamanho do ponto
             //--- saída de informações sobre a ordem
             //PrintFormat("#%I64u %s %s %.2f %s sl: %s tp: %s [%I64d]", order_ticket, order_symbol, EnumToString(type),volume,
             //DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
             //DoubleToString(sl,digits), DoubleToString(tp,digits), magic);
             //--- se o MagicNumber coincidir, o Stop Loss e o Take Profit nao foram definidos
             //if(magic==EXPERT_MAGIC_SELL && sl != high[rates_total1-2])
             if(magic==EXPERT_MAGIC_SELL)
             {  
                MqlTradeRequest request={0};
                MqlTradeResult  result={0};  
                double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)];
                price        = low[rates_total1-2]; // price for opening
                price = NormalizeDouble(price/5,0) * 5;
                  
                request.type_filling =  ORDER_FILLING_RETURN;
                request.expiration = ORDER_TIME_GTC;
                request.action=TRADE_ACTION_MODIFY; // tipo de operação de negociação
                request.order = OrderGetTicket(i); // bilhete da ordem
                request.symbol =Symbol(); // símbolo
                //--- definição do nível de preços Take Profit e Stop Loss da ordem dependendo do seu tipo
                if(type==ORDER_TYPE_SELL_STOP)
                {
                   request.type = ORDER_TYPE_SELL_STOP; 
                   
                   request.tp = NormalizeDouble((low[rates_total1-2] - tpMin)/5,0) * 5;

                   if (OpenBuyOrder() >= 1)
                     request.sl = NormalizeDouble(((high[rates_total1-2]/5) - 10),0) * 5;
                   else
                     request.sl = NormalizeDouble(SL_venda/5,0) * 5;
                       

                   request.price = NormalizeDouble(price,digits);  
                }
                //--- envio do pedido
                if(!OrderSend(request,result))
                  PrintFormat("OrderSend error %d",GetLastError()); // se não foi possível enviar o pedido, exibir o código de erro 
                //--- informações sobre a operação 
                PrintFormat("retcode=%u deal=%I64u order=%I64u",result.retcode,result.deal,result.order);
                Sleep(5000);
                //--- zerado dos valores do pedido e o seu resultado
                ZeroMemory(request);
                ZeroMemory(result);
                candleOperado = candleCounter;
              }
            }
          }
   
   
   
   //Venda
   if(low[rates_total1-2] <= VWAP_Buffer_Daily && low[rates_total1-2] <= mediamovelrap[1] && low[rates_total1-2] <= mediamovellenta[1]
        && high[rates_total1-2] > VWAP_Buffer_Daily && high[rates_total1-2] > mediamovelrap[1]  
         && PositionsTotal() == 0 && candleCounter != candleAnterior && candleOperado != candleCounter && Ask > low[rates_total1-2])
      { 
         if ((StringSubstr(horadata,0,5) >= horainicioOp) && (StringSubstr(horadata,0,5) <= horafimOp) )
               {
               if (OpenSellOrder() == 0)
               {
                  double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)];
                  double price;                                                       // order triggering price
                  price        = low[rates_total1-2]; // price for opening
                  price = NormalizeDouble(price/5,0) * 5;
                  
                  MqlTradeRequest request={0};
                  MqlTradeResult  result={0};
                  request.action   = TRADE_ACTION_PENDING;                             // type of trade operation
                  request.symbol   = Symbol();                                         // symbol
                  request.volume   = volumeOp;                                         // volume of 0.1 lot
                  request.magic    = EXPERT_MAGIC_SELL;                                     // MagicNumber of the order
                  double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // value of point
                  int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // number of decimal places (precision)
                  
                  request.type = ORDER_TYPE_SELL_STOP;                                // order type
                  request.type_filling =        ORDER_FILLING_RETURN;
                  request.type_time    = ORDER_TIME_DAY;
                  request.expiration = ORDER_TIME_GTC;
                  
                     
                  if (OpenBuyOrder() >= 1)
                     request.sl = (NormalizeDouble((high[rates_total1-2] - 10)/5,0)) * 5;
                  else
                     request.sl = SL_venda;   
                     
                  request.tp = NormalizeDouble((low[rates_total1-2] - tpMin)/5,0) * 5;

                  request.price = NormalizeDouble(price,digits);                      // normalized opening price
      
                  //--- send the request
                  if(!OrderSend(request,result))
                     PrintFormat("OrderSend error %d",GetLastError());                 // if unable to send the request, output the error code
                  //--- information about the operation
                  PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
                  Sleep(5000);
                  ZeroMemory(request);
                  ZeroMemory(result);
                  candleOperado = candleCounter;
                  

              }
            }
         }
   
   
   
   
   //Stop para vendido
        
   if (high[rates_total1-2] < high[rates_total1-3] && PositionsTotal() > 0 && candleCounter != candleAnterior && candleOperado != candleCounter)
      {
       for(int i=0; i<PositionsTotal(); i++)
         {
         ulong  position_ticket=PositionGetTicket(i);// ticket of the position
         string position_symbol=PositionGetString(POSITION_SYMBOL); // symbol 
         int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // number of decimal places
         ulong  magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position
         double volume=PositionGetDouble(POSITION_VOLUME);    // volume of the position
         double sl=PositionGetDouble(POSITION_SL);  // Stop Loss of the position
         double tp=PositionGetDouble(POSITION_TP);  // Take Profit of the position
         ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);  // type of the position
         double SL_venda = highinverse[ArrayMaximum(highinverse,1,slvendido)];
         SL_venda = NormalizeDouble(SL_venda/5,0) * 5;
         //--- if the MagicNumber matches, Stop Loss and Take Profit are not defined
         if(magic==EXPERT_MAGIC_SELL && type==POSITION_TYPE_SELL && sl != SL_venda)
           {                 
            MqlTradeRequest request;
            MqlTradeResult  result;
            //--- setting the operation parameters
            request.action  = TRADE_ACTION_SLTP; // type of trade operation
            request.position= position_ticket;   // ticket of the position
            request.symbol  = position_symbol;     // symbol 
            request.tp      = NormalizeDouble(tp/5,0) * 5;  
            request.sl      = SL_venda;
            request.magic   = EXPERT_MAGIC_SELL;         // MagicNumber of the position
            //--- output information about the modification
            PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));
            //--- send the request
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
            //--- information about the operation   
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
            Sleep(5000);
            ZeroMemory(request);
            ZeroMemory(result);
            candleOperado = candleCounter;
            }
         }
   }
}


//***********************************************************************************************************************   
//***********************************************************************************************************************

if ((OrdersTotal() >= 0 || PositionsTotal() >=0) && (StringSubstr(horadata,0,5) >= "16:40"))
   {
      for(int i=OrdersTotal()-1; i>=0; i--)
        {
         ulong  order_ticket=OrderGetTicket(i);                   // order ticket
         ZeroMemory(request);
         ZeroMemory(result);
         //--- setting the operation parameters
         request.action=TRADE_ACTION_REMOVE;                   // type of trade operation
         request.order = order_ticket;                         // order ticket
         //--- send the request
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
         //--- information about the operation
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
         Sleep(5000);
        }
   }

if ((PositionsTotal()>0) && (StringSubstr(horadata,0,5) >= "16:53"))
   {
   for(int i=0; i<OrdersTotal(); i++)
         {
         ulong  magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber of the position
         if(magic==EXPERT_MAGIC_BUY)
           {
           //printf (pos_profit);
            if (PositionGetDouble(POSITION_PROFIT) < 0)
               {
               if (trade.PositionClose(PositionGetSymbol(i)));
               }
           }
         if(magic==EXPERT_MAGIC_SELL)
           {
           //printf (pos_profit);
            if (PositionGetDouble(POSITION_PROFIT) < 0)
               {
               if (trade.PositionClose(PositionGetSymbol(i)));
               }
           }
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // if unable to send the request, output the error code
         //--- information about the operation
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
         Sleep(5000);
         }
   }

if ((PositionsTotal()>0) && (StringSubstr(horadata,0,5) >= "17:10"))
   {
      ZeroMemory(request);
      ZeroMemory(result);
      CloseAll();
      Sleep(5000);
   }
   
if (candleCounter != candleAnterior)
   {  
         candleAnterior = candleCounter;       
   }
   
}
//+------------------------------------------------------------------+
maronezzi
43
maronezzi  
maronezzi:

Tive que quebrar em três responstas, pelo limite de caracteres do forum.

Para rodar hoje na conta real, reiniciei o metatrader e recompilei o código, vamos ver como se comporta.


Como disse podem ter coisas a otimizar, mas no geral o código funciona perfeitamente na conta Demo.


Agradeço a ajuda.

Gustavo Enedir Hennemann
436
Gustavo Enedir Hennemann  

Olá @maronezzi, não olhei o seu código completo, mas uma coisa me chamou à atenção, você está com a função OrderSend() dentro de um laço for, isto é muito perigoso e deve ser usado com muita atenção.

Sugiro você criar funções específicas para abrir, fechar e alterar ordens e posições, com nome bem descritivos, isso ajuda bastante a identificar bugs. Como você já está usando a classe "Trade" aproveite os recursos que ela oferece.

Outra dica, em último caso, é usar o debug na conta real. Isso ajuda a identificar situações que não acontecem em conta demo.

maronezzi
43
maronezzi  
Gustavo Hennemann:

Olá @maronezzi, não olhei o seu código completo, mas uma coisa me chamou à atenção, você está com a função OrderSend() dentro de um laço for, isto é muito perigoso e deve ser usado com muita atenção.

Sugiro você criar funções específicas para abrir, fechar e alterar ordens e posições, com nome bem descritivos, isso ajuda bastante a identificar bugs. Como você já está usando a classe "Trade" aproveite os recursos que ela oferece.

Outra dica, em último caso, é usar o debug na conta real. Isso ajuda a identificar situações que não acontecem em conta demo.

@Gustavo Hennemann, hoje pretendo colocar em debug na conta real. Assim que a lógica ocorrer.


As minhas OrderSend() dentro de um for, estão nas alterações de stops, ou modificar uma ordem que já estava em aberto. A ordem seca de Buy não tem for.

O próximo passo para o script é colocar mais funções, indentar melhor o código e comenta-lo melhor também.


Obrigado pelos comentários.

Rogerio Giannetti Torres
3257
Rogerio Giannetti Torres  

Boa tarde Maronezzi,

sugiro diferenciar as mensagens do   PrintFormat("retcode=%u  ...) para melhor depuração do pgm. 

Ex PrintFormat(" ORDEM PENDING BUY STOP retconde=%u ...). 

12
Para adicionar comentários, por favor Faça o login ou registrar