Robot Example 5 – One Cancels the Other Order

0

This example robot adds separate take profit and stop loss orders to example one. It also needs to implement the MetaTrader equivalent of a One Cancels the Other order. When one of the exit orders is executed the robot cancels the other one itself.

Here are the results from the MetaTrader strategy tester (but with the list of trades shortened):

Strategy Tester Report
GuruEx05
Symbol EURUSD (Euro vs US Dollar)
Period 1 Minute (M1) 2009.01.05 00:01 – 2009.07.31 22:59 (2009.01.05 – 2009.08.01)
Model Every tick (the most precise method based on all available least timeframes)
Parameters Magic=12349; Slippage=30; ProfitTarget=1000; StopLoss=10000; Lots=0.01;
Bars in test 210704 Ticks modelled 6376172 Modelling quality 25.00%
Mismatched charts errors 0
Initial deposit 100.00
Total net profit 260.57 Gross profit 369.57 Gross loss -109.01
Profit factor 3.39 Expected payoff 3.38
Absolute drawdown 56.76 Maximal drawdown 124.31 (74.19%) Relative drawdown 74.19% (124.31)
Total trades 77 Short positions (won %) 38 (100.00%) Long positions (won %) 39 (94.87%)
Profit trades (% of total) 75 (97.40%) Loss trades (% of total) 2 (2.60%)
Largest profit trade 10.05 loss trade -100.43
Average profit trade 4.93 loss trade -54.50
Maximum consecutive wins (profit in money) 63 (309.61) consecutive losses (loss in money) 1 (-100.43)
Maximal consecutive profit (count of wins) 309.61 (63) consecutive loss (count of losses) -100.43 (1)
Average consecutive wins 38 consecutive losses 1

Equty curve for OCO example robot

