Invalid Stops and Closing trade

 

Hi Everyone, 


I'm developing my EA. The thing is that I want to make only one trade each time. How can I check If the current trade is open in order to avoid the enterTrade functionality while it is opened?


And also I've noticed that I had some problems related to "failed market sell 0.1 XAUEUR sl: 1877.52 tp: 1869.75 [Invalid stops]"


Here's my code:


//+------------------------------------------------------------------+
//|                                                    fvg_test1.mq5 |
//|                                                              EGD |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "EGD"
#property link      "https://www.mql5.com"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Includes                                                         |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <errordescription.mqh>
#include <MQLTA Utils.mqh>

//+------------------------------------------------------------------+
//| Variables                                                        |
//+------------------------------------------------------------------+
struct Zone
  {
   double            Max;
   double            Min;
   double            long_or_short; // 1 long and 0 short
   datetime          timestamp;
   double            middleCandleMax;
   double            middleCandleMin;
   double            firstCandleMax;
   double            firstCandleMin;
  };

enum ENUM_CONSIDER
  {
   All = -1,                  // All orders
   Buy = POSITION_TYPE_BUY,   // Buy only
   Sell = POSITION_TYPE_SELL, // Sell only
  };

Zone zones[];

// Trade parameters
CTrade* trade;
double stopLoss;
double takeProfit;
double TPratio;

// Inputs
input bool EnableFullFVG = false;
input bool EnableReversalFVG = false;
input bool EnableOppositeReversalFVG = false;
input bool EnableHesitantFVG = false;
input long InpMagicNumber = 123456;
input long InpStopLoss = 150;
input bool EnableTrailingParam = false;
input bool OnlyCurrentSymbol = true;
input bool UseMagic = false; // Filter by magic number
input int MagicNumber = 0; // Magic number (if above is true)
input bool UseComment = false; // Filter by comment
input string CommentFilter = ""; // Comment (if above is true)
input ENUM_CONSIDER OnlyType = All; // Apply to
input int TrailingStop = 50; // Trailing Stop, points
input int Profit = 100; // Profit in points when TS should kick in.
input bool SwingSL = false;
input bool MiddleCandleSL = false;
input double riskPercent = 0.1; // Risk 10% of the account balance per trade

// Other variables
bool EnableTrailing = EnableTrailingParam;
int OrderOpRetry = 5; // Number of position modification attempts
double swingLongSL;
double swingShortSL;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
void OnInit()
  {
   EnableTrailing = EnableTrailingParam;
   trade = new CTrade;
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete trade;
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.hour = 22;
   structTime.min = 0;
   structTime.sec = 0;
   datetime timeClose = StructToTime(structTime);

   MqlDateTime structTime2;
   TimeCurrent(structTime2);
   structTime2.hour = 22;
   structTime2.min = 0;
   structTime2.sec = 2;
   datetime timeClose2 = StructToTime(structTime2);

// Check if the current time is past the end of day time
   if(TimeCurrent() > timeClose && TimeCurrent() < timeClose2)
     {
      // Empty the 'zones' array
      ArrayFree(zones);
      Print("Array 'zones' has been emptied because it's the end of the day.");
     }

   if(EnableFullFVG)
      full_FVG();
   if(EnableReversalFVG)
      reversal_FVG();
   if(EnableOppositeReversalFVG)
      opposite_Reversal_FVG();
   if(EnableHesitantFVG)
      hesitant_FVG();

// update swing array
   if(iLow(Symbol(),Period(),1) < iLow(Symbol(),Period(),0) && iLow(Symbol(),Period(),1) < iLow(Symbol(),Period(),2))
     {
      swingLongSL = iLow(Symbol(),Period(),1);
     }
   else
      if(iHigh(Symbol(),Period(),1) > iHigh(Symbol(),Period(),0) && iHigh(Symbol(),Period(),1) > iHigh(Symbol(),Period(),2))
        {
         swingShortSL = iHigh(Symbol(),Period(),1);
        }

   for(int i = 0; i < ArraySize(zones); i++)
     {

      // short
      if(zones[i].long_or_short == 0)
        {
         enterTrade(0, zones[i]);
         ArrayRemove(zones, i-1, 1);
        }

      // long
      else
         if(zones[i].long_or_short == 1)
           {
            enterTrade(1, zones[i]);
            ArrayRemove(zones, i-1, 1);
           }
     }

// update stop loss
   TrailingStop();
  }

