The Enigmatic Turtle Trading System in Python

Correction to Original Post!  Turtle Intro

[Corrections in bold and results –  August 6, 2020] My favorite book on the Turtle Trading System is Curtis Faith’s “Way of the Turtle.”  I like this book because of the thorough explanation of the rules as told by Curtis.  Having been in this industry for a very long time I have met several Turtles – some that have been very successful and some not so.  And that is all I will proffer up on my impression of the few Turtles I have met.  The rules on the surface are quite simple, but once you dig in to program the ideas you discover they are intricate and require, in some instances, subjective analysis.  In this post I want to demonstrate how to program most of the ideas in Python with my TradingSimula-18 software.  Some of the concepts aren’t 100% programmable, like the reduction of trading capital at the end of a trading year based on losses occurred during that particular year.   Also to keep things simple I will not show reinvestment of profits – if I did we would have ran out of money a few times during the back test.  However, I will show code that will allow this feature.  In the original post I used 1 N as the AddOn price level.  This should have been 1/2N and I also discovered I was using 2N to put on the first AddOn trade.  Those corrections are reflected in the tables below.

Why Use TradingSimula-18

This all inclusive algorithm was one of the major reasons I designed TradingSimula-18 like I did.  As I have described elsewhere on this website, TS-18 spans the portfolio horizontally and at the end of each historical day, the program knows the exact number of contracts, or units, that’s in play and the total portfolio balance.   This information is key to executing the major components of the algorithm.  Remember you get this software when you purchase my lastest book – TrendFollowing – a DIY Project – Batteries Included.  https://www.amazon.com/gp/product/B082QY381Y/ref=dbs_a_def_rwt_bibl_vppi_i2

Pinnacle Data

I used Ed Pavia’s excellent continuous contract database for all of the testing.  I have found his software to be highly reliable and I prefer his rollover mechanism.  Check it out for yourself at Pinnacle Data Continuous Contract.

Core Concepts:

  1. The concept of N – a quasi exponential moving average of the past twenty days true ranges.
  2. Last Trade Was A Loser Filter (LTL) – only take 20-day break outs if the prior one was deemed a loser.
  3. Pyramid at N-Levels – if long then add on at 1N, 2N, 3N and 4N levels.  This should be 0.5N, 1.0N,1.5N. Levels added on using original entry price as foundation.
  4. Only allow 4 Units Per Market and 12 Units Per Portfolio – trade while # of units fall below these levels (in our analysis 1 Unit = 1 contract).
  5. Always enter a 55 day break out – no matter what the results of the last break out happened to be
  6. Trade a similar portfolio to the Original Turtle Portfolio

N – calculation

# Calculate N - first simple average - 2nd and beyond use weighted calculation
if NValue[curMarket] == -999999:
NValue[curMarket] = sAverage(myTrueRange,20,curBar,1)
else:
NValue[curMarket] = (19 * NValue[curMarket] + myTrueRange[curBar-1])/20
unitSize = (0.01*(initCapital + dailyPortCombEqu))/(NValue[curMarket]*myBPV)
unitSize = trunc(unitSize)

# I use the variable (list) NValue to store the N for each market
# NValue[curMarket] keeps track of the N while we loop through
# each market on a daily basis
# If we were to use a TRUE unit size this is how you would calculate
# Here we are using 1% of initCapital + dailyPortfolio Cumu Equity as risk value
# Then divide by N (aka volatility measure)

Finite State Machine to Determine LTL (Last Trade Loser)

I showed how to do this in my other blog in EasyLanguage George’s Blog.  In EasyLanguage you can can use Case Switch programming structures, but you can’t do this in Python.  If constructs can be used here:

### finite state machine to determine LTL
seekLong = True
seekShort = True
for i in range(0,2):
if state==0:
lep = highest(myHigh,20,curBar,1)
sep = lowest(myLow,20,curBar,1)
if seekLong and myHigh[curBar]>= lep + myMinMove:
theoMP[curMarket] = 1
theoEX[curMarket] = max(myOpen[curBar],lep) - 2 * NValue[curMarket]
theoEP[curMarket] = max(myOpen[curBar],lep)
if seekShort and myLow[curBar]<= sep - myMinMove:
theoMP[curMarket] = -1
theoEX[curMarket] = min(myOpen[curBar],sep) + 2 * NValue[curMarket]
theoEP[curMarket] = min(myOpen[curBar],sep)
# print(myDate[curBar]," Going Short")
if theoMP[curMarket] !=0:
state = 1
cantExitToday = True
# print("Can't exit today ",cantExitToday)
if state == 1:
if not(cantExitToday):
lxp = max(theoEX[curMarket],lowest(myLow,10,curBar,1) - myMinMove)
sxp = min(theoEX[curMarket],highest(myHigh,10,curBar,1) + myMinMove)
if theoMP[curMarket] == 1 and myLow[curBar]<=lxp:
theoMP[curMarket] = 0
seekLong = False
# if lxp <= theoEX[curMarket]:
if lxp < theoEP[curMarket]:
ltl = True
else:
ltl = False
if theoMP[curMarket] ==-1 and myHigh[curBar]>=sxp:
theoMP[curMarket] = 0
seekShort = False
# if sxp >= theoEX[curMarket]:
if sxp > theoEP[curMarket]:
ltl = True
else:
ltl = False
if theoMP[curMarket] == 0: state = 0
cantExitToday = False

if ltl: theoWL[curMarket] = -1
else: theoWL[curMarket] = 1
Finite State Machine to Determine LTL

All this code is doing is keeping track of hypothetical positions and if those positions either turn out to be a pure loser or a 2N loss loser.  In Curtis’ book a 20-day break out turned out to be a loser only if it suffered a 2N loss.  A 2N loss is an exit that equates to a 2N move prior to a 10 day low/high.  In the rules, 20-bar breakouts are terminated at either a 2N loss or a 10 bar low, whichever is closer (if long).  If the trade is terminated at a 10 day low, then it is not considered a loser – no matter if it was or not.  I do show performance for any loser and only a 2N loss loser later in the post.  This code looks rather complex, but it really isn’t.  All I am doing is seeing if a 20-day break out occurs, long or short, and then monitoring those positions to see how they turn out.  Since we are spanning markets first then days, I use four lists theoMP (theoretical market position), theoEP (theoretical entry price), theoEX (theoretical exit level – 2 N counter move), and theoWL (theoretical winner or loser.)  The code consists of 2 States (0: looking for an entry and 1: looking for an exit.)  This FSM only consists of these two states, so the logic can only flow through these two conditions.  In State 0, long entry and short entry points are calculated using the functions highest and lowest.  If a day’s extreme prices penetrate one of these levels, then the variables theoMP, theoEP and theoEX are assigned the corresponding values.  Most importantly the FSM switches gears to State 1.  Once in State 1, the logic searches for a day that penetrates either a 10 bar low/high or a 2N retracement.  In this example, I have commented out the code that determines if the exit is for sure a 2N loss.  In this example, any loser is considered a loss and fulfills the LTL filter.  Assume you are long and the low of a bar exceeds the lxp (long exit point; greater of 10 bar low or 2 N retracement from entry), then the exit price is either compared to theoEX (2 N loss), which is commented out, or just to the theoEP which is used.  Comment out one or the other to determent LTL.  (If you want to just use a 2N loss to determine a loser then comment out the line of code that uses theoEP and un-comment the code that uses theoEX.)

The Tale of Two Systems

If we don’t use the LTL filter, then we would always enter on every 20 day break out.  Since some 20 day break outs are skipped we must use a fail safe 55 day break out to make sure we can get onboard a trend.  The 55 day break out also uses a 2N loss or a 20 day low/high to determine trade termination.  The 20 day and 55 day algorithms work in concert with each other.  However, the exits must be tied to the entry mechanism.  You wouldn’t want to exit a 55 day long breakout with a 10 bar low penetration.  So we must keep track of which entry mechanism was engaged.