# Time Type Order Size Price S / L T / P Profit Balance
1 2009.01.05 00:01 sell 1 0.01 1.38820 0.00000 0.00000
2 2009.01.05 00:01 buy limit 2 0.01 1.37820 0.00000 0.00000
3 2009.01.05 00:01 buy stop 3 0.01 1.48836 0.00000 0.00000
4 2009.01.05 09:22 buy 2 0.01 1.37820 0.00000 0.00000
5 2009.01.05 09:22 close by 1 0.01 1.37820 0.00000 0.00000 10.00 110.00
6 2009.01.05 09:22 close by 2 0.00 1.37820 0.00000 0.00000 0.00 110.00
7 2009.01.05 09:22 delete 3 0.01 1.48836 0.00000 0.00000
8 2009.01.05 09:22 sell 4 0.01 1.37725 0.00000 0.00000
9 2009.01.05 09:22 buy limit 5 0.01 1.36725 0.00000 0.00000
10 2009.01.05 09:22 buy stop 6 0.01 1.47741 0.00000 0.00000
11 2009.01.05 09:39 buy 5 0.01 1.36725 0.00000 0.00000
12 2009.01.05 09:39 close by 4 0.01 1.36725 0.00000 0.00000 10.00 120.00
13 2009.01.05 09:39 close by 5 0.00 1.36725 0.00000 0.00000 0.00 120.00
14 2009.01.05 09:39 delete 6 0.01 1.47741 0.00000 0.00000
15 2009.01.05 09:39 sell 7 0.01 1.36689 0.00000 0.00000
16 2009.01.05 09:39 buy limit 8 0.01 1.35689 0.00000 0.00000
17 2009.01.05 09:39 buy stop 9 0.01 1.46705 0.00000 0.00000
18 2009.01.05 13:50 buy 8 0.01 1.35689 0.00000 0.00000
19 2009.01.05 13:50 close by 7 0.01 1.35689 0.00000 0.00000 10.00 130.00
20 2009.01.05 13:50 close by 8 0.00 1.35689 0.00000 0.00000 0.00 130.00
21 2009.01.05 13:50 delete 9 0.01 1.46705 0.00000 0.00000
22 2009.01.05 13:50 buy 10 0.01 1.35677 0.00000 0.00000
23 2009.01.05 13:50 sell limit 11 0.01 1.36677 0.00000 0.00000
24 2009.01.05 13:50 sell stop 12 0.01 1.25661 0.00000 0.00000
25 2009.01.07 14:28 sell 11 0.01 1.36677 0.00000 0.00000
26 2009.01.07 14:28 close by 10 0.01 1.36677 0.00000 0.00000 9.99 139.99
27 2009.01.07 14:28 close by 11 0.00 1.36677 0.00000 0.00000 0.00 139.99
28 2009.01.07 14:28 delete 12 0.01 1.25661 0.00000 0.00000
29 2009.01.07 14:28 buy 13 0.01 1.36731 0.00000 0.00000
30 2009.01.07 14:28 sell limit 14 0.01 1.37731 0.00000 0.00000
31 2009.01.07 14:28 sell stop 15 0.01 1.26715 0.00000 0.00000
32 2009.01.08 15:07 sell 14 0.01 1.37731 0.00000 0.00000
33 2009.01.08 15:07 close by 13 0.01 1.37731 0.00000 0.00000 9.98 149.97
34 2009.01.08 15:07 close by 14 0.00 1.37731 0.00000 0.00000 0.00 149.97
35 2009.01.08 15:07 delete 15 0.01 1.26715 0.00000 0.00000
36 2009.01.08 15:07 sell 16 0.01 1.37739 0.00000 0.00000
37 2009.01.08 15:07 buy limit 17 0.01 1.36739 0.00000 0.00000
38 2009.01.08 15:07 buy stop 18 0.01 1.47755 0.00000 0.00000
39 2009.01.08 19:43 buy 17 0.01 1.36739 0.00000 0.00000
40 2009.01.08 19:43 close by 16 0.01 1.36739 0.00000 0.00000 10.00 159.97
41 2009.01.08 19:43 close by 17 0.00 1.36739 0.00000 0.00000 0.00 159.97
42 2009.01.08 19:43 delete 18 0.01 1.47755 0.00000 0.00000
43 2009.01.08 19:43 buy 19 0.01 1.36741 0.00000 0.00000
44 2009.01.08 19:43 sell limit 20 0.01 1.37741 0.00000 0.00000
45 2009.01.08 19:43 sell stop 21 0.01 1.26725 0.00000 0.00000
46 2009.02.17 02:19 sell 21 0.01 1.26725 0.00000 0.00000
47 2009.02.17 02:19 close by 19 0.01 1.26725 0.00000 0.00000 -100.43 59.54
48 2009.02.17 02:19 close by 21 0.00 1.26725 0.00000 0.00000 0.00 59.54
49 2009.02.17 02:19 delete 20 0.01 1.37741 0.00000 0.00000
50 2009.02.17 02:19 buy 22 0.01 1.26749 0.00000 0.00000
51 2009.02.17 02:19 sell limit 23 0.01 1.27749 0.00000 0.00000
52 2009.02.17 02:19 sell stop 24 0.01 1.16733 0.00000 0.00000
53 2009.02.20 18:07 sell 23 0.01 1.27749 0.00000 0.00000
54 2009.02.20 18:07 close by 22 0.01 1.27749 0.00000 0.00000 9.96 69.50
55 2009.02.20 18:07 close by 23 0.00 1.27749 0.00000 0.00000 0.00 69.50
56 2009.02.20 18:07 delete 24 0.01 1.16733 0.00000 0.00000
57 2009.02.20 18:07 buy 25 0.01 1.27792 0.00000 0.00000
58 2009.02.20 18:07 sell limit 26 0.01 1.28792 0.00000 0.00000
59 2009.02.20 18:07 sell stop 27 0.01 1.17776 0.00000 0.00000
60 2009.02.20 19:19 sell 26 0.01 1.28792 0.00000 0.00000
61 2009.02.20 19:19 close by 25 0.01 1.28792 0.00000 0.00000 10.00 79.50
62 2009.02.20 19:19 close by 26 0.00 1.28792 0.00000 0.00000 0.00 79.50
63 2009.02.20 19:19 delete 27 0.01 1.17776 0.00000 0.00000
64 2009.02.20 19:19 buy 28 0.01 1.28834 0.00000 0.00000
65 2009.02.20 19:19 sell limit 29 0.01 1.29834 0.00000 0.00000
66 2009.02.20 19:19 sell stop 30 0.01 1.18818 0.00000 0.00000
67 2009.02.23 08:22 sell 29 0.01 1.29834 0.00000 0.00000
68 2009.02.23 08:22 close by 28 0.01 1.29834 0.00000 0.00000 9.99 89.50
69 2009.02.23 08:22 close by 29 0.00 1.29834 0.00000 0.00000 0.00 89.50
70 2009.02.23 08:22 delete 30 0.01 1.18818 0.00000 0.00000
71 2009.02.23 08:22 sell 31 0.01 1.29849 0.00000 0.00000
72 2009.02.23 08:22 buy limit 32 0.01 1.28849 0.00000 0.00000
73 2009.02.23 08:22 buy stop 33 0.01 1.39865 0.00000 0.00000
74 2009.02.23 10:15 buy 32 0.01 1.28849 0.00000 0.00000
75 2009.02.23 10:15 close by 31 0.01 1.28849 0.00000 0.00000 10.00 99.50
76 2009.02.23 10:15 close by 32 0.00 1.28849 0.00000 0.00000 0.00 99.50
77 2009.02.23 10:15 delete 33 0.01 1.39865 0.00000 0.00000
78 2009.02.23 10:15 buy 34 0.01 1.28847 0.00000 0.00000
79 2009.02.23 10:15 sell limit 35 0.01 1.29847 0.00000 0.00000
80 2009.02.23 10:15 sell stop 36 0.01 1.18831 0.00000 0.00000
81 2009.03.16 09:57 sell 35 0.01 1.29847 0.00000 0.00000
82 2009.03.16 09:57 close by 34 0.01 1.29847 0.00000 0.00000 9.85 109.35
83 2009.03.16 09:57 close by 35 0.00 1.29847 0.00000 0.00000 0.00 109.35
84 2009.03.16 09:57 delete 36 0.01 1.18831 0.00000 0.00000
85 2009.03.16 09:57 buy 37 0.01 1.29876 0.00000 0.00000
86 2009.03.16 09:57 sell limit 38 0.01 1.30876 0.00000 0.00000
87 2009.03.16 09:57 sell stop 39 0.01 1.19860 0.00000 0.00000
88 2009.03.18 13:30 sell 38 0.01 1.30876 0.00000 0.00000
89 2009.03.18 13:30 close by 37 0.01 1.30876 0.00000 0.00000 9.99 119.34
90 2009.03.18 13:30 close by 38 0.00 1.30876 0.00000 0.00000 0.00 119.34
91 2009.03.18 13:30 delete 39 0.01 1.19860 0.00000 0.00000
92 2009.03.18 13:30 buy 40 0.01 1.30906 0.00000 0.00000
93 2009.03.18 13:30 sell limit 41 0.01 1.31906 0.00000 0.00000
94 2009.03.18 13:30 sell stop 42 0.01 1.20890 0.00000 0.00000
95 2009.03.18 19:18 sell 41 0.01 1.31906 0.00000 0.00000
96 2009.03.18 19:18 close by 40 0.01 1.31906 0.00000 0.00000 10.00 129.34
97 2009.03.18 19:18 close by 41 0.00 1.31906 0.00000 0.00000 0.00 129.34
98 2009.03.18 19:18 delete 42 0.01 1.20890 0.00000 0.00000

