Todas las órdenes pendientes son canceladas inmediatamente luego de ser colocadas - Código de error: 10013 [Invalid Request]

 

Estoy intentando enteder por qué cada una de las órdenes pendientes son canceladas inmediatamente luego de que las mismas son colocadas de mantra exitosa en el mercado. El mensaje de error que devuelve el asesor experto es el siguiente: "Error Code: 10013 [Invalid Request]"


Comparto el log donde se pueden ver los mensajes del servidor:

RQ 0 17:21:02.223 Trades '1520355161': sell stop 1 XAUUSD at 2450.69 sl: 2475.20 tp: 2401.68

EF 0 17:21:02.366 Trades '1520355161': accepted sell stop 1 XAUUSD at 2450.69 sl: 2475.20 tp: 2401.68

GF 0 17:21:02.371 Trades '1520355161': order #31994308 sell stop 1 / 1 XAUUSD at 2450.69 done in 148.542 ms

OQ 0 17:21:02.435 Trades '1520355161': cancel order #31994308 sell stop 1 XAUUSD at 2450.69 sl: 2475.20 tp: 2401.68

PR 0 17:21:02.488 Trades '1520355161': accepted cancel order #31994308 sell stop 1 XAUUSD at 2450.69 sl: 2475.20 tp: 2401.68

ML 0 17:21:02.490 Trades '1520355161': cancel #31994308 sell stop 1 XAUUSD at market done in 54.933 ms


Comparto el código:

//+------------------------------------------------------------------+
//|                                        London range breakout.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <trade/trade.mqh>

//+------------------------------------------------------------------+
//| Parámetros de entrada                                            |
//+------------------------------------------------------------------+

input group "Trade Settings"
input ENUM_TIMEFRAMES v_TimeFrame = PERIOD_H1; //Timeframe to execute the strategy
input double i_Risk           = 1.0; //Balance Risk % per operation
input double i_StopLossPerc   = 1.0; //Stop Loss % from the entry price
input double i_TakeProfitPerc = 2.0; //Take profit % from the entry price

input group "Trading days"
input bool   i_Monday    = true; //Enable trading on Monday
input bool   i_Tuesday   = true; //Enable trading on Tuesday
input bool   i_Wednesday = true; //Enable trading on Wednesday
input bool   i_Thursday  = true; //Enable trading on Thursday
input bool   i_Friday    = true; //Enable trading on Friday

input group "General Settings"
input bool i_SwingTrading  = true; //Enable swing trading
input bool i_ClosePendingOrders = true; //Close pending orders at EOD

input group "Trailing Stop Settings"
input bool   i_TrailingStop         = true; //Trailing Stop
input double i_TraillingTriggerPerc = 0.5; //Profit % from which you want to modify the stop loss
input double i_TraillingPerc        = 0.5; //Stop Loss (%) from the current price

input group "Partial Close Settings"
input bool   i_PartialClose       = false; //Take partials
input double i_PartialClosePerc   = 0.5; //Profit % where to partially close the order
input double i_PartialCloseFactor = 0.25; //Lot % to close

//+------------------------------------------------------------------+
//| Variables globales                                               |
//+------------------------------------------------------------------+
double v_LondonOpenPrice,
       v_LondonClosePrice,
       v_LondonHighestPrice,
       v_LondonLowestPrice,
       v_EntryPrice;

ulong v_OrderTicket;

int const c_MagicNumber = 35273184;

bool v_tradeOpenedToday = false;

MqlDateTime v_lastTradeDate,
            v_currentDate;

