open opposite position immediately after hit SL issue

 

When a certain buy condition is met, I want to open a buy position and set the take profit (TP) and stop loss (SL) based on the candle length.

I found a Martingale strategy on Forex Factory that is similar to what I want. The main function of this Martingale strategy is that when a buy position hits the SL, it opens an opposite sell position with 2x the lot size.

It is working, but it does not open the sell position immediately once the buy position hits the SL.

Here is the code I modified, but it still does not open immediately.

Any help would be much appreciated!

i edited this code but it sill not working well.

double barLength = High[1] - Low[1];
           if(OrderType() == OP_BUY) {
              if(OrderOpenPrice() > OrderClosePrice()) {
                 SendOrder(Symbol(), OP_SELL, OrderLots() * multiply, Bid, 3, Bid + barLength, Bid - barLength, "martingale sell", magic, Red);
              } else {
                 SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
              }

here is full code

#property copyright "Copyright 2015, Tomas RD"
#property link      "https://www.mql5.com"
#property version   "1.01"
#property strict

int MagicNumber=1;
extern int magic=3059823;
extern double lotes=0.01;
extern bool UseRisk = FALSE;
extern double Risk = 0.1; 
extern double stop_loss=30;
extern double take_profit =30;
extern double multiply=2.5;
extern string INDICATOR_PARAMETER1 ="=========Candle==========";
extern int SHIFT_CANDLE=1;
double lots=0.01;
int TP=20;
int SL=20;

extern string INDICATOR_PARAMETER2 ="=========Volumes==========";
extern int SHIFT_VOLUME=1;
double Scale, stop_loss_v, take_profit_v;
int LOTS, x, f, g, h, k, y, z, jumlahbuy, jumlahbuylimit, jumlahselllimit, jumlahsell, jumlahbuystop, jumlahsellstop;
double BUY[99], SELL[99], BUYLIMIT[99], SELLLIMIT[99], BUYSTOP[99], SELLSTOP[99], BATAS;
int prec=0;
int a=0;
double pt, i, minlot, stoplevel;
color FontColorUp1 = Red;  
color FontColorDn1 = White; 
color FontColor = Blue;
color FontColorUp2 = Yellow;  
color FontColorDn2 = Lime; 
color FontUP = Lime;  
color Font = White; 
color FontDOWN = Red; 

double initialBarLength = 0;
bool buyConditionMet = false;

int OnInit() {
   switch(Digits) {
      case 1: Scale = 0.1; break;
      case 2: Scale = 0.01; break;
      case 3: Scale = 0.01; break;
      case 4: Scale = 0.0001; break;
      case 5: Scale = 0.0001; break;
   }
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason) {
   for(int i=1; i<=50; i++) {
      ObjectDelete("Market_Price_Label" + IntegerToString(i));
   }
}

void OnTick() {
   if(lotesMarginFree() >= MarketInfo(NULL, MODE_MINLOT)) {
      if (UseRisk == TRUE) lotes = (AccountFreeMargin() / 10000) * Risk;
      if(vol_ea() == 1 ) {
         initialBarLength = High[1] - Low[1];
         //buyConditionMet = true/
         OpenMartingale();
      }
   }
   modifyOrders();
}

void modifyOrders() {
   double tp, sl;
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
         if(OrderMagicNumber() == magic) {
            if(buyConditionMet) {
               double barLength = initialBarLength;

               if(OrderType() == OP_BUY) {
                  sl = OrderOpenPrice() - barLength;
                  tp = OrderOpenPrice() + barLength;
               }
               if(OrderType() == OP_SELL) {
                  sl = OrderOpenPrice() + barLength;
                  tp = OrderOpenPrice() - barLength;
               }

               sl = NormalizeDouble(sl, Digits);
               tp = NormalizeDouble(tp, Digits);

               if(OrderTakeProfit() == 0 && OrderStopLoss() == 0) {
                  int p = OrderModify(OrderTicket(), OrderOpenPrice(), sl, tp, 0);
                  if (p == 0) {
                     Print("OrderModify failed with error #", GetLastError());
                  }
               }

               if(OrderType() == OP_BUY && Bid <= sl) {
                  OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrRed);
                  SendOrder(Symbol(), OP_SELL, OrderLots(), Bid, 3, Bid + barLength, Bid - barLength, "Opposite sell", magic, Red);
               }
               if(OrderType() == OP_SELL && Ask >= sl) {
                  OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrBlue);
                  SendOrder(Symbol(), OP_BUY, OrderLots(), Ask, 3, Ask - barLength, Ask + barLength, "Opposite buy", magic, Blue);
               }

               if(OrderType() == OP_BUY && Bid >= tp) {
                  OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrGreen);
                 
               }
               if(OrderType() == OP_SELL && Ask <= tp) {
                  OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrGreen);
               
               }
            }
         }
      }
   }
}