#  Get current entry names from curTradesList[-1].tradename
longEntryName = ""
shortEntryName = ""
if mp >= 1: longEntryName = curTradesList[-mp].tradeName
if mp <=-1: shortEntryName = curTradesList[mp].tradeName
# TS-18 keeps track of every entry name and can be accessed using the
# curTradeList.tradeNames. Since the curTradesList is a list of all
# entryNames (original entry and pyramid entries) you must look back
# in the list the mp (marketPosition variable). mp starts out at 0 and
# goes to 1 if an initial long is entered then 2 if another long is
# added on, and 3 if another and so on and so forth. So if mp is equal
# to 3 then to get to the original entry name we have to look back into
# the list 3 elements. When looking back in a Python list you must use
# a negative number. If mp = 3 then you have to put a (-)sign in front of
# it. If you are short 3 units then mp = -3 so no need to negate.

Once you know the name of the original entry signal you can apply the correct exit logic.

Long Entry and Exit Functions

I have deviated a little bit away from my old standby, top down if then constructs, to determine entry and exit.  I have switched, for reasons I will explain later, to using entry and exit functions.   To save time and space I will only show long entries and exits.

#Only pertinent code is shown

def longEntrySys1():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if ((mp < 0 and buyLevel < ltlBenchMark) or mp == 0) and myHigh[curBar] >= buyLevel and mp < 1 and \
theoWL[curMarket] == -1 and canTrade and totalUnits < maxUnits:
price = max(myOpen[curBar],buyLevel)
marketVal4[curMarket] = 1
marketVal3[curMarket] = price
tradeName = "TurtSys1:B"
numShares = posSize
long2NLoss = roundToNearestTick(price - 2 * NValue[curMarket],-1,myMinMove)
marketVal2[curMarket] = long2NLoss
totalUnits +=1

def longAddOn():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if myHigh[curBar] >= longAddOnPrice and mp >= 1 and marketVal4[curMarket] < 4 and canTrade and totalUnits < maxUnits :
price = max(myOpen[curBar],longAddOnPrice)
tradeName = "TurtAdd:B"+str(marketVal4[curMarket])
marketVal4[curMarket] += 1
numShares = posSize
long2NLoss = roundToNearestTick(price - 2 * NValue[curMarket],-1,myMinMove)
marketVal2[curMarket] = long2NLoss
totalUnits +=1

def longEntrySys2():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if myHigh[curBar] >= buyLevel2 and mp < 1 and canTrade and totalUnits < maxUnits :
price =max(myOpen[curBar],buyLevel2)
tradeName = "TurtSys2:B"
marketVal3[curMarket] = price
marketVal4[curMarket] = 1
numShares = posSize
long2NLoss = price - 2 * NValue[curMarket]
long2NLoss = roundToNearestTick(long2NLoss,1,myMinMove)
marketVal2[curMarket] = long2NLoss
totalUnits +=1

def longExitSys1():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if mp >= 1 and myLow[curBar] <= longExit and longExit > shortLevel and \
longEntryName == "TurtSys1:B" and barsSinceEntry > 1:
price = min(myOpen[curBar],longExit)
tradeName = "TurtSys1-Lx"
numShares = curShares
totalUnits -= numShares

def longExitSys2():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if mp >= 1 and myLow[curBar] <= longExit2 and longExit2 > long2NLoss and \
longEntryName == "TurtSys2:B" and barsSinceEntry > 1:
price = min(myOpen[curBar],longExit2)
tradeName = "TurtSys2:Lx"
marketVal4[curMarket] = 0
numShares = curShares
totalUnits -= numShares

def long2NExit():
global barsSinceEntry,curShares,todaysCTE,totalUnits
if mp >= 1 and myLow[curBar] <= long2NLoss and barsSinceEntry > 1:
price = min(myOpen[curBar],long2NLoss)
tradeName = "Turt2N:Lx"
marketVal4[curMarket] = 0
numShares = curShares
totalUnits -= numShares
Long Entry and Exit Logic

Okay, I know this is getting a bit hairy.  But stick with it, unless you heading out to the bar.  This logic shows 3 long entries (20 and 55 bar break outs and N pyramid) and 3 exits (10 bar low, 20 bar low, and 2N loss.)  The longEntrySys1 only allows  long entries if theoWL[curMarket] was a loser (-1) and totalUnits < maxUnits.  For right now ignore the ltlBenchMark variable.  The 2N loss value is stored in marketVal2 – I store it now because I understood the loss is to be captured using the day of entry’s N.  The next entry involves the pyramiding algorithm (longAddOn).  Remember if you are long, you add onto your position if the market moves different multiples of N.  So to calculate these levels you need to know your current market position and current # of units on.  The marketVal3 variable stores the original break out entryPrice and marketVal4 stores the current number of units that have been put on.  So to calculate the next addOnPrice you must use the following formulae.

 