//+------------------------------------------------------------------+
//| Clases                                                           |
//+------------------------------------------------------------------+
CTrade v_Trade;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit() {
   v_Trade.SetExpertMagicNumber(35273184);
   v_tradeOpenedToday = false;
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert trade transaction function                                |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result) {

   if(result.retcode == TRADE_RETCODE_INVALID) {
      Print(__FUNCTION__, "Invalid request in symbol ", _Symbol, ". Error: ", result.retcode);
   }
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick() {

   TimeToStruct(TimeGMT(), v_currentDate);
   if (AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) &&
         AccountInfoInteger(ACCOUNT_TRADE_EXPERT)) {

//Verificar si comenzó un nuevo día
      if(v_currentDate.day_of_year != v_lastTradeDate.day_of_year) {
         v_tradeOpenedToday = false;
         //Al finalizar el día, cerrar órdenes colocadas que aún no
         //hayan sido abiertas
         closeOrder();
      }
//Si no se abrieron trades en el día actual
      if(v_tradeOpenedToday == false) {
         //Analizar condiciones para establecer una orden
         checkTradeConditions(v_currentDate);
      }
      if(i_TrailingStop || i_PartialClose) {
         //Modificar órdenes abiertas
         modifyOrder();
      }
   }  else {
      Print("Trading not allowed");
   }
}