void OpenMartingale() {
   int value = 0;
   int martingaleLevel = 0;

   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
         if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
            value++;
            if(OrderComment() == "martingale buy" || OrderComment() == "martingale sell") {
               martingaleLevel++;
            }
         }
      }
   }

   if(martingaleLevel >= 3) {
      Print("Maximum Martingale level reached. No new Martingale orders will be placed.");
      return;
   }

   if(value == 0) {
      for(int i=OrdersHistoryTotal()-1; i>=0; i--) {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) {
            if(OrderMagicNumber() == magic && OrderSymbol() == Symbol()) {
               value++;
               double barLength = High[1] - Low[1];
               if(OrderType() == OP_BUY) {
                  if(OrderOpenPrice() > OrderClosePrice()) {
                     SendOrder(Symbol(), OP_SELL, OrderLots() * multiply, Bid, 3, Bid + barLength, Bid - barLength, "martingale sell", magic, Red);
                  } else {
                     SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
                  }
               }
               if(OrderType() == OP_SELL) {
                  if(OrderOpenPrice() < OrderClosePrice()) {
                     SendOrder(Symbol(), OP_BUY, OrderLots() * multiply, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
                  } else {
                     SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
                  }
               }
               break;
            }
         }
      }
   }
   if(value == 0) {
      double barLength = High[1] - Low[1];
      SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);
   }
}

void SendOrder(string symbol, int type, double lot, double price_s, int slippage_v, double stop_loss_v, double take_profit_v, string comment, int magic_v, color color_v) {
   int countTentative = 3;
   int tentative = 0;
   int ticket = 0;             
   while(IsConnected() && ticket < 1 && tentative <= countTentative) {
      RefreshRates();
      ticket = OrderSend(symbol, type, lot, price_s, slippage_v, stop_loss_v, take_profit_v, comment, magic_v, 0, color_v);
      Sleep(1000);            
      tentative++;
   }
}

void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam) {
   if(id == CHARTEVENT_OBJECT_CLICK) { 
      if(sparam == "sell_option") {
         stop_loss_v = Bid + stop_loss * Scale;
         take_profit_v = Bid - take_profit * Scale;         
         SendOrder(Symbol(), OP_SELL, lotes, Bid, 3, stop_loss_v, take_profit_v, "sell", magic + 1, Red);
      }
      if(sparam == "buy_option") {
         stop_loss_v = Ask - stop_loss * Scale;
         take_profit_v = Ask + take_profit * Scale;         
         SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, stop_loss_v, take_profit_v, "buy", magic + 1, Blue);
      }
      if(sparam == "close_this_option") {
         closeOrdersSymbol();
      }
      if(sparam == "close_all_option") {
         closeOrdersAll();
      }                 
   }     
}

void closeOrdersSymbol() {
   int p;
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
         if(OrderMagicNumber() == magic + 1 && OrderSymbol() == Symbol()) {
            if(OrderType() == OP_BUY) {
               p = OrderClose(OrderTicket(), OrderLots(), Bid, 3, clrSkyBlue);
            } else {
               p = OrderClose(OrderTicket(), OrderLots(), Ask, 3, clrPink);
            }                                 
         }
      }
   }
}

void closeOrdersAll() {
   int p;
   for(int i=OrdersTotal()-1; i>=0; i--) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
         if(OrderMagicNumber() == magic + 1) {
            if(OrderType() == OP_BUY) {
               p = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 3, clrSkyBlue);
            } else {
               p = OrderClose(OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 3, clrPink);
            }                                 
         }
      }
   }
}

double lotesMarginFree() {
   double MargRequired = MarketInfo(Symbol(), MODE_MARGINREQUIRED); // current price * 1000
   double Equity = AccountEquity();
   return NormalizeDouble(Equity / MargRequired, 1);  
}

