Robot Example 4 – Range Breakout
Prompted by the Forex Espionage "Advanced" System here is a robot based around a range breakout system. It is a much simplified version of the original Turtle Trading system provided to his students by Richard Dennis way back in 1984. It enters a trade on a breakout from the range of a number of consecutive bars. It then exits the trade on a breakout in the opposite direction from the range of a smaller number of bars.
To get an initial feel for the system used by the legendary Turtle Traders try out this expert advisor using daily bars and the default input settings with the Long Period set to 55 and the Short Period set to 20. You may also wish to try other timeframes and other input settings. Does this type of system show any promise for day trading, for example?
Since this example is for a long term trend following system our initial backtests cover a long period of time! Here are the results from the MetaTrader 4 strategy tester starting on January 1st 2000, using the EUR/USD pair and the default input settings with daily bars:
Symbol | EURUSD (Euro vs US Dollar) | ||||
Period | Daily (D1) 2000.01.03 00:00 – 2009.06.12 00:00 (2000.01.01 – 2009.06.13) | ||||
Model | Every tick (the most precise method based on all available least timeframes) | ||||
Parameters | Magic=12348; Slippage=30; Lots=0.1; LongPeriod=55; ShortPeriod=20; | ||||
Bars in test | 3469 | Ticks modelled | 21721141 | Modelling quality | n/a |
Mismatched charts errors | 20103 | ||||
Initial deposit | 500.00 | ||||
Total net profit | 3021.91 | Gross profit | 8016.85 | Gross loss | -4994.94 |
Profit factor | 1.60 | Expected payoff | 73.71 | ||
Absolute drawdown | 288.05 | Maximal drawdown | 2083.86 (39.06%) | Relative drawdown | 74.01% (603.69) |
Total trades | 41 | Short positions (won %) | 18 (38.89%) | Long positions (won %) | 23 (52.17%) |
Profit trades (% of total) | 19 (46.34%) | Loss trades (% of total) | 22 (53.66%) | ||
Largest | profit trade | 858.80 | loss trade | -861.00 | |
Average | profit trade | 421.94 | loss trade | -227.04 | |
Maximum | consecutive wins (profit in money) | 2 (1268.41) | consecutive losses (loss in money) | 3 (-800.00) | |
Maximal | consecutive profit (count of wins) | 1268.41 (2) | consecutive loss (count of losses) | -1312.78 (2) | |
Average | consecutive wins | 1 | consecutive losses | 2 |
# | Time | Type | Order | Size | Price | S / L | T / P | Profit | Balance |
1 | 2000.01.27 13:36 | sell | 1 | 0.10 | 0.99847 | 0.00000 | 0.00000 | ||
2 | 2000.02.22 16:53 | close | 1 | 0.10 | 1.00623 | 0.00000 | 0.00000 | -80.72 | 419.28 |
3 | 2000.02.28 04:26 | sell | 2 | 0.10 | 0.96646 | 0.00000 | 0.00000 | ||
4 | 2000.05.26 16:43 | close | 2 | 0.10 | 0.92014 | 0.00000 | 0.00000 | 451.50 | 870.78 |
5 | 2000.09.06 02:13 | sell | 3 | 0.10 | 0.87170 | 0.00000 | 0.00000 | ||
6 | 2000.12.01 00:52 | close | 3 | 0.10 | 0.88018 | 0.00000 | 0.00000 | -96.24 | 774.54 |
7 | 2000.12.20 00:52 | buy | 4 | 0.10 | 0.90878 | 0.00000 | 0.00000 | ||
8 | 2001.02.15 02:11 | close | 4 | 0.10 | 0.90590 | 0.00000 | 0.00000 | -22.90 | 751.64 |
9 | 2001.03.15 00:37 | sell | 5 | 0.10 | 0.89820 | 0.00000 | 0.00000 | ||
10 | 2001.07.18 16:31 | close | 5 | 0.10 | 0.86687 | 0.00000 | 0.00000 | 297.31 | 1048.95 |
11 | 2001.08.02 03:19 | buy | 6 | 0.10 | 0.88398 | 0.00000 | 0.00000 | ||
12 | 2001.09.06 09:20 | close | 6 | 0.10 | 0.88370 | 0.00000 | 0.00000 | 0.70 | 1049.65 |
13 | 2001.09.14 14:34 | buy | 7 | 0.10 | 0.92468 | 0.00000 | 0.00000 | ||
14 | 2001.10.11 12:56 | close | 7 | 0.10 | 0.90566 | 0.00000 | 0.00000 | -187.50 | 862.15 |
15 | 2001.11.13 14:40 | sell | 8 | 0.10 | 0.88190 | 0.00000 | 0.00000 | ||
16 | 2001.12.12 19:57 | close | 8 | 0.10 | 0.89898 | 0.00000 | 0.00000 | -174.57 | 687.58 |
17 | 2002.01.25 10:55 | sell | 9 | 0.10 | 0.87300 | 0.00000 | 0.00000 | ||
18 | 2002.03.07 09:00 | close | 9 | 0.10 | 0.88089 | 0.00000 | 0.00000 | -84.23 | 603.35 |
19 | 2002.04.17 10:03 | buy | 10 | 0.10 | 0.88753 | 0.00000 | 0.00000 | ||
20 | 2002.08.06 09:58 | close | 10 | 0.10 | 0.97230 | 0.00000 | 0.00000 | 858.80 | 1462.15 |
21 | 2002.09.17 10:50 | sell | 11 | 0.10 | 0.96196 | 0.00000 | 0.00000 | ||
22 | 2002.10.10 10:53 | close | 11 | 0.10 | 0.99208 | 0.00000 | 0.00000 | -304.45 | 1157.70 |
23 | 2002.11.05 09:13 | buy | 12 | 0.10 | 1.00114 | 0.00000 | 0.00000 | ||
24 | 2002.11.23 11:22 | close | 12 | 0.10 | 0.98835 | 0.00000 | 0.00000 | -126.00 | 1031.70 |
25 | 2002.12.12 15:51 | buy | 13 | 0.10 | 1.01848 | 0.00000 | 0.00000 | ||
26 | 2003.03.17 16:50 | close | 13 | 0.10 | 1.06868 | 0.00000 | 0.00000 | 511.30 | 1543.00 |
27 | 2003.04.30 01:42 | buy | 14 | 0.10 | 1.10939 | 0.00000 | 0.00000 | ||
28 | 2003.06.19 04:11 | close | 14 | 0.10 | 1.16250 | 0.00000 | 0.00000 | 536.30 | 2079.30 |
29 | 2003.07.16 01:54 | sell | 15 | 0.10 | 1.11508 | 0.00000 | 0.00000 | ||
30 | 2003.09.12 15:48 | close | 15 | 0.10 | 1.12778 | 0.00000 | 0.00000 | -134.80 | 1944.50 |
31 | 2003.09.29 17:01 | buy | 16 | 0.10 | 1.15592 | 0.00000 | 0.00000 | ||
32 | 2003.11.03 16:12 | close | 16 | 0.10 | 1.15410 | 0.00000 | 0.00000 | -14.70 | 1929.80 |
33 | 2003.11.18 16:09 | buy | 17 | 0.10 | 1.18670 | 0.00000 | 0.00000 | ||
34 | 2004.02.27 11:06 | close | 17 | 0.10 | 1.23790 | 0.00000 | 0.00000 | 522.30 | 2452.10 |
35 | 2004.03.02 17:00 | sell | 18 | 0.10 | 1.22932 | 0.00000 | 0.00000 | ||
36 | 2004.05.27 14:25 | close | 18 | 0.10 | 1.21875 | 0.00000 | 0.00000 | 94.26 | 2546.36 |
37 | 2004.07.07 07:54 | buy | 19 | 0.10 | 1.23577 | 0.00000 | 0.00000 | ||
38 | 2004.07.27 16:19 | close | 19 | 0.10 | 1.20610 | 0.00000 | 0.00000 | -294.70 | 2251.66 |
39 | 2004.10.15 14:41 | buy | 20 | 0.10 | 1.24496 | 0.00000 | 0.00000 | ||
40 | 2005.01.07 16:08 | close | 20 | 0.10 | 1.31518 | 0.00000 | 0.00000 | 710.60 | 2962.26 |
41 | 2005.02.04 14:52 | sell | 21 | 0.10 | 1.29170 | 0.00000 | 0.00000 | ||
42 | 2005.02.22 04:18 | close | 21 | 0.10 | 1.31278 | 0.00000 | 0.00000 | -212.88 | 2749.38 |
43 | 2005.05.12 08:56 | sell | 22 | 0.10 | 1.27637 | 0.00000 | 0.00000 | ||
44 | 2005.08.03 11:02 | close | 22 | 0.10 | 1.22618 | 0.00000 | 0.00000 | 491.37 | 3240.75 |
45 | 2005.09.01 14:27 | buy | 23 | 0.10 | 1.24938 | 0.00000 | 0.00000 | ||
46 | 2005.09.19 00:08 | close | 23 | 0.10 | 1.21570 | 0.00000 | 0.00000 | -335.20 | 2905.55 |
47 | 2005.10.03 03:07 | sell | 24 | 0.10 | 1.19497 | 0.00000 | 0.00000 | ||
48 | 2005.12.12 13:52 | close | 24 | 0.10 | 1.19031 | 0.00000 | 0.00000 | 37.50 | 2943.05 |
49 | 2006.01.06 14:52 | buy | 25 | 0.10 | 1.21738 | 0.00000 | 0.00000 | ||
50 | 2006.02.03 14:59 | close | 25 | 0.10 | 1.20048 | 0.00000 | 0.00000 | -166.20 | 2776.85 |
51 | 2006.04.06 10:59 | buy | 26 | 0.10 | 1.23237 | 0.00000 | 0.00000 | ||
52 | 2006.06.08 14:33 | close | 26 | 0.10 | 1.26895 | 0.00000 | 0.00000 | 372.10 | 3148.95 |
53 | 2006.07.18 16:47 | sell | 27 | 0.10 | 1.24769 | 0.00000 | 0.00000 | ||
54 | 2006.08.04 14:31 | close | 27 | 0.10 | 1.28365 | 0.00000 | 0.00000 | -362.07 | 2786.88 |
55 | 2006.08.21 16:01 | buy | 28 | 0.10 | 1.29351 | 0.00000 | 0.00000 | ||
56 | 2006.09.08 14:37 | close | 28 | 0.10 | 1.26947 | 0.00000 | 0.00000 | -238.40 | 2548.48 |
57 | 2006.10.10 11:05 | sell | 29 | 0.10 | 1.25560 | 0.00000 | 0.00000 | ||
58 | 2006.10.31 16:08 | close | 29 | 0.10 | 1.27528 | 0.00000 | 0.00000 | -199.53 | 2348.95 |
59 | 2006.11.10 09:54 | buy | 30 | 0.10 | 1.28804 | 0.00000 | 0.00000 | ||
60 | 2007.01.05 14:30 | close | 30 | 0.10 | 1.30508 | 0.00000 | 0.00000 | 176.00 | 2524.95 |
61 | 2007.03.16 02:12 | buy | 31 | 0.10 | 1.32980 | 0.00000 | 0.00000 | ||
62 | 2007.05.10 18:58 | close | 31 | 0.10 | 1.34800 | 0.00000 | 0.00000 | 187.50 | 2712.45 |
63 | 2007.06.13 02:37 | sell | 32 | 0.10 | 1.32860 | 0.00000 | 0.00000 | ||
64 | 2007.07.02 09:36 | close | 32 | 0.10 | 1.35558 | 0.00000 | 0.00000 | -272.27 | 2440.18 |
65 | 2007.07.10 15:15 | buy | 33 | 0.10 | 1.36863 | 0.00000 | 0.00000 | ||
66 | 2007.08.13 16:56 | close | 33 | 0.10 | 1.36070 | 0.00000 | 0.00000 | -75.90 | 2364.28 |
67 | 2007.09.12 07:21 | buy | 34 | 0.10 | 1.38576 | 0.00000 | 0.00000 | ||
68 | 2007.12.14 12:22 | close | 34 | 0.10 | 1.45240 | 0.00000 | 0.00000 | 675.90 | 3040.18 |
69 | 2008.02.26 20:34 | buy | 35 | 0.10 | 1.49541 | 0.00000 | 0.00000 | ||
70 | 2008.05.01 10:44 | close | 35 | 0.10 | 1.55136 | 0.00000 | 0.00000 | 566.20 | 3606.38 |
71 | 2008.07.11 15:29 | buy | 36 | 0.10 | 1.59108 | 0.00000 | 0.00000 | ||
72 | 2008.07.29 16:12 | close | 36 | 0.10 | 1.56103 | 0.00000 | 0.00000 | -298.90 | 3307.48 |
73 | 2008.08.08 02:02 | sell | 37 | 0.10 | 1.53010 | 0.00000 | 0.00000 | ||
74 | 2008.09.22 20:46 | close | 37 | 0.10 | 1.48129 | 0.00000 | 0.00000 | 482.51 | 3789.99 |
75 | 2008.10.02 09:26 | sell | 38 | 0.10 | 1.38798 | 0.00000 | 0.00000 | ||
76 | 2008.12.11 06:27 | close | 38 | 0.10 | 1.30848 | 0.00000 | 0.00000 | 785.90 | 4575.89 |
77 | 2008.12.17 05:50 | buy | 39 | 0.10 | 1.41518 | 0.00000 | 0.00000 | ||
78 | 2009.01.13 06:42 | close | 39 | 0.10 | 1.32881 | 0.00000 | 0.00000 | -861.00 | 3714.89 |
79 | 2009.02.18 15:49 | sell | 40 | 0.10 | 1.25479 | 0.00000 | 0.00000 | ||
80 | 2009.03.16 11:02 | close | 40 | 0.10 | 1.29963 | 0.00000 | 0.00000 | -451.78 | 3263.11 |
81 | 2009.05.20 15:43 | buy | 41 | 0.10 | 1.37395 | 0.00000 | 0.00000 | ||
82 | 2009.06.12 13:54 | close at stop | 41 | 0.10 | 1.39958 | 0.00000 | 0.00000 | 258.80 | 3521.91 |
Here's the source code for this "robot":
//+------------------------------------------------------------------+
//| GuruEx04.mq4 |
//| Copyright © 2009, Marketing Dreams Ltd. All Rights Reserved. |
//| http://trading-gurus.com |
//| |
//| GuruTrader™ example 4 |
//| Version 1.0 |
//| |
//| A basic range breakout system |
//| Based on the original Turtle Trading system |
//| |
//| 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 = 12348; extern int Slippage=30; extern double Lots=0.1; extern int LongPeriod=55; extern int ShortPeriod=20; //---- static variables static int Dig; static double Points;
static bool Initialized = FALSE; static bool Running = FALSE; static bool Long = FALSE; static double LongMax; static double LongMin; static double ShortMax; static double ShortMin; static int LastBar; static int OrderNumber; static double PositionSize;
static color clBuy = DodgerBlue; static color clSell = Crimson;
//+------------------------------------------------------------------+ //| Utility functions | //+------------------------------------------------------------------+ #include <stdlib.mqh> #include <stderror.mqh> #include <WinUser32.mqh>
//+------------------------------------------------------------------+ //| Expert helper functions | //+------------------------------------------------------------------+
//+------------------------------------------------------------------+ //| Closes an order at market | //+------------------------------------------------------------------+ int CloseMarket(int Ticket) { int Type, ErrorCode; double Price, Quantity;
OrderSelect(Ticket, SELECT_BY_TICKET); Type = OrderType();
Quantity = OrderLots();
while (TRUE) { // Keep trying until the order really is closed if (Type == OP_BUY) Price=Bid; else if (Type == OP_SELL) Price=Ask; else return (-1); Print("CLOSE ", Ticket, ", ", Quantity, ", ", Price); if (OrderClose(Ticket, Quantity, Price, Slippage, CLR_NONE) == TRUE) { Sleep(SLEEP_OK); return (0); } else { ErrorCode = GetLastError(); Print("Error closing order ", Ticket, ": ", ErrorDescription(ErrorCode), " (", ErrorCode, ")", " size: ", Quantity, ", prices: ", Price, ", ", Bid, ", ", Ask); Sleep(SLEEP_ERR); RefreshRates(); } } return (-1); }
//+------------------------------------------------------------------+ //| Places an 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); }
//+------------------------------------------------------------------+ //| Calculates Long & Short period ranges | //+------------------------------------------------------------------+ void CalcRanges() { int Index;
Index = ArrayMaximum(High, LongPeriod); LongMax = High[Index]; Index = ArrayMinimum(Low, LongPeriod); LongMin = Low[Index];
Index = ArrayMaximum(High, ShortPeriod); ShortMax = High[Index]; Index = ArrayMinimum(Low, ShortPeriod); ShortMin = Low[Index];
LastBar = Bars; }
//+------------------------------------------------------------------+ //| Performs system initialisation | //+------------------------------------------------------------------+ void InitSystem() { Running = FALSE;
PositionSize = Lots;
RefreshRates();
CalcRanges();
Print("Entry Levels - Upper = ", LongMax, ", Lower = ", LongMin, ". Exit Levels - Upper = ", ShortMax, ", Lower = ", ShortMin);
Initialized = TRUE; }
//+------------------------------------------------------------------+ //| Checks for entry to a trade | //+------------------------------------------------------------------+ int CheckEntry(double Size) { if (Bid > LongMax) { // Broken out higher so GO LONG! if (OrderNumber > 0) CloseMarket(OrderNumber); // Close previous short order OrderNumber = Order(Symbol(), OP_BUY, Ask, Size, 0, 0); if (OrderNumber > 0) { Long = TRUE; return(1); } } else if (Bid < LongMin) { // Broken out lower so GO SHORT! if (OrderNumber > 0) CloseMarket(OrderNumber); // Close previous long order OrderNumber = Order(Symbol(), OP_SELL, Bid, Size, 0, 0); if (OrderNumber > 0) { Long = FALSE; return(1); } } return(0); }
//+------------------------------------------------------------------+ //| Checks for exit from a trade | //+------------------------------------------------------------------+ int CheckExit() { int ErrorCode;
if (Long && (Bid < ShortMin)) { CloseMarket(OrderNumber); // Close long order if (OrderSelect(OrderNumber, SELECT_BY_TICKET) != TRUE) { ErrorCode = GetLastError(); Print("Error selecting order ", OrderNumber, ": ", ErrorDescription(ErrorCode), " (", ErrorCode, ")"); return(-1); } Print("Order ", OrderNumber, " closed: ", OrderClosePrice(), ", at ", TimeToStr(OrderCloseTime()), ". Profit = ", OrderProfit()); return(1); } if (!Long && (Bid > ShortMax)) { CloseMarket(OrderNumber); // Close short order if (OrderSelect(OrderNumber, SELECT_BY_TICKET) != TRUE) { ErrorCode = GetLastError(); Print("Error selecting order ", OrderNumber, ": ", ErrorDescription(ErrorCode), " (", ErrorCode, ")"); return(-1); } Print("Order ", OrderNumber, " closed: ", OrderClosePrice(), ", at ", TimeToStr(OrderCloseTime()), ". Profit = ", OrderProfit()); return(1); } else { 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); }
if (ShortPeriod >= LongPeriod) { Print("Error - ShortPeriod must be less than LongPeriod."); 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); }
if (Bars > LastBar) CalcRanges();
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, OrderNumber = 0; // indicate no open order any more InitSystem(); // and start all over again! } } else if (CheckEntry(PositionSize) > 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