longAddOnPrice = marketVal3[curMarket] + (marketVal4[curMarket])*.5*NValue[curMarket]
longAddOnPrice = roundToNearestTick(longAddOnPrice,1,myMinMove)

# take the original entry price and add ((current units + 1) * N)
# so if you are long from 42.50 and you only have the intial unit on
# and N = 2 then you next addOnPrice = 42.50 + * ((1)*0.5) = 43.5

# originally I was using N to add contracts it should be 1/2N
AddOn Formula

LongAddon will add units at longAddOnPrice as long as the current unit # for this market is < 4 and totalUnits < maxUnits.  MarketVal4 is updated with the additional unit.

LongEntrySys2 is the 55 day break out algorithm.  Again you are constrained to maxUnitsMarketVal2, marketVal3, and marketVal4 are reset with applicable values:  entryPrice, # units and 2N loss value.

LongExitSys1 is the 10 bar low.  In some cases a 10 bar low is the same as a 20 bar low so you only want to exit if the 10 bar low is not equal to a 20 bar short entry.  TotalUnits is decremented by the current units held by this particular market.  So if you have 3 Euros liquidated and your totalUnit size is 12, then totalUnit size becomes 9.

LongExitSys2 is the 20 bar low.  I only want to exit here if the 20 bar lower is greater than long2Nloss.  If not then I want to be taken out by the long2NLoss value because it is closer to the current market.  Total units are updated here too!

Long2NExit is the fail safe exit.  It is executed if its the last standing exit.  If you are long from longEntrySys1 and the 10 bar low is below this value or if you are long from longEntrySys2 and the 20 bar low is below this level, then this exit is executed.  The number of units is adjusted accordingly.

How Do I Know The Total Number of Units Prior to the Trading Day?

       if firstMarketLoop == False and firstMarketOfDay == 0:
totalUnits = 0
for myCom in range(0,numMarkets):
if len(marketMonitorList[myCom].mp)!=0:
totalUnits += abs(marketMonitorList[myCom].mp[-1])
if totalUnits >= maxUnits:
canTrade = False
else:
canTrade = True

# If its the first market of the day then you loop thru each market
# and accumulate the scalar values of each market's absolute value
# mp. if mp for each EC = 3, CL = 4, US = -4 then totalUnits = 11.
# If totalUnits >= maxUnits then no new initiations
Gather All Your Little Units Up

Because of TS-18’s testing paradigm, I can loop through each market prior to the trading day and gather the information I need.  Just like I was really a portfolio manager.  But you do still need to keep track of units that are added,subtracted after the day starts to make sure you don’t go beyond you maxUnits.  That is why this code is interwoven in the entry/exit functions.

I think that is all the code that needs to be explained, so now let’s look at some results.

Results set #1 LTL is determined by 2N Loss only and only 4 units per market and  only 12 units per portfolio are allowed.