int vol_ea() {
   y = 0; f = 0; g = 0; h = 0; k = 0; z = 0; jumlahbuy = 0; jumlahsell = 0; jumlahbuylimit = 0; jumlahselllimit = 0; jumlahsellstop = 0; jumlahbuystop = 0;

   //////////CANDLE///////
   double OPEN_3 = iOpen(Symbol(), 0, SHIFT_CANDLE);
   double OPEN_2 = iOpen(Symbol(), 0, SHIFT_CANDLE + 2);
   double OPEN_1 = iOpen(Symbol(), 0, SHIFT_CANDLE + 3);

   double CLOSE_3 = iClose(Symbol(), 0, SHIFT_CANDLE);
   double CLOSE_2 = iClose(Symbol(), 0, SHIFT_CANDLE + 2);
   double CLOSE_1 = iClose(Symbol(), 0, SHIFT_CANDLE + 3);

   ////CANDLE 1////
   double BULLISH = CLOSE_3 > OPEN_3;
   double BEARISH = CLOSE_3 < OPEN_3;                      

   /////////////VOLUME//////////
   double VOLUME_3 = iVolume(Symbol(), 0, SHIFT_VOLUME);
   double VOLUME_2 = iVolume(Symbol(), 0, SHIFT_VOLUME + 1);
   double VOLUME_1 = iVolume(Symbol(), 0, SHIFT_VOLUME + 2);
   double VOLUME_0 = iVolume(Symbol(), 0, SHIFT_VOLUME + 3);
   double VOLUME_LALU = iVolume(Symbol(), 0, SHIFT_VOLUME + 4);

   double VOLUME_OP = ((VOLUME_0 < VOLUME_1) && (VOLUME_1 < VOLUME_2) && (VOLUME_2 < VOLUME_3));

   if(jumlahbuy + jumlahsell == 0) {
      if (BEARISH == true && VOLUME_OP == true) {
         return(1);
      }                 
      if (BULLISH == true && VOLUME_OP == true) {
         return(1);
      } 
   }

   return(0);
}

 
  1. Jeon Suman: It is working, but it does not open the sell position immediately once the buy position hits the SL.

    EAs must be coded to recover. If the power fails, OS crashes, terminal or chart is accidentally closed, on the next tick, any static / global ticket variables will have been lost. You will have an open order / position but don't know it, so the EA will never try to close it, trail SL, etc. How are you going to recover?

    See if you have an open order. If not, find the last closed order. If it was by SL, open your next opposite one. Otherwise test for your initial condition.

  2. Jeon Suman: I found a Martingale strategy on Forex Factory that is similar to what I want

    Martingale is not a strategy. It's a betting system.

    Hedging, grid trading, same as Martingale.
              Martingale, Hedging and Grid : MHG - General - MQL5 programming forum (2016)

    Martingale, guaranteed to blow your account eventually. If your strategy is not profitable without, it is definitely not profitable with.
              Martingale vs. Non Martingale (Simplified RoR vs Profit and the Illusions) - MQL5 programming forum (2015)

    Why it won't work:
              Calculate Loss from Lot Pips - MQL5 programming forum (2017)
              THIS Trading Strategy is a LIE... I took 100,000 TRADES with the Martingale Strategy - YouTube (2020)
              Does a safe Martingale exist ? - Trading Systems - MQL5 programming forum (2010)

  3.                  SendOrder(Symbol(), OP_BUY, lotes, Ask, 3, Ask - barLength, Ask + barLength, "martingale buy", magic, Blue);

    You buy at the Ask and sell at the Bid. Pending Buy Stop orders become market orders when hit by the Ask.

    1. Your buy order's TP/SL (or Sell Stop's/Sell Limit's entry) are triggered when the Bid / OrderClosePrice reaches it. Using Ask±n, makes your SL shorter and your TP longer, by the spread. Don't you want the specified amount used in either direction?

    2. Your sell order's TP/SL (or Buy Stop's/Buy Limit's entry) will be triggered when the Ask / OrderClosePrice reaches it. To trigger close at a specific Bid price, add the average spread.
                MODE_SPREAD (Paul) - MQL4 programming forum - Page 3 #25

    3. Prices (open, SL, and TP) must be a multiple of ticksize. Using Point means code breaks on 4 digit brokers (if any still exists), exotics (e.g. USDZAR where spread is over 500 points), and metals. Compute what a logical PIP is and use that, not points.
                How to manage JPY pairs with parameters? - MQL4 programming forum (2017)
                Slippage defined in index points - Expert Advisors and Automated Trading - MQL5 programming forum (2018)

    4. The charts show Bid prices only. Turn on the Ask line to see how big the spread is (Tools → Options (control+O) → charts → Show ask line.)

      Most brokers with variable spreads widen considerably at end of day (5 PM ET) ± 30 minutes.
      My GBPJPY shows average spread = 26 points, average maximum spread = 134.
      My EURCHF shows average spread = 18 points, average maximum spread = 106.
      (your broker will be similar).
                Is it reasonable to have such a huge spreads (20 PIP spreads) in EURCHF? - General - MQL5 programming forum (2022)

  4.    for(int i=OrdersTotal()-1; i>=0; i--) {
          if(OrderSelect(i,SELECT_BY_POS,MODE_OPEN)) {
             if(OrderMagicNumber() == magic) {
    

    Magic number only allows an EA to identify its trades from all others. Using OrdersTotal/OrdersHistoryTotal (MT4) or PositionsTotal (MT5), directly and/or no Magic number/symbol filtering on your OrderSelect / Position select loop means your code is incompatible with every EA (including itself on other charts and manual trading.)
              Symbol Doesn't equal Ordersymbol when another currency is added to another seperate chart . - MQL4 programming forum (2013)
              PositionClose is not working - MQL5 programming forum (2020)
              MagicNumber: "Magic" Identifier of the Order - MQL4 Articles (2006)
              Orders, Positions and Deals in MetaTrader 5 - MQL5 Articles (2011)
              Limit one open buy/sell position at a time - General - MQL5 programming forum (2022)

    You need one Magic Number for each symbol/timeframe/strategy.
         Trade current timeframe, one strategy, and filter by symbol requires one MN.
         If trading multiple timeframes, and filter by symbol requires use a range of MN (base plus timeframe).
              Why are MT5 ENUM_TIMEFRAMES strange? - General - MQL5 programming forum - Page 2 #11 (2020)