The original Turtle system was made famous because it was supposed to show that anyone could become a good commodities trader—all you needed was to follow some specific rules that implemented a good trading system. The implementation shown below is based on Altucher’s book, which uses its own choice of 22 week (100 day) and 55 week (385 day) moving averages. This is what he calls a “slow turtle” strategy that is intended to catch very long (and major) trends. He does this by using very long moving averages. The original Turtle system used shorter averages. (It is worth saying that there are many variations of the Turtle system on the Internet.) There are three interesting things about this single-state (always in the market) implementation. It uses very long moving averages (100 and 385 days). It only trades on Monday mornings (in the OnBarOpen method). And it reverses existing positions by buying or selling a trade quantity that is twice the size of the existing position.

using OpenQuant.API;
using OpenQuant.API.Indicators;

using System.Drawing;

public class MyStrategy : Strategy
{
	// quantity to buy on a trade
	[Parameter("Order quantity (number of contracts to trade)")]	
	double Qty = 100;
	
	[Parameter("Bar Block Size")]
	int BarBlockSize = 6;
	
	[Parameter("Length of SMA in blocks (weeks)", "SMA")]
	int FastSMALength = 22;
	
	[Parameter("Length of SMA in blocks (weeks)", "SMA")]
	int SlowSMALength = 55;

	int positionInBlock = 0;
	bool buyOnNewBlock;
	bool sellOnNewBlock;
	
	// two moving averages
	SMA fastSMA;
	SMA slowSMA;
	
	public override void OnStrategyStart()
	{		
		// set up the fast average
		fastSMA = new SMA(Bars, FastSMALength * 7, Color.Yellow);		
		Draw(fastSMA, 0);
		// set up the slow average
		slowSMA = new SMA(Bars, SlowSMALength * 7, Color.Pink);		
		Draw(slowSMA, 0);
	}

	public override void OnBarOpen(Bar bar)
	{
		// calc quantity to reverse a position
		double orderQty = 2 * Qty;

		if (!HasPosition)
			orderQty = Qty;

		if (positionInBlock == 0)
		{
			if (buyOnNewBlock)
			{
				Buy(orderQty, "Reverse to Long");

				buyOnNewBlock = false;
			}

			if (sellOnNewBlock)
			{
				Sell(orderQty, "Reverse to Short");				

				sellOnNewBlock = false;
			}
		}
	}

	public override void OnBar(Bar bar)
	{
		// if our SMAs contain the current bar date
		if (fastSMA.Contains(bar.DateTime) && slowSMA.Contains(bar.DateTime))
		{
			// see which one is above the other
			Cross cross = fastSMA.Crosses(slowSMA, bar);

			if (cross == Cross.Above)
				buyOnNewBlock = true;

			if (cross == Cross.Below)
				sellOnNewBlock = true;
		}

		positionInBlock = (positionInBlock++) % BarBlockSize;
	}
}