15

I have written the code below that opens a buy and sell trade (a certain number of pips above and below the ask and bid price) at a specific time.

  1. How can I close/cancel one immediately when the other is opened?

  2. How can I close the opened trade if it's say X pips in profit or after a minute (depending on which condition is reached first)?

I'm a not too sure I've done the right thing in the code below and would really appreciate some help.

double spread = Ask-Bid;
extern datetime time;
extern int pipGap = 7;
extern int lotSize = 0.01;
extern int closeTimeInSeconds = 60;


int start() {
  if (TimeCurrent() >= StrToTime(time)){

    OrderSend(Symbol(),OP_BUYSTOP,lotSize, Ask + Point*pipGap, 0,0,0);
    OrderSend(Symbol(),OP_SELLSTOP,lotSize, Bid - Point*pipGap, 0,0,0);


    }


for(int pos = OrdersTotal()-1; pos >= 0 ; pos--) if (
    OrderSelect(pos, SELECT_BY_POS)           
){              
    int duration = TimeCurrent() - OrderOpenTime();
    if (duration >= closeTimeInSeconds)
         OrderClose( OrderTicket(), OrderLots(), OrderClosePrice(),
                     3*Point);
}

   return(0);
}
NotEveryDay
  • 153
  • 1
  • 5
  • Thanks NotEveryDay for inviting me to this post. What @iGetIt essentially wants is a News Trading bot that places a net to trap spikes (eg Interest Rate hike kinda trap). Not very useful for high swing events (eg NFP). I just read this, I've built a pretty complex NewsTrader before. Gotta break it into parts to address your question and the bounty. Will revert in a bit. – jlee88my May 14 '19 at 02:54
  • 1
    @iGetIt --> See solution in the Answer section. – jlee88my May 14 '19 at 06:16

2 Answers2

8

AUTOMATED NEWS TRADING What you (@iGetIt ) are looking for is a rudimentary News Trading bot. Here's a diluted implementation for it.

In the more advanced stages, you will need to automatically download news and auto-trade base on the affected pairs, track volatility (to avoid swings), sync your PC time (Windows date/time is NOT accurate and news trading need to be synced to the millisecond level). Track your broker server response time, implement Trailing-StopLoss (for improved profit), implement slide-in-orders (multiple stop orders to catch huge spikes), calculate order-set profitability (to know when to close all the orders when price retrace), etc etc.

Anyway, here's a basic version that you can play with (based on the Bounty requirements):

  1. Opens buy + sell stop-orders at specific time.
  2. Configurable number of pips AWAY from current ask/bid.
  3. Implements OCO (One Cancels the Other).
  4. Closes executed trades with x-pip profit (aka TP level).
  5. Closes executed or outstanding stop-orders after x-seconds.

Visual: To show that it executes in time (this is Asian time, so liquidity is low, so +- a few seconds before price ticks). enter image description here


Closing: It closes automatically based on the settings. enter image description here

SOURCE CODE: And this is the complete MQL4 source-code for it.

(UPDATED 15May19 1045 GMT+8) to fix bug as reported in the closing of executed orders after TTL.

//+------------------------------------------------------------------+
//|                                                                 SO55930471.mq4 |
//|                   Copyright 2019, Joseph Lee, joseph.lee@fs.com.my |
//|                                                       TELEGRAM @JosephLee74 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, Joseph Lee, TELEGRAM @JosephLee74"
#property link      "http://www.fs.com.my"
#property version   "1.00"
#property strict


//-------------------------------------------------------------------
// APPLICABLE PARAMETERS
//-------------------------------------------------------------------
//-------------------------------------------------------------------
// NEWS IMPACT SELECTION
//===================================================================
extern string       vsEAComment                         = "Telegram @JosephLee74";      //Ego trip
extern datetime vdTradeStartInGMT                   = D'2019.5.14 06:00';           //When to trade (GMT)
extern int          viStopOrderLevelInPip           = 5;                    // StopOrder distance from ask/bid (pips)
extern double       viFixLots                           = 0.01;             // Lot size
extern int          viStopLossInPip                 = 20;                   // StopLoss (pips)
extern int          viTargetProfitInPip             = 100;              // TargetProfit (pips)
extern int          viDeleteStopOrderAfterInSec = 30;                   // StopOrder TTL (sec)
extern int          viDeleteOpenOrderAfterInSec = 300;              // Executed Order TTL (sec)
extern int          viMaxSlippageInPip              = 2;                    // Max Slippage (pip)


