Systems

This page is under construction. Plans include to add:

  1. A brief discussion of the system, including
    • where the system is taken from
    • entry and exit rules
    • position sizing, etc
  2. Backtesting results

Adaptive Price Zone

//AdaptivePriceZone.afl
//Taken from Quantitative Trading System (2nd Edition) by Howard Bandy Pg 148

//Trading system based on Lee Leibfarth's Trading with An Adaptive Price Zone
//TASC September 2006 Issue

function DblSmoothEMA(price, length)
{
	period = IIf(Length < 0, 1, sqrt(Length));
	smooth = 2 / (period + 1);
	
	return AMA( AMA(price, smooth), smooth);
}

SetTradeDelays(0,0,0,0);
BuyPrice = C;
SellPrice = C;

price = C;
period = 50; 
BandPct = 2;

DsEMA = DblSmoothEMA(price, period);
RangeDsEMA = DblSmoothEMA(H-L, period);

UpBand = BandPct * RangeDsEMA + DsEMA;
DnBand = DsEMA - BandPct * RangeDsEMA;

ADXThshold = 30;
ADXLength = 14;
ADXValue = ADX(ADXLength);

Buy = ADXValue <= ADXThshold AND Low <= DnBand;
Sell = ADXValue > ADXThshold;

Buy = ExRem(Buy, Sell);
Sell = ExRem(Sell, Buy);

Plot(UpBand, "UpBand", colorLightGrey);
Plot(DnBand, "DownBand", colorLightGrey);

PlotShapes(Buy*shapeUpArrow, colorGreen, 0, DnBand, -24);
PlotShapes(Sell*shapeDownArrow, colorRed, 0, UpBand, -24);

Naïve System

// BuyAfterAnNDaySequenceMultiPosition.afl
// Taken or adapted from Mean Reversion Trading Systems by Howard Bandy

eq = Param("Fixed Equity", 100000, 1, 10000000);
percentEQ = Param("Percentage of EQ to risk", 1, 0.01, 1, 0.01);
SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", eq);
SetPositionSize(percentEQ*eq, spsValue);

MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);
BuyPrice = SellPrice = Close;
//ObFn == K-ratio, CAR/MDD, expectancy

//Define a day as rising based on the closing price
Rising = C > Ref(C, -1);
Falling = C < Ref(C, -1);

//Any stop loss
SL = ParamToggle("Stop Loss", "No|Yes", 1);
StopLossThreshold = Param("Stop Loss Threshold", 20, 1, 100, 1);

//The number of dats in the sequence
//N = Optimize("N", 3, 1, 7, 1);
N = Param("N", 3, 1, 7, 1);

//Direction. 1 == Rising, 0 == Falling
Direction = 0; 	//Optimize("Direction", 0,0,1,1);

//Exit variables
//Maximum holding period
//HoldDays = Optimize("HoldDays", 4,1,7,1);
HoldDays = Param("HoldDays", 7,1,7,1);

//Profit target
//ProfitTarget = Optimize("ProfitTarget", 0.4,0.2,4,0.2);
ProfitTarget = Param("ProfitTarget", 0.4,0.2,4,0.2);

//Detect an N day sequence

if (Direction == 1)
	NDaySequence = Sum(Rising, N) >= N;
else	
	NDSequence = Sum(Falling, N) >= N;
	
Buy = NDSequence;
Sell = 0;


ApplyStop(stopTypeProfit, stopModePercent, ProfitTarget);
ApplyStop(stopTypeNBar, stopModeBars, HoldDays);
if (SL)
	ApplyStop(stopTypeLoss, stopModePercent, StopLossThreshold);


//Plots

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

shapes = IIf(Buy, shapeUpArrow, shapeNone);
shapecolors = IIf(Buy, colorGreen, colorWhite);
PlotShapes(shapes, shapecolors);

Filter = 1;
AddColumn(Sell, "Sell");

PIRDPO

/*DetrendedPriceOscillator_System.afl
Compute and plot the high frequency residual after detrending */
// Copied or adapted from Mean Reversion Trading Systems by Howard Bandy

eq = Param("Fixed Equity", 100000, 1, 10000000);
percentEQ = Param("Percentage of EQ to risk", 1, 0.01, 1, 0.01);
SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", eq);
SetPositionSize(percentEQ*eq, spsValue);

MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);
BuyPrice = SellPrice = Close;

