Backtesting Pattern Theory in the Forex Markets

William Wu
3 min readFeb 1, 2020

--

We’ve (or rather all traders) at some point in their lives have heard about support resistance lines or head and shoulder patterns. The problem with these kind of strategies is the difficulty in backtesting those strategies and the subjectivity with which those strategies exist. Stare at any particular chart long enough and you’ll always find some way of finding evidence to support your theory of going long or short. Hindsight is 20:20 and I believe it to be some kind of confirmation bias where people are just more afraid of losing opportunity so will find a way to justify their perspective on the matters. Nevertheless, this makes it much more difficult to backtest compared to indicator based strategies.

However, today I’ve been looking into a method to backtest patterns in Zorro and one such method is outlined in the following article above. Details are in the article, while in this article I wanted to look into the results of my investigation.

vars ClosePrices = series(priceClose());vars filtData = series(LowPass(ClosePrices, 27));

In order to remove a degree of subjectivity and noise, I've used a lowpassfilter and fed the resulting data into the frechet function. Furthermore, I tested the pattern on the daily charts in Zorro with the BarPeriod at 1440. The major currencies tested were: “AUD/USD”, “EUR/USD”, “GBP/USD”, “USD/CAD”, and “USD/JPY”.

In the interest of time and quickly test whether pattern theory works in a general backtest, I applied the most widely know head and shoulders pattern with a stop loss at 3*ATR(20) and a trailing stop at 1.5*ATR(20). This pattern was generated in an excel spreadsheet and set into a pattern variable: `static var headShldrs[17] = {1,3,5,4,3,5,8,10,7,6,4,3,4,6,5,3,0}`. The only variables that were changes during this investigation were currencypair and TimeFrame used in the frechet comparison. 10/20/30 bars were used and the results summarised below.

The results were as follows:

AUD/USD
Portfolio analysis OptF ProF Win/Loss Wgt%
_10_Asym avg — — 1.02 16/44 2.6
_20_Asym avg — — 1.57 28/178 87.9
_30_Asym avg — — 1.02 111/337 9.5

EUR/USD
Portfolio analysis OptF ProF Win/Loss Wgt%
_10_Asym avg — — 0.77 14/62 19.4
_20_Asym avg — — 0.87 38/234 16.4
_30_Asym avg — — 0.88 131/437 64.2

GBP/USD
Portfolio analysis OptF ProF Win/Loss Wgt%
_10_Asym avg — — 0.44 15/65 55.1
_20_Asym avg — — 0.97 38/224 2.5
_30_Asym avg — — 0.90 146/432 42.3

USD/CAD
Portfolio analysis OptF ProF Win/Loss Wgt%
_10_Asym avg — — 0.67 14/62 22.3
_20_Asym avg — — 0.77 37/207 38.8
_30_Asym avg — — 0.93 117/361 38.8

USD/JPY
Portfolio analysis OptF ProF Win/Loss Wgt%
_10_Asym avg — — 0.67 14/62 22.3
_20_Asym avg — — 0.77 37/207 38.8
_30_Asym avg — — 0.93 117/361 38.8

In the interest of space for this article, complete long/short strategy breakdown was not included. However, what was interesting was that no Long strategies were entered, as expected due to the shape of the head and shoulders pattern.

Nevertheless the overall results showed fairly poor result overall, except for maybe AUD/USD. However, during further investigation of AUD/USD it was noted that the Sharpe ratio was only 0.11, far below what would be considered a good or useful strategy.

Would I use this for trading? Probably not. Would I try optimising it? Probably not. Does that mean technical patterns are useless? Most likely not. But in the forex markets I'm not too sure.

So I've attached the code here below if you want to try it out in Zorro. Too lazy to use github/gitlab/gitsomething, etc.

function tradeStrategy(){static var headShldrs[17] = {1,3,5,4,3,5,8,10,7,6,4,3,4,6,5,3,0};vars ClosePrices = series(priceClose());vars filtData = series(LowPass(ClosePrices, 27));plot("FiltData",filtData, MAIN,BLACK);static var threshold = 20;var* pattern=headShldrs;int i;for(i=20;i<=20;i+=10){algo(strf("_%d_Asym", i));plot(strf("Ptn_%d", i),frechet(filtData, i, MaxVal(ClosePrices,i) - MinVal(ClosePrices,i), pattern),NEW,BLUE);if(frechet(filtData, i, MaxVal(ClosePrices,i)-MinVal(ClosePrices,i), pattern) > threshold){EntryTime = 5;Stop = 3*ATR(20);Trail = 1.25*ATR(20);if(NumOpenLong == 0) enterLong();if(NumOpenShort == 0) enterShort();}}PlotWidth = 800;PlotScale = 15;PlotHeight1 = 500;PlotHeight2 = 125;}function run(){set(LOGFILE,PARAMETERS,PLOTNOW); // log all tradesCapital = slider(1,1000,1,10000,"Capital","Initial capital");StartDate = 20110601;EndDate = 20180601;asset("AUD/USD");Hedge = 0;MaxLong = 3;MaxShort = 3;tradeStrategy();}

--

--