//+------------------------------------------------------------------+
//| Analizar condiciones para establecer una orden                   |
//+------------------------------------------------------------------+
void checkTradeConditions(MqlDateTime & p_currentDate) {

   string lv_day = "";

   if((p_currentDate.day_of_week == 1 && i_Monday == true) ||
         (p_currentDate.day_of_week == 2 && i_Tuesday == true) ||
         (p_currentDate.day_of_week == 3 && i_Wednesday == true) ||
         (p_currentDate.day_of_week == 4 && i_Thursday == true) ||
         (p_currentDate.day_of_week == 5 && i_Friday == true)) {

      if(p_currentDate.day_of_week == 0) lv_day = "Sunday";
      if(p_currentDate.day_of_week == 1) lv_day = "Monday";
      if(p_currentDate.day_of_week == 2) lv_day = "Tuesday";
      if(p_currentDate.day_of_week == 3) lv_day = "Wednesday";
      if(p_currentDate.day_of_week == 4) lv_day = "Thursday";
      if(p_currentDate.day_of_week == 5) lv_day = "Friday";
      if(p_currentDate.day_of_week == 6) lv_day = "Saturday";

      //London session hours
      //5am - 10am (GMT)
      //6am - 11am (LN Time) (UTC + 1) DST
      //5am - 10am (LN Time) (UTC-0)
      int lv_LondonOpen  = 05,
          lv_LondonClose = 10;

      //Si ya finalizó la London Session
      if(p_currentDate.hour > lv_LondonClose) {
         if(v_LondonLowestPrice  == NULL &&
               v_LondonHighestPrice == NULL ) {

            MqlDateTime lv_MqlDate = p_currentDate;
            lv_MqlDate.min = 0;
            lv_MqlDate.sec = 0;

            for(int i = lv_LondonOpen; i <= lv_LondonClose; i++) {
               lv_MqlDate.hour = i;
               //Obtener precios de interés de la sesión de Londres
               getLondonPrices(lv_MqlDate);
            }
         }

         MqlTick lv_currentTick;
         SymbolInfoTick(_Symbol, lv_currentTick);

         //Si el precio se encuentra debajo del London Highest Price
         if(lv_currentTick.ask < v_LondonHighestPrice) {
            sendOrder(ORDER_TYPE_BUY_STOP);
         }
         //Si el precio se encuentra encima del London Lowest Price
         if(lv_currentTick.bid > v_LondonLowestPrice) {
            sendOrder(ORDER_TYPE_SELL_STOP);
         }
      }
   }
}
//+------------------------------------------------------------------+
//| Obtener niveles de precios de London Session                     |
//+------------------------------------------------------------------+
void getLondonPrices(MqlDateTime & p_CurrentDate) {
   datetime lv_DateTime = StructToTime(p_CurrentDate);
   switch(p_CurrentDate.hour) {
   //Obtener el precio de apertura de Londres
   case 05:
      v_LondonOpenPrice    = iOpen(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, lv_DateTime));
      v_LondonOpenPrice    = NormalizeDouble(v_LondonOpenPrice, _Digits);
      v_LondonHighestPrice = iHigh(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, lv_DateTime));
      v_LondonLowestPrice  = iLow(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, lv_DateTime));
      v_LondonHighestPrice = NormalizeDouble(v_LondonHighestPrice, _Digits);
      v_LondonLowestPrice = NormalizeDouble(v_LondonLowestPrice, _Digits);
      break;
   case 06:
   case 07:
   case 08:
      getSessionHighLow(v_LondonLowestPrice, v_LondonHighestPrice, lv_DateTime);
      break;
   case 09:
      v_LondonClosePrice = iClose(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, lv_DateTime));
      getSessionHighLow(v_LondonLowestPrice, v_LondonHighestPrice, lv_DateTime);
      break;
   }
}
//+------------------------------------------------------------------+
//| Modificar órdenes abiertas                                       |
//+------------------------------------------------------------------+
void modifyOrder() {

   for(int i = 0; i < PositionsTotal(); i++) {

      ulong lv_positionTicket = PositionGetTicket(i);

      if(PositionGetSymbol(POSITION_SYMBOL) != _Symbol)
         continue;

      if(PositionGetInteger(POSITION_MAGIC) != c_MagicNumber)
         continue;

      double lv_BidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      lv_BidPrice = NormalizeDouble(lv_BidPrice, _Digits);

      double lv_AskPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      lv_AskPrice = NormalizeDouble(lv_AskPrice, _Digits);

      double lv_positionOpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
      lv_positionOpenPrice = NormalizeDouble(lv_positionOpenPrice, _Digits);

      double lv_PositionStopLoss = PositionGetDouble(POSITION_SL);
      lv_PositionStopLoss = NormalizeDouble(lv_PositionStopLoss, _Digits);

      double lv_PositionTakeProfit = PositionGetDouble(POSITION_TP);
      lv_PositionTakeProfit = NormalizeDouble(lv_PositionTakeProfit, _Digits);

      double lv_PositionVolume = PositionGetDouble(POSITION_VOLUME);
      lv_PositionVolume = NormalizeDouble(lv_PositionVolume, _Digits);

      double lv_VolMin = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
      lv_VolMin = NormalizeDouble(lv_VolMin, _Digits);

      double lv_VolMax = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
      lv_VolMax = NormalizeDouble(lv_VolMax, _Digits);

      int lv_StopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
      int lv_Spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

      //Si es una orden de compra
      if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {

         if(i_TrailingStop) {

            double lv_trailingTrigger = lv_positionOpenPrice + (lv_positionOpenPrice * i_TraillingTriggerPerc / 100);
            lv_trailingTrigger = NormalizeDouble(lv_trailingTrigger, _Digits);

            if(lv_BidPrice >= lv_trailingTrigger) {

               //Calculo el nuevo Stop Loss en base a un porcentaje (parámetro) de la
               //diferencia entre el Bid Price y el precio de apertura de la orden
               double lv_StopLoss = lv_BidPrice - (lv_BidPrice * i_TraillingPerc / 100);
               lv_StopLoss = NormalizeDouble(lv_StopLoss, _Digits);

               if(lv_StopLoss > lv_PositionStopLoss && (lv_BidPrice - lv_StopLoss >= (lv_StopLevel + lv_Spread) * _Point)) {
                  v_Trade.PositionModify(lv_positionTicket, lv_StopLoss, lv_PositionTakeProfit);
               } else {
                  Print(__FUNCTION__, " > Trailing Stop error. Cannot modify SL (Invalid SL Price)");
               }
            }
         }

         if(i_PartialClose) {

            double lv_pClose = lv_positionOpenPrice + ((lv_PositionTakeProfit - lv_positionOpenPrice) * i_PartialClosePerc / 100);
            lv_pClose = NormalizeDouble(lv_pClose, _Digits);

            if(lv_BidPrice >= lv_pClose) {

               double lv_LotSize = calcLotSize(ORDER_TYPE_BUY_STOP, lv_PositionStopLoss, lv_positionOpenPrice, i_Risk);

               if(lv_PositionVolume == lv_LotSize) {

                  double lv_LotsToClose = lv_PositionVolume * i_PartialCloseFactor / 100;

                  if (lv_LotsToClose < lv_VolMin) {
                     lv_LotsToClose = lv_VolMin;
                  } else if (lv_LotsToClose > lv_VolMax) {
                     lv_LotsToClose = lv_VolMax;
                  }

                  v_Trade.PositionClosePartial(lv_positionTicket, lv_LotsToClose);

               }
            }
         }

      } else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {

         if(i_TrailingStop) {

            double lv_trailingTrigger = lv_positionOpenPrice - (lv_positionOpenPrice * i_TraillingTriggerPerc / 100);
            lv_trailingTrigger = NormalizeDouble(lv_trailingTrigger, _Digits);

            if(lv_AskPrice <= lv_trailingTrigger) {

               //Calculo el nuevo Stop Loss en base a un porcentaje (parámetro) de la
               //diferencia entre el precio de apertura de la orden y el Ask Price
               double lv_StopLoss = lv_AskPrice + (lv_AskPrice * i_TraillingPerc / 100);
               lv_StopLoss = NormalizeDouble(lv_StopLoss, _Digits);

               if((lv_StopLoss < lv_PositionStopLoss || lv_PositionStopLoss == 0) && (lv_StopLoss - lv_AskPrice >= (lv_StopLevel + lv_Spread) * _Point)) {
                  v_Trade.PositionModify(lv_positionTicket, lv_StopLoss, lv_PositionTakeProfit);
               } else {
                  Print(__FUNCTION__, " > Trailing Stop error. Cannot modify SL (Invalid SL Price)");
               }

            }
         }

         if(i_PartialClose) {

            double lv_pClose = lv_positionOpenPrice - (lv_positionOpenPrice * i_PartialClosePerc / 100);
            lv_pClose = NormalizeDouble(lv_pClose, _Digits);

            if(lv_AskPrice <= lv_pClose) {

               double lv_LotSize = calcLotSize(ORDER_TYPE_SELL_STOP, lv_PositionStopLoss, lv_positionOpenPrice, i_Risk);

               if(lv_PositionVolume == lv_LotSize) {

                  double lv_LotsToClose = lv_PositionVolume * i_PartialCloseFactor / 100;

                  if (lv_LotsToClose < lv_VolMin) {
                     lv_LotsToClose = lv_VolMin;
                  } else if (lv_LotsToClose > lv_VolMax) {
                     lv_LotsToClose = lv_VolMax;
                  }

                  v_Trade.PositionClosePartial(lv_positionTicket, lv_LotsToClose);

               }

            }
         }
      }
   }
}
//+------------------------------------------------------------------+
//| Cerrar órdenes y posiciones abiertas al final del NY PM Session|
//+------------------------------------------------------------------+
void closeOrder() {
//Cerrar posiciones abiertas
   if(i_SwingTrading == false) {
      if(PositionsTotal() > 0) {
         for(int i = PositionsTotal() - 1; i >= 0; i--) {
            ulong lv_positionTicket = PositionGetTicket(i);
            if(PositionGetSymbol(POSITION_SYMBOL) == _Symbol &&
                  PositionGetInteger(POSITION_MAGIC) == c_MagicNumber) {
               v_Trade.PositionClose(lv_positionTicket);
            }
         }
      }
   }
   if(i_ClosePendingOrders) {
      //Eliminar órdenes pendientes
      if(OrdersTotal() > 0) {
         for(int i = OrdersTotal() - 1; i >= 0; i--) {
            ulong lv_orderTicket = OrderGetTicket(i);
            if(OrderGetInteger(ORDER_MAGIC) == c_MagicNumber) {
               v_Trade.OrderDelete(lv_orderTicket);
            }
         }
      }
   }

   v_LondonClosePrice    = NULL;
   v_LondonOpenPrice     = NULL;
   v_LondonHighestPrice  = NULL;
   v_LondonLowestPrice   = NULL;
   v_EntryPrice          = NULL;
}