function PIR(p, Length)
{

	//compute the PIR of series p, relative to its position over a lookback window of Length
	
	ll = LLV(p, Length);
	hh = HHV(p, Length);
	
	return 100*(p-ll)/(hh-ll);

}

MA1Length = Optimize("MA1Length", 3, 1, 50, 1);
PIRLength = Optimize("PIRLength", 12, 2, 30, 1);

BuyLevel = Optimize("BuyLevel", 10, 1, 30, 1);

MA1 = MA(C, MA1Length);

DPO = (C-MA1) / MA1;
PIRDPO = PIR(DPO, PIRLength);

Buy = PIRDPO < BuyLevel;
Sell = BarsSince (Buy) >= 3;

//Plot Price
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 


Plot(MA1, "MA1", colorBlue, styleLine|styleThick);
Plot(PIRDPO, "PIRDPO", colorGreen, styleLine|styleOwnScale, 0, 100);

Connors RSI Pullback

//ConnorsRSIPullback.afl

//ConnorsRSI is defined in "An introduction of ConnorsRSI" published by TradingMarkets.

/////////////////////////// System Settings ///////////////////////////

OptimizerSetEngine("cmae");

eq = Param("Fixed Equity", 100000, 1, 10000000);
percentEQ = Param("Percentage of EQ to risk", 1, 0.01, 1, 0.01);
SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", eq);
SetPositionSize(percentEQ*eq, spsValue);

MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);
BuyPrice = SellPrice = Close;

/////////////////////////// User Functions ///////////////////////////

function StreakDuration(p)
{
	t[0] = 0;
	
	for (i = 1; i < BarCount; i++)
	{
		t[i] = 0;
		
		if (p[i] > p[i-1])
			if (t[i-1] >= 0)
				t[i] = t[i-1] + 1;
			else
				t[i] = 1;
		else if (p[i] < p[i-1])
			if (t[i-1] <= 0)
				t[i] = t[i-1] - 1;
			else
				t[i] = -1;			
	}
	
	return(t);

}

function ConnorsRSI(V1, V2, V3)
{

	t1 = RSIa(C, V1);
	t2 = RSIa(StreakDuration(C), V2);
	OneDayReturn = (C - Ref(C, -1)) / Ref(C, -1);
	t3 = PercentRank(OneDayReturn, V3);
	return ((t1+t2 + t3) / 3);
}

/////////////////////////// Parameters ///////////////////////////

w = Optimize("W", 8, 1, 20, 1);		//Percent below previous close
x = Optimize("X", 10, 5, 95, 5);	//Position in Range of Close
y = Optimize("Y", 5, 5, 95, 5);		//ConnorsRSI for entry
z = Optimize("Z", 10, 0, 16, 1);	//Entry limit
n = Optimize("N", 80, 5, 95, 5);	//ConnorsRSI for exit

/////////////////////////// Indicators ///////////////////////////
LowBelowClose = Max(100*(Ref(C, -1) - L) / Ref(C, -1), 0);
PIROfClose = 100*(C-L) / (H-L);
LimitEntry = (1-0.01*z) * C;

/////////////////////////// Rules ///////////////////////////
ER1 = ADX(10) > 30;
ER2 = LowBelowClose > w;
ER3 = PIROfClose < x;
ER4 = ConnorsRSI(3, 2, 100) < y;
ER5 = L < Ref(LimitEntry, -1);

XR1 = ConnorsRSI(3, 2, 100) > n;

/////////////////////////// Signals ///////////////////////////

Buy = Ref(ER1, -1) AND Ref(ER2, -1) AND Ref(ER3, -1) AND Ref(Er4, -1) AND ER5;

BuyPrice = Min(O, Ref(LimitEntry, -1));

Sell = XR1;
SellPrice = Close;

/////////////////////////// Plots ///////////////////////////
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

Dual Time Frame

// Dual Time Frame
// Taken or adapted from Mean Reversion Trading Systems by Howard Bandy
//Use RSI on weekly data as a filter. Take positions when RSI on daily data is at a low level

/////////////////////////// System Settings ///////////////////////////

OptimizerSetEngine("cmae");
eq = Param("Fixed Equity", 100000, 1, 10000000);
percentEQ = Param("Percentage of EQ to risk", 1, 0.01, 1, 0.01);
SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", eq);
SetPositionSize(percentEQ*eq, spsValue);

MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);
BuyPrice = SellPrice = Close;


/////////////////////////// Parameters ///////////////////////////

DailyRSILB = Optimize("DailyRSILB", 3, 2, 6, 1);
DailyBuyLevel = Optimize("DailyBuyLevel", 15, 5, 30, 1);
WeeklyRSILB = Optimize("WeeklyRSILB", 5, 1, 10, 1);
WeeklyPermitLevel = Optimize("WeeklyPermitLevel", 64, 10, 90, 1);

/////////////////////////// Indicators ///////////////////////////

//The data base is daily
//Form weekly bars

TimeFrameSet(inWeekly);
WRSI = RSI(WeeklyRSILB);
TimeFrameRestore();

//Expand weekly indicator to daily periodicity
WeeklyRSI = TimeFrameExpand(WRSI, inWeekly);
DailyRSI = RSI(DailyRSILB);

//Rules
Permission = WeeklyRSI > WeeklyPermitLevel;

//Signals
Buy = Permission AND DailyRSI < DailyBuyLevel;
Sell = DailyRSI > 75; 		//Or !Permission
Buy = ExRem(Buy, Sell);		//Remove excess signals
Sell = ExRem(Sell, Buy);

/////////////////////////// Plots ///////////////////////////

SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

shapes = IIf(Buy, shapeUpArrow, shapeNone);
shapecolors = IIf(Buy, colorGreen, colorWhite);
PlotShapes(shapes, shapecolors);
Plot(WeeklyRSI, "WeeklyRSI", colorGreen, styleDots|styleThick|styleLeftAxisScale);
Plot(DailyRSI, "DailyRSI", colorBlue, styleLine|styleThick, styleLeftAxisScale);

Three Days High Low Long

Entry rules are based on the three days high-low long system from the book “High Probability ETF Trading” by Larry Connors and Cesar Alvarez.

A trade simulator that allows us to test entering the first order, the second order, or both orders.

//SimulateMultiplePositions.afl
// Taken or adapted from Mean Reversion Trading Systems by Howard Bandy
//This program implements the 3 Day High Low system for both basic and aggressive trades.
//It allows either level of trades to be isolated so they can be evaluated independently.

//This is a simplified trading system simulator.

//Data is stored in arrays, one element for each data bar
//Nheld - Number of long positions held
//EntryP1 - Entry price for Position 1
//EntryP2 - Entry Price for Position 2
//Buy1 - Signal to enter the first position
//Buy2 - Signal to enter the second position
//SellAll - Signal to exit all positions

/////////////////////////// System Settings ///////////////////////////

OptimizerSetEngine("cmae");

eq = Param("Fixed Equity", 100000, 1, 10000000);
percentEQ = Param("Percentage of EQ to risk", 10, 1, 100, 1);
SetOption("ExtraColumnsLocation", 1);
SetOption("CommissionMode", 2); 	//$ per trade
SetOption("CommissionAmount", 5);
SetOption("InitialEquity", eq);
//SetPositionSize(percentEQ*eq, spsValue);
SetPositionSize(percentEQ, spsPercentOfEquity);

MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetBacktestMode(backtestRegularRawMulti);
SetTradeDelays(0,0,0,0);
BuyPrice = SellPrice = Close;

/////////////////////////// User Functions ///////////////////////////

//Parameters
LongTermMALength = 200;
ShortTermMALength = 5;
ExitMALength = 5;

/////////////////////////// Indicators ///////////////////////////
LongTermMA = MA(C, LongTermMALength);
ShortTermMA = MA(C, ShortTermMALength);

/////////////////////////// Rules ///////////////////////////

//Filter - Close must be above its long term moving average
FilterRule1 = C > LongTermMA;

//Close is below its short term moving average
EntryRule1 = C < ShortTermMA;

//Three days of lower lows and lower highs
EntryRule2 = 	Ref(H, -2) < Ref(H, -3) AND Ref(H, -1) < Ref(H, -2) AND H < Ref(H, -1) AND 
				Ref(L, -2) < Ref(L, -3) AND Ref(L, -1) < Ref(L, -2) AND L < Ref(L, -1);

//Clsoe is above its short term moving average
ExitRule1 = C > ShortTermMA;

/////////////////////////// Trading System Simulator Loops ///////////////////////////

//Initialize