Testing from : 20010102 to: 20200728
-----------------------------------------------------------------------------------------------------------
Avg. Monthly Avg.
SysName Market TotProfit MaxDD ClsTrdDD AvgWin AvgLoss PerWins #Trds MonthRet. StdDev YearlyRet.
TurtSysLMT12... T. Bond-US -23058 69458 68864 8692 -2358 0.10 121 -98 4277 -1213
TurtSysLMT12... 10YNote-TY -27249 47166 35733 3306 -1273 0.10 111 -115 2022 -1448
TurtSysLMT12... Coffee-KC -95781 126443 116906 7742 -2584 0.09 173 -407 4585 -3761
TurtSysLMT12... Cocoa-CC -51430 76810 65880 3410 -1218 0.07 161 -218 1936 -2636
TurtSysLMT12... Sugar-SB 46997 40342 10485 4482 -872 0.13 159 199 2859 2375
TurtSysLMT12... Cotton-CT 84894 51315 29370 12205 -1903 0.10 166 361 4547 4726
TurtSysLMT12... S.Franc-SN -92587 110000 100412 3984 -1978 0.09 146 -393 2672 -4632
TurtSysLMT12... EuroCur-FN -21993 80143 68568 10466 -2951 0.10 119 -93 4184 -1307
TurtSysLMT12... B.Pound-BN -51737 76924 69243 2806 -1919 0.13 122 -220 1974 -2566
TurtSysLMT12... Jap.Yen-JN -54712 100200 94312 8848 -2175 0.08 128 -232 3606 -2680
TurtSysLMT12... Can.Dol-CN 5024 46070 29090 4673 -1268 0.12 139 21 2912 19
TurtSysLMT12... E-Mini-ES -85237 131712 118562 4873 -2045 0.10 193 -362 3180 -5601
TurtSysLMT12... EuroDol-EC 5606 9424 8231 1300 -261 0.10 188 23 538 121
TurtSysLMT12... Gold-ZG -8659 106319 69399 12209 -2989 0.11 121 -36 4994 -511
TurtSysLMT12... Silver-ZI -39780 265105 119995 21813 -3577 0.06 140 -169 15584 -2497
TurtSysLMT12... Copper-ZK 189062 111350 88350 25733 -2720 0.09 153 804 8308 7902
TurtSysLMT12... Crude-ZU 293420 121140 75080 29355 -3615 0.10 174 1248 12582 15110
TurtSysLMT12... HeatOil-ZH 309979 135050 63731 33126 -3461 0.12 122 1319 13497 16116
TurtSysLMT12... RBOB-Un-ZB -65026 79383 72030 10169 -4066 0.12 132 -276 4663 -3115
-------------------------------------------------------------------------------------------------------------------
Totals 317731 544062 or 69.3 % Avg. DD 116682 2768
-----------------------------------------------------------------------------------------------------------


Did our constraints hold?
U T K C S C S F B J C E E Z Z Z Z Z Z
S,Y,C,C,B,T,N,N,N,N,N,S,C,G,I,K,U,H,Z
20011106,0,4,0,0,0,3,0,0,0,0,0,1,1,0,0,2,0,0,1,83810.0
20011107,0,4,0,0,0,0,0,0,0,0,1,1,2,0,0,3,0,0,1,83590.0
20011108,0,4,0,0,0,0,0,0,0,0,1,1,2,0,0,3,0,0,1,78558.0
20011109,0,4,0,0,0,0,0,0,0,0,1,1,2,0,0,0,0,0,1,75789.0
20011112,0,4,0,0,0,0,0,0,0,0,1,1,2,0,0,0,0,0,1,76736.0
20011113,0,4,0,1,0,0,0,1,0,0,1,1,3,0,0,0,0,0,1,75571.0
20011114,0,4,0,1,0,0,0,1,0,0,1,1,3,0,0,0,0,0,1,72669.0
20011115,0,0,0,2,0,0,0,1,0,0,1,1,0,0,0,0,1,1,2,75341.0
20011116,0,0,0,3,0,0,0,1,0,0,1,1,0,0,0,0,1,1,3,72828.0
20011119,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,3,73480.0
20011120,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,3,68288.0
20011121,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,3,69245.0
20011123,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,3,70195.0
20011126,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,3,72686.0
20011127,0,0,0,3,0,0,0,1,1,0,0,1,0,1,0,0,1,1,0,66960.0
20011128,0,0,0,3,0,1,0,1,1,0,0,1,1,1,0,0,1,1,0,65178.0
20011129,0,0,1,3,0,1,0,1,1,0,0,0,1,1,0,1,1,1,0,68671.0
20011130,0,0,1,3,0,1,0,0,1,0,1,0,1,1,0,1,1,1,0,66145.0
20011203,0,0,1,3,0,1,0,0,1,0,1,0,1,1,0,1,1,1,0,62442.0
20011204,0,0,1,3,0,1,0,0,1,0,1,0,1,1,0,1,1,1,0,62805.0
20011205,0,0,1,3,0,1,0,0,1,0,1,0,1,1,0,0,1,1,0,62889.0
LTL=2N,4 per Mkt.,12 per Port.