//+------------------------------------------------------------------+
//| Obtener máximo y mínimo de la sesión                             |
//+------------------------------------------------------------------+
void getSessionHighLow(double & p_SessionLow, double & p_SessionHigh,
                       datetime & p_DateTime) {
   double lv_high = iHigh(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, p_DateTime));
   double lv_low = iLow(_Symbol, v_TimeFrame, iBarShift(_Symbol, v_TimeFrame, p_DateTime));
   if(lv_high * _Point > p_SessionHigh * _Point || p_SessionHigh == NULL) {
      p_SessionHigh = lv_high;
      p_SessionHigh = NormalizeDouble(p_SessionHigh, _Digits);
   }
   if(lv_low * _Point < p_SessionLow * _Point || p_SessionLow == NULL) {
      p_SessionLow = lv_low;
      p_SessionLow = NormalizeDouble(p_SessionLow, _Digits);
   }
}
//+------------------------------------------------------------------+
//| Enviar orden al mercado                                          |
//+------------------------------------------------------------------+
void sendOrder(ENUM_ORDER_TYPE p_OrderType) {

   if(p_OrderType == ORDER_TYPE_BUY_STOP) {

      v_EntryPrice = v_LondonHighestPrice;
      v_EntryPrice = NormalizeDouble(v_EntryPrice, _Digits);

      double lv_StopLoss = v_EntryPrice - ((v_EntryPrice * i_StopLossPerc) / 100),
             lv_TakeProfit = v_EntryPrice + ((v_EntryPrice * i_TakeProfitPerc) / 100),
             //Calcular el tamaño del lote en base al balance
             lv_lots = 1;
      lv_lots = NormalizeDouble(lv_lots, 2);

      lv_TakeProfit = NormalizeDouble(lv_TakeProfit, _Digits);
      lv_StopLoss = NormalizeDouble(lv_StopLoss, _Digits);

      if(checksForStopOrders(ORDER_TYPE_BUY_STOP, lv_TakeProfit, lv_StopLoss, lv_lots)) {
         bool lv_result = v_Trade.BuyStop(lv_lots, v_EntryPrice, _Symbol, lv_StopLoss, lv_TakeProfit, ORDER_TIME_GTC);
         if(lv_result) {
            MqlTradeResult lv_OrderResult;
            v_Trade.Result(lv_OrderResult);
            if(lv_OrderResult.retcode == TRADE_RETCODE_DONE) {
               v_OrderTicket = lv_OrderResult.order;
               TimeToStruct(TimeGMT(), v_lastTradeDate);
               v_tradeOpenedToday = true;
         } else {
            Print(__FUNCTION__, " | Error: ", v_Trade.ResultRetcodeDescription(), ". | Code: ", v_Trade.ResultRetcode(), " | Price: ", v_EntryPrice, " | SL: ", lv_StopLoss, " | TP: ", lv_TakeProfit, " | Volume: ", lv_lots);
         }
      }
   } else if(p_OrderType == ORDER_TYPE_SELL_STOP) {

      v_EntryPrice = v_LondonLowestPrice;
      v_EntryPrice = NormalizeDouble(v_EntryPrice, _Digits);

      double lv_StopLoss = v_EntryPrice + ((v_EntryPrice * i_StopLossPerc) / 100),
             lv_TakeProfit = v_EntryPrice - ((v_EntryPrice * i_TakeProfitPerc) / 100),
             //Calcular el tamaño del lote en base al balance
             lv_lots = 1;
      
      lv_TakeProfit = NormalizeDouble(lv_TakeProfit, _Digits);
      lv_StopLoss = NormalizeDouble(lv_StopLoss, _Digits);
      lv_lots = NormalizeDouble(lv_lots, _Digits);

      if(checksForStopOrders(ORDER_TYPE_SELL_STOP, lv_TakeProfit, lv_StopLoss, lv_lots)) {
         bool lv_result = v_Trade.SellStop(lv_lots, v_EntryPrice, Symbol(), lv_StopLoss, lv_TakeProfit, ORDER_TIME_GTC);
         if(lv_result) {
            MqlTradeResult lv_OrderResult;
            v_Trade.Result(lv_OrderResult);
            if(lv_OrderResult.retcode == TRADE_RETCODE_DONE) {
               v_OrderTicket = lv_OrderResult.order;
               TimeToStruct(TimeGMT(), v_lastTradeDate);
               v_tradeOpenedToday = true;
         } else {
            Print(__FUNCTION__, " | Error: ", v_Trade.ResultRetcodeDescription(), ". | Code: ", v_Trade.ResultRetcode(), " | Price: ", v_EntryPrice, " | SL: ", lv_StopLoss, " | TP: ", lv_TakeProfit, " | Volume: ", lv_lots);
         }
      }
   }
}
//+------------------------------------------------------------------+
//| Verificaciones para órdenes stop                                 |
//+------------------------------------------------------------------+
bool checksForStopOrders(ENUM_ORDER_TYPE p_OrderType,
                         double p_TP,
                         double p_SL,
                         double p_lots) {

   double lv_bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);
   double lv_ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);
   int lv_freezeLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL);
   double lv_margin;
   int lv_StopLevel = (int)SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
   int lv_Spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