Nheld = 0 * Close;
EntryP1 = 0 * Close;
EntryP2 = 0 * Close;
Buy1 = 0 * Close;
Buy2 = 0 * Close;
SellAll = 0 * Close;

// Loop to process all data bars

for (i = 1; i < BarCount; i++)
{

	//At the open. No actions at the open.
	
	//Intrabar. No actions intrabar.
	
	//At the close. 
	if (NHeld[i-1] > 0 && ExitRule1[i])
	{
		//Process Exits
		SellAll[i] = 1;
		NHeld[i] = 0;
	}else
	{
		//Process Entries	
		switch (NHeld[i-1])
		{
		
			case 0:		//holding none - check for buy
			{
				if (FilterRule1[i] AND EntryRule1[i] AND EntryRule2[i])		//Entry a long position
				{
					Buy1[i] = 1;
					EntryP1[i] = Close[i];
					NHeld[i] = 1;
				}else		//no action
				{
					NHeld[i] = 0;
				}
				break;
			}
			case 1:		//holding one - check for aggressive entry
			{
				
				if (Close[i] < EntryP1[i-1])		//Take a second position
				{
					Buy2[i] = 1;
					EntryP2[i] = Close[i];
					NHeld[i] = 2;
					EntryP1[i] = EntryP1[i-1];
				}else		//no action
				{
					NHeld[i] = 1;
					EntryP1[i] = EntryP1[i-1];
				}				
				break;				
			}
			case 2:		//Holding two - the maximum, no action
			{
				NHeld[i] = 2;
				EntryP1[i] = EntryP1[i-1];
				EntryP2[i] = EntryP2[i-1];
				break;
			}	
		}	//end switch		
	}	//end of else block (process entries)
}	//end of for loop

//Pass signals to amibroker for reporting
TestingEntry = 3; 	// Trades at Level 1 or 2; 3 means both

switch(TestingEntry)
{
	case 1:
	{
		//First buy
		Buy = Buy1;
		BuyPrice = EntryP1;
		Sell = SellAll;
		SellPrice = Close;
		break;	
	}
	case 2:
	{
		//Second buy
		Buy = Buy2;
		BuyPrice = EntryP2;
		Sell = SellAll;
		SellPrice = Close;
		break;
	
	}
	case 3:
	{
		//Take all trades
		Buy = Buy1 + Buy2;
		BuyPrice = IIf(Buy1, EntryP1, IIf(Buy2, EntryP2, 0));
		Sell = SellAll;
		SellPrice = Close;
		break;
	
	}

}	//end switch

/////////////////////////// Plots ///////////////////////////
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorDefault ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

Plot(LongTermMA, "LongTermMA", colorRed, styleLine);
Plot(ShortTermMA, "ShortTermMA", colorGreen, styleLine);

Shapes = IIf(Buy, shapeUpArrow, IIf(Sell, shapeDownArrow, shapeNone));
ShapeColors = IIf(Buy, colorGreen, IIf(Sell, colorRed, colorWhite));

PlotShapes(Shapes, ShapeColors);


Trade SPY from VIX

//TradeSPYFromVIX.afl
// Taken or adapted from Mean Reversion Trading Systems by Howard Bandy
//Using VIX as the source of data for the signals. When VIX is high, buy the surrogate. 

//This system uses a 2 period RSI of VIX

/////////////////////////// System Settings ///////////////////////////

OptimizerSetEngine("cmae");
SetOption("InitialEquity", 100000);
MaxPos = 1;
SetOption("MaxOpenPositions", MaxPos);
SetPositionSize(10000, spsValue);

SetOption("ExtraColumnsLocation", 1);
SetTradeDelays(0, 0, 0, 0);
BuyPrice = SellPrice = Close;

/////////////////////////// Parameters ///////////////////////////

RSILB = Optimize("RSILB", 4, 2, 6, 1);
BuyLevel = Optimize("BuyLevel", 83, 1, 99, 1);
SellLevel = Optimize("SellLevel", 9, 1, 99, 1);
ProfitTarget = Optimize("ProfitTarget", 0.5, 0.5, 2, 0.25);

/////////////////////////// Indicators ///////////////////////////
VIXC = Foreign("$VIX", "C");
RSI2 = RSIa(VIXC, RSILB);
Buy = RSI2 > BuyLevel;
Sell = RSI2 < SellLEvel;

ApplyStop(stopTypeProfit, stopModePercent, profitTarget);