//-------------------------------------------------------------------
// System Variables
//-------------------------------------------------------------------
int     viMagicId                   = 0;
double  viPipsToPrice               = 0.0001;
double  viPipsToPoint               = 1;
int     viBuyStopTicket         = -1;
int     viSellStopTicket            = -1;
int     viBuyOrderTicket            = -1;
int     viSellOrderTicket           = -1;
string  vsDisplay                   = "EVENT-TRADER v1.01 - ";

//-------------------------------------------------------------------



//+------------------------------------------------------------------+
//| EA Initialization function
//+------------------------------------------------------------------+
int init() {
    ObjectsDeleteAll(); Comment("");
    // Caclulate PipsToPrice & PipsToPoints (old sytle, but works)
    if((Digits == 2) || (Digits == 3)) {viPipsToPrice=0.01;}
    if((Digits == 3) || (Digits == 5)) {viPipsToPoint=10;}
    viMagicId = vdTradeStartInGMT;
    start();
    return(0);
}
//+------------------------------------------------------------------+
//| EA Stand-Down function
//+------------------------------------------------------------------+
int deinit() {
    ObjectsDeleteAll();
    return(0);
}


//============================================================
// MAIN EA ROUTINE
//============================================================
int start() {

    //==========================================
    //MANAGE ROBOT EXPIRY
    //==========================================
    if( TimeCurrent() > D'2020.1.1' ) {
        Comment(vsDisplay + "EXPIRED. Please contact josephfhlee74 at gmail dot com"); // Who am I kidding?
        return(0);
    }


    ResetLastError();
    // Exit the routine if it is not time to trade yet.
    if(TimeGMT() < vdTradeStartInGMT) {
        // Show a count-down timer to the trading time.
        Comment(vsDisplay +
            "[" + TimeToStr(TimeGMT()) + " GMT] " + 
            IntegerToString(int(vdTradeStartInGMT - TimeGMT())) + " sec to [" + 
            TimeToStr(vdTradeStartInGMT) + " GMT]"
        );
        return(0);
    }


    viBuyStopTicket     = -1;
    viSellStopTicket        = -1;
    viBuyOrderTicket        = -1;
    viSellOrderTicket       = -1;
    //=========================================================
    //FIND *OPENED* BUY/SELL PENDING ORDERS
    //---------------------------------------------------------
    for( int i=OrdersTotal()-1; i>=0; i-- ) {
        if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
            if( OrderSymbol() == Symbol() )
                if( OrderMagicNumber() == viMagicId) {
                    if( OrderType() == OP_BUYSTOP )
                        viBuyStopTicket  = OrderTicket();
                    if( OrderType() == OP_SELLSTOP )
                        viSellStopTicket  = OrderTicket();
                    if( OrderType() == OP_BUY )
                        viBuyOrderTicket  = OrderTicket();
                    if( OrderType() == OP_SELL )
                        viSellOrderTicket  = OrderTicket();
                }
    }
    //=========================================================
    //FIND *CLOSED* BUY/SELL ORDERS FOR THIS EVENT
    //---------------------------------------------------------
    for(int i=OrdersHistoryTotal()-1; i>=0; i--) {
        if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
            if(OrderSymbol() == Symbol())
                if(OrderMagicNumber() == viMagicId) {
                    if( OrderType() == OP_BUYSTOP )
                        viBuyStopTicket  = OrderTicket();
                    if( OrderType() == OP_SELLSTOP )
                        viSellStopTicket  = OrderTicket();
                    if( OrderType() == OP_BUY )
                        viBuyOrderTicket  = OrderTicket();
                    if( OrderType() == OP_SELL )
                        viSellOrderTicket  = OrderTicket();
                }
    }
    // The above 2 sections will ensure that each event will only be executed once.
    // If orders are cancelled or closed for whatever reason, they will never be open again.

    string vsVerbose     =  vsDisplay + "[GMT " + TimeToStr(TimeGMT()) + "] Executing ..."
                                    "\nActive BUYSTOP: " + viBuyStopTicket +
                                    "  |  Active SELLSTOP: " + viSellStopTicket +
                                    "" +
                                    "\nActive BUY: " + viBuyOrderTicket +
                                    "  |  Active SELL: " + viSellOrderTicket;
    Comment(vsVerbose);


    //=========================================================
    // HANDLES OCO (One-Cancels-the-Other)
    //---------------------------------------------------------
    // BUY Order EXISTS, cancels all SellStops
    if( viBuyOrderTicket != -1 ) {
        for( int i=OrdersTotal()-1; i>=0; i-- ) {
            if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
                if( OrderSymbol() == Symbol() )
                    if( OrderMagicNumber() == viMagicId)
                        if( OrderType() == OP_SELLSTOP )
                            OrderDelete(OrderTicket());
        }
    }
    // SELL Order EXISTS, cancels all BuyStops
    if( viSellOrderTicket != -1 ) {
        for( int i=OrdersTotal()-1; i>=0; i-- ) {
            if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
                if( OrderSymbol() == Symbol() )
                    if( OrderMagicNumber() == viMagicId)
                        if( OrderType() == OP_BUYSTOP )
                            OrderDelete(OrderTicket());
        }
    }

    //=========================================================
    //CLOSE EXPIRED STOP/EXECUTED ORDERS
    //---------------------------------------------------------
    for( int i=OrdersTotal()-1; i>=0; i-- ) {
        if(OrderSelect( i, SELECT_BY_POS, MODE_TRADES ))
            if( OrderSymbol() == Symbol() )
                if( OrderMagicNumber() == viMagicId) {
                    if( (OrderType() == OP_BUYSTOP) || (OrderType() == OP_SELLSTOP) )
                        if((TimeCurrent()-OrderOpenTime()) >= viDeleteStopOrderAfterInSec)
                            OrderDelete(OrderTicket());

                    if( (OrderType() == OP_BUY) || (OrderType() == OP_SELL) )
                        if((TimeCurrent()-OrderOpenTime()) >= viDeleteOpenOrderAfterInSec) {
                            // For executed orders, need to close them
                            double closePrice = 0;
                            RefreshRates();
                            if(OrderType() == OP_BUY)
                                closePrice  = Bid;
                            if(OrderType() == OP_SELL)
                                closePrice  = Ask;
                            OrderClose(OrderTicket(), OrderLots(), closePrice, int(viMaxSlippageInPip*viPipsToPoint), clrWhite);
                        }
                }
    }



    //===================================================================
    //OPEN STOP ORDERS IF NO EXISTING nor CLOSED NO BUY/SELL STOP/ORDERS
    //-------------------------------------------------------------------
    // Do NOT execute (place new orders) if it is past the trading window.
    if(TimeGMT() >= (vdTradeStartInGMT+viDeleteStopOrderAfterInSec))
    {
        Comment(vsDisplay + "[" + TimeToStr(TimeGMT()) + " GMT] " + "Already passed execution time.");
        return(0);
    }
    // Place BuyStop if not exists; and no executed-Buy order
    if( (viBuyStopTicket == -1) && (viBuyOrderTicket == -1)) {
        RefreshRates();
        viFixLots       = NormalizeDouble(viFixLots, 2);
        double viPrice = NormalizeDouble(Ask + (viStopOrderLevelInPip*viPipsToPrice), Digits);
        double viSL  = viPrice - (viStopLossInPip*viPipsToPrice);
        double viTP  = viPrice + (viTargetProfitInPip*viPipsToPrice);
        viBuyStopTicket   = OrderSend(Symbol(), OP_BUYSTOP, viFixLots
                                        , viPrice
                                        , int(viMaxSlippageInPip*viPipsToPoint)
                                        , viSL, viTP
                                        , vsEAComment, viMagicId, 0, Blue);
        if(viBuyStopTicket == -1)
            Print("Error executing BuyStop [" + IntegerToString(GetLastError()) + "]." );
    }
    // Place SellStop if not exists; and no executed-Sell order
    if( (viSellStopTicket == -1) && (viSellOrderTicket == -1) ) {
        RefreshRates();
        viFixLots       = NormalizeDouble(viFixLots, 2);
        double viPrice  = NormalizeDouble(Bid - (viStopOrderLevelInPip*viPipsToPrice), Digits);
        double viSL     = viPrice + (viStopLossInPip*viPipsToPrice);
        double viTP     = viPrice - (viTargetProfitInPip*viPipsToPrice);
        viSellStopTicket      = OrderSend(Symbol(), OP_SELLSTOP, viFixLots
                                        , viPrice
                                        , int(viMaxSlippageInPip*viPipsToPoint)
                                        , viSL, viTP
                                        , vsEAComment, viMagicId, 0, Red);
        if(viSellStopTicket == -1)
            Print("Error executing SellStop [" + IntegerToString(GetLastError()) + "]." );
    }
    return(0);
}
jlee88my
  • 2,935
  • 21
  • 28
  • Wow, this is great. Precisely what I’ve been trying to do. I am just trying to debug two issues that I found. 1. When it opens one trade say a buy, the other (which is supposed to be deleted) keeps reoccurring (deleting and recreating) non-stop for a few minutes. 2. When the duration for an open trade has expired, the trade doesn’t close. The [linked image](https://imgur.com/a/aRCUDDJ) shows both issues with the many arrows on the one minute chart and the “already passed time execution” text. – NotEveryDay May 14 '19 at 16:07
  • Weird, it should not happen like that. Lines 179-183 is to solves that exact issue. You can see from this image https://imgur.com/4HzVkoU that it doesn't reproduce. You can connect with me via telegram if you want to run through it. – jlee88my May 14 '19 at 16:41
  • Congratulations on the award. From my observation of the previous image you provided, the journal log shows that duration expired before any of the pending orders was open. That part works spot on. My issues are 1. when one order is opened and the other is suppose to close 2. when the open order is suppose to close on time expiration though it hasn’t reached TP or SL. I used longer durations (10 minutes and above) to make sure one order was triggered. – NotEveryDay May 14 '19 at 17:11
  • @JosephLee I seem to be getting the same bugs that NotEveryDay mentioned. I don't think the problem is from Line 179-183 something is triggering the repeated creation and deletion of the pending order that isn't open. The time expiration isn't closing the opened order too. – Hilarious404 May 14 '19 at 17:43
  • 1
    @JosephLee I've identified problems in `HANDLES OCO (One-Cancels-the-Other)` and `OPEN STOP ORDERS IF NOT EXISTS and NO BUY/SELL ORDERS` sections of the code. When one pending order is opened, the deleted order OrderTicket becomes -1 this satisfies the creation of a new order, causing the repeated deletion and recreation of the order. I tried changing the OrderTicket `int` after the order is closed but this created a problem when deleting both pending orders when none of them is opened. I placed comments on the lines in https://pastebin.com/H4N2F6Mq. – Hilarious404 May 14 '19 at 19:31
  • 1
    BUG FIX: I've made changes to the source to fix this reported issue. The idea is to use a event date/time as the MagicId and locate the executed orders in both open/history lists. – jlee88my May 15 '19 at 05:18
  • This code is now published in GitHub for open-source/public use/contribution at https://github.com/fhlee74/mql4-EventTrader – jlee88my May 15 '19 at 08:05
  • @JosephLee The repeated deletion and creation of the cancelled pending order issue has been resolved by the update you provided. But closing an open trade after `viDeleteOpenOrderAfterInSec` does seem to be working. – Hilarious404 May 15 '19 at 09:13
  • 1
    BUG FIXED: @Hilarious404 as reported and updated the code above. This is change tracker: https://github.com/fhlee74/mql4-EventTrader/commit/a4ec5648af0eb48044fc9be800c3283e45b29664 – jlee88my May 15 '19 at 10:49
  • 3
    @JosephLee Nice work. How can one extend this to be able to take multiple trades on the same pair, with different parameters? – TenOutOfTen May 15 '19 at 11:55
  • @JosephLee Sorry, I nearly forgot about this :). This is very impressive and works well. I'll have to admit that TenOutOfTen's proposition of extending it for multiple trades on the same pair with different parameters would be an exciting addition. But I guess the bounty doesn't cover that :) – iGetIt May 15 '19 at 12:05
  • @TenOutOfTen : As long as the Event-Time is different, the same EA can be used on the same pair. Just open another Chart (of the same pair) and drop it there with different param. Here's how you do it: https://imgur.com/09rEAE6 As you can see, the 2 are on the same pair, with different lotSize and just 2min apart. – jlee88my May 15 '19 at 14:15
  • @JosephLee I am interested in using different parameters but taking trades at the same time. – TenOutOfTen May 15 '19 at 14:36
  • 1
    @TenOutOfTen then what you are looking for is a Slide-In capability. Example: set multiple nets (levels) at diff distance. When a big spike happens, it will hit multiple stops (cascading orders). While a small spike will only hit the first stop. Supporting this is easy, but the next requests will be complex --you will ask for set-based P/L calc/closure (eg: on retrace, close the whole set [multiple orders]). This is possible, but not in this iteration. If there are interests for this in the GitHub repo, then will do it when I can. – jlee88my May 15 '19 at 14:47
  • 1
    @JosephLee I've asked a question that's related to this. I would be glad if you could help https://stackoverflow.com/questions/56177003/how-to-keep-a-10-pip-profit-gap-between-stop-loss-and-current-price-as-profits-i. – TenOutOfTen May 16 '19 at 21:48
  • 1
    @JosephLee You might want to take a look at this question. A bounty has been created for this https://stackoverflow.com/questions/56854700/how-can-i-write-mql4-code-ea-that-marks-the-listed-candle-patterns-with-rectan – Hilarious404 Jul 04 '19 at 20:48
  • Btw, I've updated the solution to include BlockTrailing as per https://stackoverflow.com/questions/56177003/how-to-keep-a-10-pip-profit-gap-between-stop-loss-and-current-price-as-profits-i/58797727#58797727 – jlee88my Nov 15 '19 at 11:40
