Clenow’s algorithm is definitely an indicator for the current State of Trend Following (SOTF). However, the 3 X ATR trailing stop mechanism actually dampens the profit/draw down ratio. Take a look at this chart.
All Trend Following mechanisms have a very common thread in their entry mechanisms. The thing that separates them is the preemptive exit. Do you allow the the algorithm to exit on a purely market defined method or do you overlay trade management? Here the best approach was to let the Bollinger Band system run unfettered; even though it seems somewhat illogical. Many times trade management actually increases draw down. Is there a solution? What about this – keep risk down by trading a small, yet diverse portfolio of high volume markets and overlay it with a stock index mean reversion algo. Take a look.
Should’ve, Would’ve , Could’ve.
This could be scaled up. The mean reversion helped lift the chart out of the flat and draw down periods of late. However, the smaller portfolio did OK during this time period too! Can four or five high volume markets replicate a much larger portfolio? All tests were carried out with TradingSimula18 – the software that comes with my latest book.
Its a new decade! Time to see what’s up with Trend Following.
I am a huge fan of Andreas Clenow’s books, and how he demonstrated that a typical trader could replicate the performance of most large Trend Following CTAs and not pay the 2% / 20% management/incentive combo fees. So. I felt the system that he described in his book would be a great representation of TheState of Trend Following. At the same time I am going to demonstrate TradingSimula18 (the software included in my latest book).
System Description
Take a look at my last post. I provide the EasyLanguage and a pretty good description of Clenow’s strategy.
TradingSimula18 Code [Python]
#--------------------------------------------------------------------------------------------------- # Start programming your great trading ideas below here - don't touch stuff above #--------------------------------------------------------------------------------------------------- # Define Long, Short, ExitLong and ExitShort Levels - mind your indentations ATR = sAverage(myTrueRange,30,curBar,1) posSize = 2000/(ATR*myBPV) posSize = max(int(posSize),1) posSize = min(posSize,20) avg1 = xAverage(myClose,marketVal5[curMarket],50,curBar,1) avg2 = xAverage(myClose,marketVal6[curMarket],100,curBar,1) marketVal5[curMarket] = avg1 marketVal6[curMarket] = avg2 donchHi = highest(myHigh,50,curBar,1) donchLo = lowest(myLow,50,curBar,1)
if mp == 1 : marketVal1[curMarket] = max(marketVal1[curMarket],myHigh[curBar-1]- 3 * ATR) if mp ==-1 : marketVal2[curMarket] = min(marketVal2[curMarket],myLow[curBar-1]+ 3 * ATR) # Long Entry if avg1 > avg2 and myHigh[curBar-1] == donchHi and mp !=1: price = myOpen[curBar] tradeName = "TFClenowB";numShares = posSize marketVal1[curMarket] = price - 3 * ATR if mp <= -1: profit,curShares,trades = bookTrade(entry,buy,price,myDate[curBar],tradeName,numShares) barsSinceEntry = 1 marketMonitorList[curMarket].setSysMarkTrackingInfo(tradeName,cumuProfit,mp,barsSinceEntry,curShares,trades) # Long Exit if mp == 1 and myClose[curBar-1] <= marketVal1[curMarket] and barsSinceEntry > 1: price = myOpen[curBar] tradeName = "Lxit";numShares = curShares profit,curShares,trades = bookTrade(exit,ignore,price,myDate[curBar],tradeName,numShares) todaysCTE = profit;barsSinceEntry = 0 marketMonitorList[curMarket].setSysMarkTrackingInfo(tradeName,cumuProfit,mp,barsSinceEntry,curShares,trades) # Short Entry if avg1 < avg2 and myLow[curBar-1] == donchLo and mp !=-1: price = myOpen[curBar];numShares = posSize marketVal2[curMarket] = price + 3 * ATR if mp >= 1: tradeName = "TFClenowS" profit,curShares,trades = bookTrade(entry,sell,price,myDate[curBar],tradeName,numShares) barsSinceEntry = 1 marketMonitorList[curMarket].setSysMarkTrackingInfo(tradeName,cumuProfit,mp,barsSinceEntry,curShares,trades) # Short Exit if mp == -1 and myClose[curBar-1] >= marketVal2[curMarket] and barsSinceEntry > 1: price = myOpen[curBar] tradeName = "Sxit"; numShares = curShares profit,curShares,trades = bookTrade(exit,ignore,price,myDate[curBar],tradeName,numShares) todaysCTE = profit;barsSinceEntry = 0 marketMonitorList[curMarket].setSysMarkTrackingInfo(tradeName,cumuProfit,mp,barsSinceEntry,curShares,trades) #---------------------------------------------------------------------------------------------------------------------------- # - Do not change code below - trade, portfolio accounting - our great idea should stop here #----------------------------------------------------------------------------------------------------------------------------
TradingSimula18 Python System Testing Environment
I am going to go over this very briefly. I know that many of the readers of my blog have attempted to use Python and the various packages out there and have given up on it. Quantopia and QuantConnect are great websites, but I feel they approach back-testing with a programmer in mind. This was the main reason I created TS-18 – don’t get me wrong its not a walk in the park either, but it doesn’t rely on external libraries to get the job done. All the reports I show here are generated from the data created solely by TS-18. Plus it is very modular – Step 1 leads to Step2 and on and on. Referring to the code I calculate the ATR (average true range) by calling the simple average function sAverage. I pass it myTrueRanges, 30, curBar and 1. I am looking for the average true range over the last 30 days. I then move onto my position sizing – posSize = $2,000 / ATR in $s. PosSize must fit between 1 and 20 contracts. The ATR calculation can get rather small for some markets and the posSize can get rather large. Avg1 and Avg2 are exponential moving averages of length 50 and 100. DonchHi and donchLo are the highest high and lowest low of the past 50 days. If mp == 1 (long position) then a trailing stop (marketVal1) is set to whichever is higher – the current marketVal1 or the yesterday’s High – 3 X ATR; the trailing stop tracks new intra-trade highs. The trailing stop for the short side, marketVal2 is calculated in a similar manner, but low prices are used as well as a positive offset of 3 X ATR.
Now the next section of code is quite a bit different than say EasyLanguage, but parallels some of the online Python paradigms. Here you must test the current bar’s extremes against the donchHi if you are flat and marketVal1 (the trailing stop variable) if you are long. If flat you also test the low of the bar against donchLo. The relationship between avg1 and avg2 are also examined. If the testing criteria is true, then its up to you to assign the correct price, posSize and tradeName. So you have four independent if-then constructs:
Long Entry – if flat test to see if a long position should be initiated
Long Exit – if Long then test to see if a liquidation should be initiated
Short Entry – if flat test to see if a short position should be initiated
Short Exit – if Short then test to see if a liquidation should be initiated
That’s it – all of the other things are handled by TS-18. Now that I have completely bored you out of your mind, let’s move onto some results.
Results from 2000 – risking $2,000 per trade:
Sector Performance from 2000
From this chart it doesn’t make much sense to trade MEATS, SOFTS or GRAINS with a Trend Following approach or does it?
In the next post, I will go over the results with more in depth and possibly propose some ideas that might or might not help. Stay Tuned!
Here is a free Trend Following System that I read about on Andreas Clenow’s www.followthetrend.com website and from his book. This is my interpretation of the rules as they were explained. However the main impetus behind this post wasn’t to provide a free trading system, but to show how you can program a simple system with a complete input interface and program a tracking indicator. You might be asking what is a “tracking indicator?” We use a tracking indicator to help provide insight to what the strategy is doing and what it might do in the near future. The indicator can let you know that a new signal is imminent and also what the risk is in a graphical form. The indicator can also plot the indicators that are used in the strategy itself.
Step 1: Program the Strategy
This system is very simple. Trade on a 50 day Donchian in the direction of the trend and use a 3 X ATR trailing stop. So the trend is defined as bullish when the 50-day exponential moving average is greater than the 100-day exponential moving average. A bearish trend is defined when the 50-day is below the 100-day. Long positions are initiated on the following day when a new 50 day high has been established and the trend is bullish. Selling short occurs when the trend is bearish and a new 50 day low is establish. The initial stop is set to 3 X ATR below the high of the day of entry. I tested using a 3 X ATR stop initially from the entryPrice for protection on the day of entry, but it made very little difference. As the trade moves more into your favor, the trailing stop ratchets up and tracks the higher intra-trade extremes. Eventually once the market reverses you get stopped out of a long position 3 X ATR from the highest high since you entered the long trade. Hopefully, with a big winner. The Clenow model also uses a position sizing equation that uses ATR to determine market risk and $2000 for the allocated amount to risk. Size= 2000 / ATR – this equation will normalize size across a portfolio of markets.
Here is the code.
//Based on Andreas Clenow's description from www.followingthetrend.com //This is my interpretation and may or may not be what Andreas intended //Check his books out at amazon.com // inputs: xAvgShortLen(50),xAvgLongLen(100),hhllLen(50),buyTrigPrice(h),shortTrigPrice(l),risk$Alloc(2000); inputs: atrLen(30),trailATRMult(3); vars: avg1(0),avg2(0),lXit(0),sXit(0),posSize(0),atr(0);
If marketPosition <> 1 and avg1 > avg2 and buyTrigPrice = highest(buyTrigPrice,hhllLen) then buy posSize contracts next bar at open; If marketPosition <> -1 and avg1 < avg2 and shortTrigPrice = lowest(shortTrigPrice,hhllLen) then sellshort posSize contracts next bar at open;
If marketPosition = 0 then Begin lXit = o - trailATRMult * atr ; sXit = o + trailATRMult * atr; // if c < lXit then Sell currentcontracts contracts next bar at open; // If c > sXit then buyToCover currentcontracts contracts next bar at open; end;
If marketPosition = 1 then begin lXit = maxList(lXit,h - trailATRMult * atr); If c < lXit then sell currentContracts contracts next bar at open; end;
If marketPosition = -1 then begin sXit = minList(sXit,l + trailATRMult * atr); If c > sXit then buyToCover currentContracts contracts next bar at open; end;
Cleanow Simple Trend Following System
What I like about this code is how you can use it as a template for any trend following approach. All the variables that could be optimized are included as inputs. Many may not know that you can actually change the data series that you want to use as your signal generator right in the input. Here I have provided two inputs : buyTrigPrice(H), shortTrigPrice(L). If you want to use the closing price, then all you need to do is change the H and L to C. The next lines of code performs the calculations needed to calculate the trend. PosSize is then calculated next. Here I am dividing the variable risk$Alloc by atr*bigPointValue. Basically I am taking $2000 and dividing the average true range over the past 30 days multiplied by the point value of the market being tested. Always remember when doing calculations with $s you have to convert whatever else you are using into dollars as well. The ATR is expressed in the form of a price difference. You can’t divide dollars by a price component, hence the multiplication by bigPointValue. So now we have the trend calcuation and the position sizing taken care of and all we need now is the trend direction and the entry levels. If avg1 > avg2 then the market is in a bullish posture, and if today’s High = highest(High,50) days back then initiate a long position with posSize contracts at the next bar’s open. Notice how I used the keyword contracts after posSize. This let’s TS know that I want to trade more than one contract. If the current position is flat I set the lXit and sXit price levels to the open -/+ 3 X ATR. Once a position (long or short) is initiated then I start ratcheting the trailing stop up or down. Assuming a long position, I compare the current lXit and the current bar’s HIGH- 3 X ATR and take the larger of the two values. So lXit always moves up and never down. Notice if the close is less than lXit I used the keyword currentContracts and contracts in the directive to exit a long trade. CurrentContracts contains the current number of contracts currently long and contracts informs TS that more than one contract is being liquidated. Getting out of a short position is exactly the same but in a different direction.
Step 2: Program the System Tracking Indicator
Now you can take the exact code and eliminate all the order directives and use it to create a tracking indicator. Take a look at this code:
//Based on Andreas Clenow's description from www.followingthetrend.com //This is my interpretation and may or may not be what Andreas intended //Check his books out at amazon.com // inputs: xAvgShortLen(50),xAvgLongLen(100),hhllLen(50),buyTrigPrice(h),shortTrigPrice(l); inputs: atrLen(30),trailATRMult(3); vars: avg1(0),avg2(0),lXit(0),sXit(0),posSize(0),atr(0),mp(0);
If avg1[1] > avg2[1] and buyTrigPrice[1] = highest(buyTrigPrice[1],hhllLen) then mp = 1; If avg1[1] < avg2[1] and shortTrigPrice[1] = lowest(shortTrigPrice[1],hhllLen) then mp = -1;
If mp = 0 then Begin lXit = o - trailATRMult * atr ; sXit = o + trailATRMult * atr; end;
If mp = 1 then begin lXit = maxList(lXit,h - trailATRMult * atr); plot3(lXit,"LongTrail"); If c < lXit then mp = 0; end;
If mp = -1 then begin sXit = minList(sXit,l + trailATRMult * atr); plot4(sXit,"ShortTrail"); If c > sXit then mp = 0; end;
However, you do need to keep track if the underlying strategy is long or short and you can do this by pretending you are the computer and using the mp variable. You know if yesterdays avg1 > avg2 and HIGH[1] = highestHigh(HIGH[1],50), then a long position should have been initiated. If this happens just set mp to 1. You set mp to -1 by checking the trend and lowestLow(LOW[1],50). Once you know the mp or implied market position then you can calculate the lXit and sXit. You will always plot the moving averages to help determine trend direction, but you only plot the lXit and sXit when a position is on. So plot3 and plot4 should only be plotted when a position is long or short.
Here is a screenshot of the strategy and tracking indicator.
Notice how the Yellow and Cyan plots follow the correct market position. You will need to tell TS not to connect these plot lines when they are not designed to be plotted.
Turn-Off Auto Plot Line Connection
Do this for Plot3 and Plot4 and you will be good to go.
I hope you found this post useful. Also don’t forget to check out my new book at Amazon.com. If you really want to learn programming that will help across different platforms I think it would be a great learning experience.
Backtesting with [Trade Station,Python,AmiBroker, Excel]. Intended for informational and educational purposes only!
Get All Five Books in the Easing Into EasyLanguage Series - The Trend Following Edition is now Available!
Announcement – A Trend Following edition has been added to my Easing into EasyLanguage Series! This edition will be the fifth and final installment and will utilize concepts discussed in the Foundation editions. I will pay respect to the legends of Trend Following by replicating the essence of their algorithms. Learn about the most prominent form of algorithmic trading. But get geared up for it by reading the first four editions in the series now. Get your favorite QUANT the books they need!
This series includes five editions that covers the full spectrum of the EasyLanguage programming language. Fully compliant with TradeStation and mostly compliant with MultiCharts. Start out with the Foundation Edition. It is designed for the new user of EasyLanguage or for those you would like to have a refresher course. There are 13 tutorials ranging from creating Strategies to PaintBars. Learn how to create your own functions or apply stops and profit objectives. Ever wanted to know how to find an inside day that is also a Narrow Range 7 (NR7?) Now you can, and the best part is you get over 4 HOURS OF VIDEO INSTRUCTION – one for each tutorial.
This book is ideal for those who have completed the Foundation Edition or have some experience with EasyLanguage, especially if you’re ready to take your programming skills to the next level. The Hi-Res Edition is designed for programmers who want to build intraday trading systems, incorporating trade management techniques like profit targets and stop losses. This edition bridges the gap between daily and intraday bar programming, making it easier to handle challenges like tracking the sequence of high and low prices within the trading day. Plus, enjoy 5 hours of video instruction to guide you through each tutorial.
The Advanced Topics Edition delves into essential programming concepts within EasyLanguage, offering a focused approach to complex topics. This book covers arrays and fixed-length buffers, including methods for element management, extraction, and sorting. Explore finite state machines using the switch-case construct, text graphic manipulation to retrieve precise X and Y coordinates, and gain insights into seasonality with the Ruggiero/Barna Universal Seasonal and Sheldon Knight Seasonal methods. Additionally, learn to build EasyLanguage projects, integrate fundamental data like Commitment of Traders, and create multi-timeframe indicators for comprehensive analysis.
The Day Trading Edition complements the other books in the series, diving into the popular approach of day trading, where overnight risk is avoided (though daytime risk still applies!). Programming on high-resolution data, such as five- or one-minute bars, can be challenging, and this book provides guidance without claiming to be a “Holy Grail.” It’s not for ultra-high-frequency trading but rather for those interested in techniques like volatility-based breakouts, pyramiding, scaling out, and zone-based trading. Ideal for readers of the Foundation and Hi-Res editions or those with EasyLanguage experience, this book offers insights into algorithms that shaped the day trading industry.
For thirty-one years as the Director of Research at Futures Truth Magazine, I had the privilege of collaborating with renowned experts in technical analysis, including Fitschen, Stuckey, Ruggiero, Fox, and Waite. I gained invaluable insights as I watched their trend-following methods reach impressive peaks, face sharp declines, and ultimately rebound. From late 2014 to early 2020, I witnessed a dramatic downturn across the trend-following industry. Iconic systems like Aberration, CatScan, Andromeda, and Super Turtle—once thriving on robust trends of the 1990s through early 2010s—began to falter long before the pandemic. Since 2020 we have seen the familiar trends return. Get six hours of video instruction with this edition.
Pick up your copies today – e-Book or paperback format – at Amazon.com