Results set #2 LTL is any loss and only 4 units per market and  only 12 units per portfolio are allowed.

SysName         Market     TotProfit  MaxDD ClsTrdDD AvgWin  AvgLoss PerWins #Trds  MonthRet.  StdDev  YearlyRet.
-------------------------------------------------------------------------------------------------------------------
TurtSysLMT12... T. Bond-US -55274 79182 75767 5583 -2873 0.13 173 -235 3855 -3146
TurtSysLMT12... 10YNote-TY -57196 63217 61920 1848 -1555 0.11 151 -243 1698 -3034
TurtSysLMT12... Coffee-KC -149568 164618 156843 5031 -2953 0.10 192 -636 3903 -7065
TurtSysLMT12... Cocoa-CC -84170 98210 87330 1406 -1368 0.09 204 -358 1849 -4264
TurtSysLMT12... Sugar-SB 3692 56348 26222 4653 -1019 0.09 188 15 2710 220
TurtSysLMT12... Cotton-CT 51859 90310 39865 8165 -1877 0.11 179 220 4140 2169
TurtSysLMT12... S.Franc-SN -40737 74862 64975 4953 -2330 0.12 168 -173 2922 -1977
TurtSysLMT12... EuroCur-FN 6231 83831 74512 9327 -2887 0.12 152 26 5938 64
TurtSysLMT12... B.Pound-BN -80556 98174 91081 3146 -2086 0.11 150 -342 2069 -3939
TurtSysLMT12... Jap.Yen-JN 39412 67462 48462 10879 -2437 0.11 163 167 4855 2130
TurtSysLMT12... Can.Dol-CN -13860 61420 43960 4028 -1614 0.13 176 -58 3333 -676
TurtSysLMT12... E-Mini-ES -6725 79612 64200 5031 -2354 0.14 211 -28 3753 -2576
TurtSysLMT12... EuroDol-EC 3287 11768 8937 1624 -352 0.09 193 13 798 -137
TurtSysLMT12... Gold-ZG -98179 165769 147549 9403 -3191 0.08 180 -417 4600 -6649
TurtSysLMT12... Silver-ZI 81204 93245 55025 18958 -3837 0.10 134 345 9923 4704
TurtSysLMT12... Copper-ZK 147562 79487 60162 13876 -2920 0.14 154 627 7207 7926
TurtSysLMT12... Crude-ZU 150360 95990 62520 17598 -3985 0.12 172 639 9004 8721
TurtSysLMT12... HeatOil-ZH 48483 113978 90816 21565 -3801 0.10 132 206 7414 2726
TurtSysLMT12... RBOB-Un-ZB -108264 144820 132249 8364 -4528 0.12 155 -460 6219 -5390
-------------------------------------------------------------------------------------------------------------------
Totals -162437 507648 321.6% Avg. DD 109557 3227
-------------------------------------------------------------------
LTL = any loss, 4 per Mkt., 12 per Port.

 

Results set #3 LTL is any loss and only 4 units per market and no portfolio unit constraint.