0
#property strict
//---
input datetime          InpTime1=D'2019.05.01 00:00';       //time to enter the trade, just as an example
input double            InpPipsDist=10;                     //distance in pips to place BS&SS OCO-orders
input int               InpCloseSeconds=60;                 //close time, seconds since main order is sent
input double            InpProfitPips=1.;                   //profit in pips to close all.
input double            InpLotSize=0.1;                     //lot size
input int               InpMagicNumber=123456789;           //magic number
// ---

#include <Arrays\ArrayObj.mqh>
bool firstOrderOpen;
double PIP;
CArrayObj *ordersList;
// ---

class C2Orders : public CObject
  {
private:
   int                  m_ticket1;
   int                  m_ticket2;
   datetime             m_timeStart;//OrderOpenTime of the two tickets might be different,TimeCurrent() is used as time they are open.
   bool                 m_activated;

   void              checkTicket(const int ticket)  //if one order is open, another is deleted.
      {
        if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
          {
            if(OrderType()<=OP_SELL)
              {
                if(ticket==m_ticket1)
                  {
                   if(OrderDelete(m_ticket2))
                      printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
                    m_ticket2=-1;
                  }
                else
                  {
                    if(!OrderDelete(m_ticket1))
                       printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
                    m_ticket1=-1;
                  }
                m_activated=true;
              }
          }
     }
   double            getPnlPips(const int ticket)const
     {
       if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
         {
          return (OrderProfit()>0 ? 1 : -1)*fabs(OrderOpenPrice()-OrderClosePrice());
         }
       return 0;
     }
   bool              try2closeByPnl()const
     {
        const double pnl=getPnlPips(m_ticket1)+getPnlPips(m_ticket2);
        if(pnl-InpProfitPips*PIP>0)
          {
            printf("%i : pnl=%.5f vs %.5f target. closing the tickets",__LINE__,pnl,InpProfitPips*PIP);
            close(m_ticket1);
            close(m_ticket2);
            return(true);
          }
        return(false);
     }
   bool              try2closeByTime()const
     {
        if(TimeCurrent()-m_timeStart-InpCloseSeconds>=0)
          {
            if(!OrderDelete(m_ticket1))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket1,_LastError);
            if(!OrderDelete(m_ticket2))printf("%i: failed to delete#%d. error=%d",__LINE__,m_ticket2,_LastError);
            return(true);
          }
        return(false);
     }
   void              close(const int ticket)const
     {
        if(ticket>0 && OrderSelect(ticket,SELECT_BY_TICKET))
          {
            RefreshRates();
            if(OrderClose(ticket,OrderLots(),OrderClosePrice(),1))
               printf("%i: failed to close#%d. error=%d",__LINE__,ticket,_LastError);
          }
      }
