---
title: "The Enigmatic Turtle Trading System in Python"
url: https://www.quantifiedmodels.com/the-enigmatic-turtle-trading-system-in-python/
date: 2023-05-12
modified: 2023-06-06
author: "Quantified Models"
image: https://www.quantifiedmodels.com/wp-content/uploads/2023/05/BLOG-WEB-Quantified-Models.png
categories: ["Python"]
type: post
lang: en
---

# The Enigmatic Turtle Trading System in Python

[**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.[ Go to a Amazon](https://www.amzn.com/B09YNDGJW7).

 

## 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](http://www.pinnacledata.com/).

 

 

## 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

### Finite State Machine to Determine LTL (Last Trade Loser)

I showed how to do this in my other blog in EasyLanguage [George’s Blog](http://www.georgepruitt.com/).  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

 

 
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.

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.

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** 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.

AddOn Formula

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

**LongEntrySys2** is the **55** day break out algorithm.  Again you are constrained to **maxUnits**.  **MarketVal2**, **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?

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.

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.

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.

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.

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.

Article written by George Pruitt

We have several videos available on our YouTube channel that you may find very useful in developing trading systems.

We hope this information has been useful to you.