//+------------------------------------------------------------------+
//| On trade Handling                                                |
//+------------------------------------------------------------------+
void OnTrade()
  {
  }

//+------------------------------------------------------------------+
//| FVG Types                                                        |
//+------------------------------------------------------------------+
void full_FVG()
  {
    //zone logic
  }
void reversal_FVG()
  {
    //zone logic
  }
void opposite_Reversal_FVG()
  {
    //zone logic
  }
void hesitant_FVG()
  {
    //zone logic
  }
void DetectZone(bool conditionForZone, double zoneMax, double zoneMin, double longOrShort, string FVGType)
  {
    //zone logic
  }

//+------------------------------------------------------------------+
//| Enter trade Calculations                                         |
//+------------------------------------------------------------------+

void enterTrade(int BuyOrSell, Zone &zone)
  {
   if(PositionsTotal()==0)
     {
      double tradeSizeAux = CalculateTradeSize() / SymbolInfoDouble(_Symbol, SYMBOL_LAST);
      double tradeSize = NormalizeDouble(tradeSizeAux, 2);

      // Short Position
      if(BuyOrSell == 0)
        {

         if(MiddleCandleSL)
           {

            if(zone.middleCandleMax > zone.firstCandleMax)
              {
               stopLoss = NormalizeDouble(zone.middleCandleMax + _Point, _Digits);
              }
            else
              {
               stopLoss = NormalizeDouble(zone.firstCandleMax + _Point, _Digits);
              }
           }

         else
            if(SwingSL)
              {
               stopLoss = NormalizeDouble(swingShortSL + 2*_Point, _Digits);
              }

         takeProfit = NormalizeDouble((SymbolInfoDouble(_Symbol, SYMBOL_LAST) - (SymbolInfoDouble(_Symbol, SYMBOL_LAST) - stopLoss)*TPratio), _Digits);

         Print("PRICE --> " + SymbolInfoDouble(_Symbol, SYMBOL_LAST) + " // SL --> " + stopLoss + " // TP --> " + takeProfit + " // TRADE SIZE --> " + tradeSize);

         trade.PositionOpen(_Symbol, ORDER_TYPE_SELL, 0.1, SymbolInfoDouble(_Symbol, SYMBOL_LAST), stopLoss, takeProfit);
        }

      // Long Position
      else
         if(BuyOrSell == 1)
           {
            if(MiddleCandleSL)
              {
               if(zone.middleCandleMin < zone.firstCandleMin)
                 {
                  stopLoss = NormalizeDouble(zone.middleCandleMin - _Point, _Digits);
                 }
               else
                 {
                  stopLoss = NormalizeDouble(zone.firstCandleMin - _Point, _Digits);
                 }
              }

            else
               if(SwingSL)
                 {
                  stopLoss = NormalizeDouble(swingLongSL - 2*_Point, _Digits);
                 }

            takeProfit = NormalizeDouble((SymbolInfoDouble(_Symbol, SYMBOL_LAST) + (SymbolInfoDouble(_Symbol, SYMBOL_LAST) - stopLoss)*TPratio), _Digits);

            Print("PRICE --> " + SymbolInfoDouble(_Symbol, SYMBOL_LAST) + " // SL --> " + stopLoss + " // TP --> " + takeProfit + " // TRADE SIZE --> " + tradeSize);

            trade.PositionOpen(_Symbol, ORDER_TYPE_BUY, 0.1, SymbolInfoDouble(_Symbol, SYMBOL_LAST), stopLoss, takeProfit);
           }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

// CalculateTradeSize function that returns a trade size based on a fixed percentage of the account balance
double CalculateTradeSize()
  {
   double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); // Get the current account balance
   double tradeSize = accountBalance * riskPercent; // Calculate the trade size
   return NormalizeDouble(tradeSize, 2); // Normalize the trade size to 2 decimal places
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void TrailingStop()
  {
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {

      ulong ticket = PositionGetTicket(i);

      if(ticket <= 0)
        {
         int Error = GetLastError();
         string ErrorText = ErrorDescription(Error);
         Print("ERROR - Unable to select the position - ", Error);
         Print("ERROR - ", ErrorText);
         break;
        }

      // Trading disabled.
      if(SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED)
         continue;

      // Filters.
      if((OnlyCurrentSymbol) && (PositionGetString(POSITION_SYMBOL) != Symbol()))
         continue;
      if((UseMagic) && (PositionGetInteger(POSITION_MAGIC) != MagicNumber))
         continue;
      if((UseComment) && (StringFind(PositionGetString(POSITION_COMMENT), CommentFilter) < 0))
         continue;
      if((OnlyType != All) && (PositionGetInteger(POSITION_TYPE) != OnlyType))
         continue;

      double point = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_POINT);

      // Normalize trailing stop value to the point value.
      double TSTP = TrailingStop * point;
      double P = Profit * point;

      double Bid = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_BID);
      double Ask = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_ASK);
      double OpenPrice = PositionGetDouble(POSITION_PRICE_OPEN);
      double StopLoss = PositionGetDouble(POSITION_SL);
      double TakeProfit = PositionGetDouble(POSITION_TP);
      int eDigits = (int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_DIGITS);
      double TickSize = SymbolInfoDouble(OrderSymbol(), SYMBOL_TRADE_TICK_SIZE);

      if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
        {
         if(NormalizeDouble(Bid - OpenPrice, eDigits) >= NormalizeDouble(P, eDigits))
           {
            double new_sl = NormalizeDouble(Bid - TSTP, eDigits);
            if(TickSize > 0)  // Adjust for tick size granularity.
              {
               new_sl = NormalizeDouble(MathRound(new_sl / TickSize) * TickSize, eDigits);
              }
            if((TSTP != 0) && (StopLoss < new_sl))
              {
               ModifyPosition(ticket, OpenPrice, new_sl, TakeProfit, PositionGetString(POSITION_SYMBOL));
              }
           }
        }
      else
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
           {
            if(NormalizeDouble(OpenPrice - Ask, eDigits) >= NormalizeDouble(P, eDigits))
              {
               double new_sl = NormalizeDouble(Ask + TSTP, eDigits);
               if(TickSize > 0)  // Adjust for tick size granularity.
                 {
                  new_sl = NormalizeDouble(MathRound(new_sl / TickSize) * TickSize, eDigits);
                 }
               if((TSTP != 0) && ((StopLoss > new_sl) || (StopLoss == 0)))
                 {
                  ModifyPosition(ticket, OpenPrice, new_sl, TakeProfit, PositionGetString(POSITION_SYMBOL));
                 }
              }
           }
     }
  }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void ModifyPosition(ulong Ticket, double OpenPrice, double SLPrice, double TPPrice, string symbol)
  {
   for(int i = 1; i <= OrderOpRetry; i++)  // Several attempts to modify the position.
     {
      bool result = trade.PositionModify(Ticket, SLPrice, TPPrice);
      if(result)
        {
         Print("TRADE - UPDATE SUCCESS - Order ", Ticket, " new stop-loss ", SLPrice);
         //NotifyStopLossUpdate(Ticket, SLPrice, symbol);
         break;
        }
      else
        {
         int Error = GetLastError();
         string ErrorText = ErrorDescription(Error);
         Print("ERROR - UPDATE FAILED - error modifying order ", Ticket, " return error: ", Error, " Open=", OpenPrice,
               " Old SL=", PositionGetDouble(POSITION_SL),
               " New SL=", SLPrice, " Bid=", SymbolInfoDouble(symbol, SYMBOL_BID), " Ask=", SymbolInfoDouble(symbol, SYMBOL_ASK));
         Print("ERROR - ", ErrorText);
        }
     }
  }


Thanks in advance!


 
Eric Gonzalez:
How can I check If the current trade is open in order to avoid the enterTrade functionality while it is opened?

Do you mean to stop opening new trade if there's an open trade? If that's the case you can store the ticket of the open trade and if you close the trade you set the ticket variable to 0 for next signal.

Eric Gonzalez:
"failed market sell 0.1 XAUEUR sl: 1877.52 tp: 1869.75 [Invalid stops]"

Invalid stop related to stoploss and take profit placement and also stop level. First check if stoploss price and take profit price is correct, stoploss below open price and take profit above open price for buy position and stoploss above open price and take profit below open price if it's sell.

If stoploss price and take profit price is correct you can check stop level. Stop level related to minimum stoploss and take profit price away from open price.