public:
   C2Orders(const int ticket1,const int ticket2,const datetime time):
    m_ticket1(ticket1),m_ticket2(ticket2),m_activated(false),m_timeStart(time){}
  ~C2Orders(){}

   bool              check()    //returns FALSE if deleting the object
     {
        if(!m_activated)
          {
            checkTicket(m_ticket1);
            checkTicket(m_ticket2);
          }
        if(m_activated)
          {
            if(try2closeByPnl())
                return(false);
          }
        else
          {
            if(try2closeByTime())
                return(false);
          }
        return true;
     }

  };
//+------------------------------------------------------------------+
int OnInit()
    {
        firstOrderOpen=false;
        PIP=_Point*(_Digits%2==1 ? 10 : 1); //does not work for GOLD and indexes, good for FX.
        ordersList=new CArrayObj();

        return(INIT_SUCCEEDED);
    }
void OnDeinit(const int reason)
    {
        delete(ordersList);
    }
void OnTick()
    {
        if(!firstOrderOpen && TimeCurrent()>=InpTime1)
        {
            RefreshRates();
            const int ticketBS=OrderSend(_Symbol,OP_BUYSTOP,InpLotSize,NormalizeDouble(Ask+InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
            const int ticketSS=OrderSend(_Symbol,OP_SELLSTOP,InpLotSize,NormalizeDouble(Bid-InpPipsDist*PIP,_Digits),0,0,0,NULL,InpMagicNumber);
            C2Orders *oco=new C2Orders(ticketBS,ticketSS,TimeCurrent());
            ordersList.Add(oco);
            firstOrderOpen=true;
        }
        if(firstOrderOpen)
        {
            C2Orders* oco;
            for(int i=ordersList.Total()-1;i>=0;i--)//of course you have only one instance, but in real world you may need to loop over them.
            {
                oco=ordersList.At(i);
                if(!oco.check())
                    ordersList.Delete(i);
            }

            if(ordersList.Total()==0)
                ExpertRemove();//just to finish the test faster.
        }
    }
Daniel Kniaz
  • 4,603
  • 2
  • 14
  • 20
  • Thank you for answering. Using the solution you provided, I've completed my EA, but I'm having a number of errors. I would be grateful if you would check it out for me https://pastebin.com/v0hUn93Y. – NotEveryDay May 02 '19 at 22:35
  • as I can see you just copied the answer. and what are the errors you have? – Daniel Kniaz May 03 '19 at 08:29
  • I made a few changes where I thought necessary based on my understanding of the solution you provided. The errors are 1. `'CObject' - declaration without type` and 2. `'}' unexpected end of program` and 3. `" - unexpected end of program` – NotEveryDay May 03 '19 at 11:44
  • `class C2Orders{ public: CObject` is incorrect and not clear what you meant by using incorrect statement. after correction it will compile. But I do not see how you implemented the idea into your code. – Daniel Kniaz May 04 '19 at 12:05
  • Okay, I got a bit confused and I was getting a number of errors. I recently found out that I needed to add `#include `. I've read the definition for `OrderClose` but I don't know whether I am using them correctly to solve my problem. Also not sure I'm doing the right thing in the `if(!elem.check()) {}` block. – NotEveryDay May 06 '19 at 16:49
  • Interestingly, someone just put up a bounty for my question. – NotEveryDay May 08 '19 at 14:31
  • it would be interesting to hear from the bounty creator what is the question and what to add to my reply – Daniel Kniaz May 11 '19 at 10:16
  • 5
    @DanielKniaz Currently, your solution is basically a template for solving the original question. I would like a complete solution with tested code that solves each of the issues addressed in the original question. To be more specific, a solution that opens a buy and sell pending order at a specific time at a certain number of pips that cancels one trade (buy or sell) when the other in opened and closes the opened trade when in X pips profit above the spread or after T seconds/minutes (based on the first to be satisfied). – iGetIt May 12 '19 at 21:16
  • 2
    @DanielKniaz I forgot to mention that additionally, it should cancel both pending orders if none is open within a certain duration. – iGetIt May 12 '19 at 21:16
  • @iGetIt I edited my reply, now it is tested and seems to cover all the questions. – Daniel Kniaz May 14 '19 at 21:29
  • @DanielKniaz You might want to take a look at this question. A bounty has been created for this https://stackoverflow.com/questions/56854700/how-can-i-write-mql4-code-ea-that-marks-the-listed-candle-patterns-with-rectan – Hilarious404 Jul 04 '19 at 20:50
  • @DanielKniaz I've placed a bounty for my question https://stackoverflow.com/questions/56177003/how-to-keep-a-10-pip-profit-gap-between-stop-loss-and-current-price-as-profits-i. Please take a look at it – TenOutOfTen Nov 07 '19 at 15:50