This page is under construction. Plans include to add:
- A brief discussion of the system, including
- where the system is taken from
- entry and exit rules
- position sizing, etc
- 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);