//Controles para órdenes Buy Stop
   if(p_OrderType == ORDER_TYPE_BUY_STOP) {
      if(v_EntryPrice != lv_ask && v_EntryPrice - lv_ask < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Invalid Order Price)");
         return false;
      }
      if(v_EntryPrice - lv_ask < lv_freezeLevel) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Price within Freeze Level)");
         return false;
      }
      if(p_SL > 0 && v_EntryPrice - p_SL < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Invalid SL Price)");
         return false;
      }
      if(p_TP > 0 && p_TP - v_EntryPrice < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Invalid TP Price)");
         return false;
      }
      if(OrderCalcMargin(ORDER_TYPE_BUY_STOP, _Symbol, p_lots, v_EntryPrice, lv_margin) &&
            lv_margin > AccountInfoDouble(ACCOUNT_MARGIN_FREE)) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Not enough margin)");
         return false;
      }

      return true;

//Controles para órdenes Sell Stop
   } else { //if(PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL_STOP) {
      if(v_EntryPrice != lv_bid && lv_bid - v_EntryPrice < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Sell Stop Order (Invalid Order Price)");
         return false;
      }
      if(lv_bid - v_EntryPrice < lv_freezeLevel) {
         Print(__FUNCTION__, " > Cannot place Buy Stop Order (Price within Freeze Level)");
         return false;
      }
      if(p_SL > 0 && p_SL - v_EntryPrice < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Sell Stop Order (Invalid SL Price)");
         return false;
      }
      if(p_TP > 0 && v_EntryPrice - p_TP < (lv_StopLevel + lv_Spread) * _Point) {
         Print(__FUNCTION__, " > Cannot place Sell Stop Order (Invalid TP Price)");
         return false;
      }
      if(OrderCalcMargin(ORDER_TYPE_SELL_STOP, _Symbol, p_lots, v_EntryPrice, lv_margin) &&
            lv_margin > AccountInfoDouble(ACCOUNT_MARGIN_FREE)) {
         Print(__FUNCTION__, " > Cannot place Sell Stop Order (Not enough margin)");
         return false;
      }
      return true;
   }
}
////+------------------------------------------------------------------+
 