SysName         Market     TotProfit  MaxDD ClsTrdDD AvgWin  AvgLoss PerWins #Trds  MonthRet.  StdDev  YearlyRet.
-------------------------------------------------------------------------------------------------------------------
TurtSysNoLMT T. Bond-US 23941 101358 81148 13344 -4065 0.08 516 101 9593 -314
TurtSysNoLMT 10YNote-TY -2400 81591 70501 7013 -2101 0.08 513 -10 5063 -832
TurtSysNoLMT Coffee-KC -174275 197875 184962 13151 -4350 0.07 575 -741 11142 -7228
TurtSysNoLMT Cocoa-CC -125430 146210 133400 3997 -1932 0.07 600 -533 4145 -6421
TurtSysNoLMT Sugar-SB 78386 62878 32808 6035 -1462 0.09 513 333 4863 3838
TurtSysNoLMT Cotton-CT 151064 77095 61320 11196 -2411 0.08 520 642 7874 7054
TurtSysNoLMT S.Franc-SN -34375 177850 131500 11033 -3201 0.08 566 -146 8408 -1344
TurtSysNoLMT EuroCur-FN 114193 167112 146399 17676 -4154 0.08 542 485 11508 5673
TurtSysNoLMT B.Pound-BN -37506 92762 78024 9060 -3056 0.08 543 -159 6434 -1571
TurtSysNoLMT Jap.Yen-JN 48624 99774 88612 11344 -3623 0.09 543 206 8107 3337
TurtSysNoLMT Can.Dol-CN -88585 171570 140970 7185 -2366 0.07 564 -376 5793 -4799
TurtSysNoLMT E-Mini-ES -81237 251775 228775 11065 -3421 0.07 582 -345 8673 -8156
TurtSysNoLMT EuroDol-EC 11793 21581 19793 2150 -376 0.06 542 50 1505 257
TurtSysNoLMT Gold-ZG 6790 133329 93029 16987 -4705 0.07 553 28 12443 438
TurtSysNoLMT Silver-ZI 655209 242620 111574 30108 -5615 0.09 521 2788 29292 28558
TurtSysNoLMT Copper-ZK 232187 139400 120200 18379 -4715 0.09 543 988 14207 9036
TurtSysNoLMT Crude-ZU 530770 190529 148449 26105 -5482 0.09 518 2258 16835 21271
TurtSysNoLMT HeatOil-ZH 447804 219485 191471 28026 -6038 0.08 569 1905 18253 17260
TurtSysNoLMT RBOB-Un-ZB 578985 172663 106338 29873 -6727 0.09 546 2463 22550 22856
-------------------------------------------------------------------------------------------------------------------
Totals 2335943 655121 26.8% Avg. DD 265406 10369
-------------------------------------------------------------------
LTL = any loss, 4 per Mkt., No Port. limit

Results set #4a LTL is any loss and no AddOns and only 12 units per portfolio are allowed.  Result set#4b same as #4a but no portfolio limitations.

Testing from : 20010102 to: 20200728
-----------------------------------------------------------------------------------------------------------
Avg. Monthly Avg.
SysName Market TotProfit MaxDD ClsTrdDD AvgWin AvgLoss PerWins #Trds MonthRet. StdDev YearlyRet.
TurtSysNoLMT T. Bond-US 55394 25623 21057 3581 -1668 0.40 121 235 2622 2656
TurtSysNoLMT 10YNote-TY -11373 26063 24079 1829 -963 0.31 123 -48 1326 -622
TurtSysNoLMT Coffee-KC -23587 39043 33287 2912 -2078 0.38 141 -100 3231 -986
TurtSysNoLMT Cocoa-CC -28860 32590 31020 1136 -848 0.33 151 -122 1211 -1381
TurtSysNoLMT Sugar-SB 20890 15826 10372 1609 -636 0.35 133 88 1275 1160
TurtSysNoLMT Cotton-CT 51234 22405 18245 2623 -1170 0.41 128 218 2160 2572
TurtSysNoLMT S.Franc-SN -3962 32387 28900 2705 -1436 0.34 147 -16 2296 16
TurtSysNoLMT EuroCur-FN 53812 29943 23693 4602 -1871 0.36 120 228 3045 2669
TurtSysNoLMT B.Pound-BN -26687 35018 33262 2229 -1336 0.32 132 -113 1851 -1084
TurtSysNoLMT Jap.Yen-JN -16312 48662 49850 2952 -1659 0.33 142 -69 2412 -450
TurtSysNoLMT Can.Dol-CN -30535 51340 46660 1712 -1069 0.31 143 -129 1569 -1633
TurtSysNoLMT E-Mini-ES -4725 54850 49850 2975 -1715 0.36 146 -20 2705 -1543
TurtSysNoLMT EuroDol-EC 1906 6599 6081 663 -177 0.23 141 8 448 -11
TurtSysNoLMT Gold-ZG 10420 45359 34409 3785 -2110 0.37 118 44 3363 -93
TurtSysNoLMT Silver-ZI 102339 78635 51809 7458 -2836 0.36 120 435 7141 4374
TurtSysNoLMT Copper-ZK 85024 42450 37012 4883 -2057 0.40 124 361 3797 3838
TurtSysNoLMT Crude-ZU 132640 43979 33210 6163 -2658 0.42 126 564 4529 7905
TurtSysNoLMT HeatOil-ZH 112766 58758 50451 6271 -2928 0.41 128 479 4657 5709
TurtSysNoLMT RBOB-Un-ZB 96701 54507 40835 8228 -3625 0.37 127 411 5790 5706
-------------------------------------------------------------------------------------------------------------------
Totals 577088 200705 or 32.0 % Avg. DD 62834 2511
-----------------------------------------------------------------------------------------------------------