Here's the source code for our OCO "robot":

//+------------------------------------------------------------------+
//|                                                     GuruEx05.mq4 |
//|     Copyright © 2009, Marketing Dreams Ltd. All Rights Reserved. |
//|                                         http://trading-gurus.com |
//|                                                                  |
//| GuruTrader™ example 5                                            |
//| Version 1.0                                                      |
//|                                                                  |
//| Adds futures style stops and targets to example 1.               |
//| The EA does a One Cancels the Other order all by itself!         |
//|                                                                  |
//| Wealth Warning! This expert is for educational purposes only.    |
//| It should NEVER be used on a live account. Past performance is   |
//| in no way indicative of future results!                          |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, Marketing Dreams Ltd."
#property link      "http://trading-gurus.com"
#define SLEEP_OK     250
#define SLEEP_ERR    250
//---- input parameters
extern int     Magic = 12349;
extern int     Slippage=30;
extern int     ProfitTarget=1000;
extern int     StopLoss=10000;
extern double  Lots=0.01;
//---- static variables
static int     Dig;
static double  Points;
static bool    Initialized = FALSE;
static bool    Running = FALSE;
static int     OrderNumber;
static int     TargetOrder;
static int     StopOrder;
static double  LastBid;
static double  LastAsk;
static color   clBuy = DodgerBlue;
static color   clSell = Crimson;
//+------------------------------------------------------------------+
//| Utility functions                                                |
//+------------------------------------------------------------------+
#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh>
//+------------------------------------------------------------------+
//| Expert helper functions                                          |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Places a market order                                            |
//+------------------------------------------------------------------+
int Order(string symbol, int Type, double Entry, double Quantity,
          double TargetPrice, double StopPrice, string comment="")
{
   string TypeStr;
   color  TypeCol;
   int    ErrorCode, Ticket;
   double Price, FillPrice;
   Price = NormalizeDouble(Entry, Dig);
   switch (Type) {
      case OP_BUY:
         TypeStr = "BUY";
         TypeCol = clBuy;
         break;
      case OP_SELL:
         TypeStr = "SELL";
         TypeCol = clSell;
         break;
      default:
         Print("Unknown order type ", Type);
         break;
   }
   Ticket = OrderSend(symbol, Type, Quantity, Price, Slippage,
              StopPrice, TargetPrice, comment, Magic, 0, TypeCol);
   if (Ticket >= 0) {
      Sleep(SLEEP_OK);
      if (OrderSelect(Ticket, SELECT_BY_TICKET) == TRUE) {
         FillPrice = OrderOpenPrice();
         if (Entry != FillPrice) {
            RefreshRates();
            Print("Slippage on order ", Ticket, " - Requested = ",
                  Entry, ", Fill = ", FillPrice, ", Current Bid = ",
                  Bid, ", Current Ask = ", Ask);
         }
      }
      else {
         ErrorCode = GetLastError();
         Print("Error selecting new order ", Ticket, ": ",
               ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      }
      return (Ticket);
   }
   ErrorCode = GetLastError();
   RefreshRates();
   Print("Error opening ", TypeStr, " order: ", ErrorDescription(ErrorCode),
         " (", ErrorCode, ")", ", Entry = ", Price, ", Target = ",
         TargetPrice, ", Stop = ", StopPrice, ", Current Bid = ", Bid,
         ", Current Ask = ", Ask);
   Sleep(SLEEP_ERR);
   return (-1);
}
//+------------------------------------------------------------------+
//| Places a pending order                                           |
//+------------------------------------------------------------------+
int PendingOrder(string symbol, int Type, double Entry, double Quantity,
          double TargetPrice, double StopPrice, string comment="")
{
   string TypeStr;
   color  TypeCol;
   int    ErrorCode, Ticket;
   double Price, FillPrice;
   Price = NormalizeDouble(Entry, Dig);
   switch (Type) {
      case OP_BUYSTOP:
         TypeStr = "BUY STOP";
         TypeCol = clBuy;
         break;
      case OP_SELLSTOP:
         TypeStr = "SELL STOP";
         TypeCol = clSell;
         break;
      case OP_BUYLIMIT:
         TypeStr = "BUY LIMIT";
         TypeCol = clBuy;
         break;
      case OP_SELLLIMIT:
         TypeStr = "SELL LIMIT";
         TypeCol = clSell;
         break;
      default:
         Print("Unknown pending order type ", Type);
         break;
   }
   Ticket = OrderSend(symbol, Type, Quantity, Price, Slippage,
              StopPrice, TargetPrice, comment, Magic, 0, TypeCol);
   if (Ticket >= 0) {
      Sleep(SLEEP_OK);
      if (OrderSelect(Ticket, SELECT_BY_TICKET) == FALSE) {
         ErrorCode = GetLastError();
         Print("Error selecting new pending order ", Ticket, ": ",
               ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      }
      return (Ticket);
   }
   ErrorCode = GetLastError();
   RefreshRates();
   Print("Error opening ", TypeStr, " order: ", ErrorDescription(ErrorCode),
         " (", ErrorCode, ")", ", Entry = ", Price, ", Target = ",
         TargetPrice, ", Stop = ", StopPrice, ", Current Bid = ", Bid,
         ", Current Ask = ", Ask);
   Sleep(SLEEP_ERR);
   return (-1);
}
//+------------------------------------------------------------------+
//| Cancels a pending order                                           |
//+------------------------------------------------------------------+
int Cancel(int Ticket)
{
   int ErrorCode;
   if (OrderSelect(Ticket, SELECT_BY_TICKET) != TRUE) {
      ErrorCode = GetLastError();
      Print("Error selecting order to cancel ", Ticket, ": ",
            ErrorDescription(ErrorCode), " (", ErrorCode, ")");
   }
   if (OrderDelete(Ticket) != TRUE) {
      ErrorCode = GetLastError();
      Print("Error cancelling order ", Ticket, ": ",
            ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      Sleep(SLEEP_ERR);
      return (-1);
   }
   switch(OrderType()) {
   case OP_BUYSTOP:
   case OP_SELLSTOP:
      StopOrder = 0;
      break;
   case OP_BUYLIMIT:
   case OP_SELLLIMIT:
      TargetOrder = 0;
      break;
   default:
      break;
   }
   Sleep(SLEEP_OK);
   return (0);
}
int CloseBy(int Ticket, int Opposite)
{
   int ErrorCode;
   if (OrderCloseBy(Ticket, Opposite) != TRUE) {
      ErrorCode = GetLastError();
      Print("Error closing order ", Ticket, " with order ", Opposite, ": ",
            ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      Sleep(SLEEP_ERR);
      return (-1);
   }
   Sleep(SLEEP_OK);
   return (0);
}
//+------------------------------------------------------------------+
//| Performs system initialisation                                   |
//+------------------------------------------------------------------+
void InitSystem()
{
   Running = FALSE;
   RefreshRates();
   LastBid = Bid;
   LastAsk = Ask;
   Initialized = TRUE;
}
//+------------------------------------------------------------------+
//| Checks for entry to a trade                                      |
//+------------------------------------------------------------------+
int CheckEntry(double Size)
{
   if (Ask > LastAsk) {  // Short term uptrend so GO LONG!
      Print("Going Long!");
      OrderNumber = Order(Symbol(), OP_BUY, Ask, Size, 0,0, 0.0);
      if (OrderNumber <= 0)
         return(0);
      TargetOrder = PendingOrder(Symbol(), OP_SELLLIMIT,
            Ask + (Points * ProfitTarget), Size, 0.0, 0.0);
      if (TargetOrder <= 0)
         return(0);
      StopOrder = PendingOrder(Symbol(), OP_SELLSTOP,Bid - (Points * StopLoss), Size, 0.0,0,0);
      if (StopOrder > 0)
         return(1);
   }
   else if (Bid < LastBid) {  // Short term downtrend so GO SHORT!
      Print("Going Short!");
      OrderNumber = Order(Symbol(), OP_SELL, Bid, Size, 0.0, 0.0);
      if (OrderNumber <= 0)
         return(0);
      TargetOrder = PendingOrder(Symbol(), OP_BUYLIMIT,
            Bid - (Points * ProfitTarget), Size, 0.0, 0,0);
      if (TargetOrder <= 0)
         return(0);
      StopOrder = PendingOrder(Symbol(), OP_BUYSTOP, Ask + (Points * StopLoss), Size, 0.0,0.0);
      if (StopOrder > 0)
         return(1);
   }
   return(0);
}
//+------------------------------------------------------------------+
//| Checks for exit from a trade                                     |
//+------------------------------------------------------------------+
int CheckExit()
{
   int ErrorCode;
   if (OrderSelect(TargetOrder, SELECT_BY_TICKET) != TRUE) {
      ErrorCode = GetLastError();
      Print("Error selecting target order ", TargetOrder, ": ",
            ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      return (0);
   }
   else if ((OrderType() == OP_SELL) || (OrderType() == OP_BUY)) {
      Print("Target ", TargetOrder, " reached: ", OrderOpenPrice(),
             " at ", TimeToStr(OrderOpenTime(), TIME_SECONDS));
      CloseBy(OrderNumber, TargetOrder);
      Cancel(StopOrder);
      return (1);
   }
   if (OrderSelect(StopOrder, SELECT_BY_TICKET) != TRUE) {
      ErrorCode = GetLastError();
      Print("Error selecting stop order ", StopOrder, ": ",
            ErrorDescription(ErrorCode), " (", ErrorCode, ")");
      return (0);
   }
   else if ((OrderType() == OP_SELL) || (OrderType() == OP_BUY)) {
      Print("Stop Loss ", StopOrder, " reached: ", OrderOpenPrice(),
             " at ", TimeToStr(OrderOpenTime(), TIME_SECONDS));
      CloseBy(OrderNumber, StopOrder);
      Cancel(TargetOrder);
      return (1);
   }
   return(0);
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   Dig = MarketInfo(Symbol(), MODE_DIGITS);
   Points = MarketInfo(Symbol(), MODE_POINT);
   Print("Digits = ", Dig, ", Points = ", DoubleToStr(Points, 5));
   if (!IsDemo() && !IsTesting()) {
      MessageBox("Wealth Warning! This expert is for educational purposes only." +
            " It should NEVER be used on a live account." +
            " Past performance is in no way indicative of future results!");
      Print("Initialization Failure");
      return(-1);
   }
   InitSystem();
   Print("Initialized OK");
   return(0);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
    Print("DeInitialized OK");
    return(0);
}
//+------------------------------------------------------------------+
//| Expert start function                                            |
//| Executed on every tick                                           |
//+------------------------------------------------------------------+
int start()
{
   if (!Initialized) {
      return(-1);
   }
   else if (Running) {                    // Are we in a trade at the moment?
      if (CheckExit() > 0) {              // Yes - Last trade complete?
         Initialized = FALSE;             // Yes - Indicate we need to reinitialise
         InitSystem();                    //  and start all over again!
      }
   }
   else {
      if (CheckEntry(Lots) > 0) {         // Entered a trade?
         Running = TRUE;                  // Yes - Indicate that we're in a trade
      }
   }
   return(0);
}

You can also download the source code here.

Leave a Comment

Fields marked by an asterisk (*) are required.