gcasellato:

No podemos hacer el trabajo por usted. Si no sabe o no desea programar, le recomendamos utilizar la sección Freelance para contratar a un programador.

Alternativamente, puede probar suerte y esperar a ver si alguien tiene el tiempo y la disposición para revisar 600 líneas de código.

En el foro solemos ayudar con dudas puntuales sobre una función o un problema específico, pero revisar un código completo copiado y pegado es otra cosa... ¿Qué opina?

 
Miguel Angel Vico Alba #:

No podemos hacer el trabajo por usted. Si no sabe o no desea programar, le recomendamos utilizar la sección Freelance para contratar a un programador.

Alternativamente, puede probar suerte y esperar a ver si alguien tiene el tiempo y la disposición para revisar 600 líneas de código.

En el foro solemos ayudar con dudas puntuales sobre una función o un problema específico, pero revisar un código completo copiado y pegado es otra cosa... ¿Qué opina

El trabajo ya fue realizado por mi, ya que soy yo el que escribió el código que copié.

Tampoco necesito contratar a un programador, ya que, como ya mencioné, soy el autor del código.

Seguramente haya alguien que sí tenga experiencia programando en MQL5, que ya haya solucionado este error y que sí tenga ganas de ayudarme.

 
gcasellato #:

El trabajo ya fue realizado por mi, ya que soy yo el que escribió el código que copié.