No Portfolio Limitations

Testing from : 20010102 to: 20200728
-----------------------------------------------------------------------------------------------------------
Avg. Monthly Avg.
SysName Market TotProfit MaxDD ClsTrdDD AvgWin AvgLoss PerWins #Trds MonthRet. StdDev YearlyRet.
TurtSysNoLMT T. Bond-US 28208 31087 26490 3420 -1719 0.37 160 120 2898 1062
TurtSysNoLMT 10YNote-TY 5935 22548 20687 1825 -875 0.34 164 25 1469 80
TurtSysNoLMT Coffee-KC -37531 51350 42531 2928 -2043 0.37 179 -159 3431 -1467
TurtSysNoLMT Cocoa-CC -35890 42600 40430 1065 -836 0.34 194 -152 1329 -1828
TurtSysNoLMT Sugar-SB 21909 18034 10677 1574 -687 0.36 159 93 1439 1074
TurtSysNoLMT Cotton-CT 43394 30145 25295 2628 -1172 0.38 164 184 2335 1936
TurtSysNoLMT S.Franc-SN -28375 53737 45462 2698 -1529 0.33 190 -120 2592 -1342
TurtSysNoLMT EuroCur-FN 16875 65574 58049 4276 -1973 0.33 172 71 3490 1033
TurtSysNoLMT B.Pound-BN -7512 21712 21881 2336 -1251 0.33 174 -31 1899 -177
TurtSysNoLMT Jap.Yen-JN 17649 52237 50887 2991 -1633 0.37 172 75 2537 1361
TurtSysNoLMT Can.Dol-CN -29540 50070 45470 1852 -1019 0.30 184 -125 1779 -1720
TurtSysNoLMT E-Mini-ES 9300 61200 56300 2594 -1610 0.39 181 39 2906 -1482
TurtSysNoLMT EuroDol-EC -1074 11637 11243 530 -179 0.24 181 -4 469 -165
TurtSysNoLMT Gold-ZG 16090 39429 27039 3917 -2213 0.38 170 68 4005 999
TurtSysNoLMT Silver-ZI 193159 70970 42529 7269 -2910 0.40 161 821 8641 8003
TurtSysNoLMT Copper-ZK 92337 32600 27800 4307 -2157 0.42 164 392 4216 3947
TurtSysNoLMT Crude-ZU 192990 48569 42719 6467 -2570 0.42 157 821 5100 8521
TurtSysNoLMT HeatOil-ZH 176014 56004 47697 6794 -2804 0.40 170 748 5619 7734
TurtSysNoLMT RBOB-Un-ZB 185597 79753 65985 7717 -3504 0.41 168 789 6935 7758
-------------------------------------------------------------------------------------------------------------------
Totals 859538 196012 or 22.8 % Avg. DD 76334 3264
-----------------------------------------------------------------------------------------------------------
LTL = any loss. 12 per port., no AddOn

 

This last analysis is interesting, because trends have changed over the years.  In the Turtle’s heyday trends occurred infrequently, but when they did they held for long periods of time.  This is why the AddOn trade was so successful.  I hope this post was beneficial and let me know if you want the Python code.  I will put this in the download for those that buy my latest book!

I will go over some of the other nuances I encountered while programming this monstrosity in a later post.  Keep an eye open on www.georgepruitt.com too!

 

Tags: , , , , ,

classic

yes

About This Site

This site is home to George’s Excellent Adventure into TradingSimula_18 and Python.  George grew tired of the old and expensive back testing software so he created his own and now is able to test and develop  Trend Following Systems utilizing EOD data and EOD intra-testing portfolio management.  This software, TradingSimula_18 can be found in his Trend Following Systems: A DIY Project – Batteries Included book – now in its 2nd edition.

May 2024
M T W T F S S
 12345
6789101112
13141516171819
20212223242526
2728293031