Tampoco necesito contratar a un programador, ya que, como ya mencioné, soy el autor del código.

Seguramente haya alguien que sí tenga experiencia programando en MQL5, que ya haya solucionado este error y que sí tenga ganas de ayudarme.

En ese caso, el problema es aún más grave.

Comience por corregir todos los errores de compilación. Después de eso, añada declaraciones de "Print" en puntos clave para verificar a través de los registros que todo está funcionando correctamente, incluyendo los cálculos, entre otros aspectos.

Esto le ayudará a identificar posibles fallos. Normalmente, el problema suele estar en que los TP/SL (Take Profit/Stop Loss) están mal calculados y posteriormente se aplican incorrectamente a la orden de apertura.

Si estos valores son incorrectos, la orden será rechazada, como parece ser su caso.

En cualquier caso, es importante ser más preciso y directo al enfrentar un problema. Me resulta difícil creer que haya sido capaz de desarrollar un EA de 600 líneas y, sin embargo, ante un problema tan común, la única solución que considere sea publicar el código completo en el foro y esperar a que alguien le ayude. Algo aquí no encaja...

 
Miguel Angel Vico Alba #:

En ese caso, el problema es aún más grave.

Comience por corregir todos los errores de compilación. Después de eso, añada declaraciones de "Print" en puntos clave para verificar a través de los registros que todo está funcionando correctamente, incluyendo los cálculos, entre otros aspectos.

Esto le ayudará a identificar posibles fallos. Normalmente, el problema suele estar en que los TP/SL (Take Profit/Stop Loss) están mal calculados y posteriormente se aplican incorrectamente a la orden de apertura.

Si estos valores son incorrectos, la orden será rechazada, como parece ser su caso.

En cualquier caso, es importante ser más preciso y directo al enfrentar un problema. Me resulta difícil creer que haya sido capaz de desarrollar un EA de 600 líneas y, sin embargo, ante un problema tan común, la única solución que considere sea publicar el código completo en el foro y esperar a que alguien le ayude. Algo aquí no encaja...

El código compila perfectaente. No tiene errores. Simplemente no lo copié en su totalidad debido a la cantidad máxima de caracteres permitida en el mensaje.
Gracias Miguel. Fuiste de gran ayuda.
 
gcasellato #:

Le recomiendo que evite trabajar con órdenes pendientes, y si decide utilizarlas, es crucial que tenga en cuenta detalles importantes, como establecer una fecha y hora de caducidad, entre otros aspectos.

Dicho esto, si busca una solución más sencilla y directa, le sugiero que opte por órdenes instantáneas, al menos al principio, hasta asegurarse de que todo lo demás funciona correctamente.

Personalmente, no tengo nada en contra de las órdenes pendientes, pero como mencioné, requieren un conocimiento profundo de su funcionamiento, ya que tienen varios matices que deben ser considerados.

Y, sobre todo, asegúrese de revisar que los TP/SL (Take Profit/Stop Loss) estén bien calculados. Este suele ser el problema en la mayoría de los casos.