May 2019 Technical Analysis of Stocks & Commodities article

The May 2019 issue of Technical Analysis of Stocks and Commodities did not have an AmiBroker code for the “Traders Tips” article. I assume @Tomasz was busy (or didn't think the article was interesting).

So I am taking a stab at it here (its been raining much of the day and my golf outing was cancelled). The article was “Backtesting A Mean-Reversion Strategy In Python” by Anthony Garner.

Certainly nothing revolutionary but a worthwhile look at mean reversion. I am not familiar with Python so my code may not be correct.

As usual, in the “tips” section of the magazine the other platform vendors offer their codes and as best I can tell it was interesting to see that some of them had different interpretations of the rules (the entries seemed consistent but the exit rules varied). I think this may be because the author did not detail his rules in the article text but refers to his code as the source of the rules. Also, I was uncertain but the author did not appear to use a “Trade Delay” from signal generation to trade execution but many of the other software platforms did interpret this system to have a delay. Whether that is what they interpreted as being in the python code, or they just felt it was the more reasonable / realistic method for this strategy I do not know.

He tests his rules on the SPY from 1993 to 2018 and in my backtest I get very similar but not exactly the same results as the original author (perhaps my data is slightly different, perhaps my code is not a correct interpretation of the original).

// Technical Analysis of Stocks and Commodities, May 2019
// Backtesting A Mean-Reversion Strategy In Python by Anthony Garner
// v1.0 by @portfoliobuilder 

InitialPortfolio = 10000;
MaxPositions = 1;

// Options
SetOption( "CommissionAmount", 0.0 );
SetOption( "MaxOpenPositions", MaxPositions );
SetOption( "InitialEquity", InitialPortfolio );
SetOption( "AllowSameBarExit", True );
SetOption( "AllowPositionShrinking", True );
//SetPositionSize( GetOption("InitialEquity") / MaxPositions, spsValue);
SetPositionSize( 100 / MaxPositions, spsPercentOfEquity );

// figure 1 in the article show No Trade Delay
// but in the other platforms in the "tips" section usually use a one bar delay
entryDelay 	= 0; // realistically consider using a 1 instead of zero
exitDelay 	= 0; // or add some method of pre-calculating triggers for order generation
SetTradeDelays( entryDelay, exitDelay, entryDelay, exitDelay );
BuyPrice = ShortPrice = IIf( entryDelay == 0, Close, Open );
SellPrice = CoverPrice = IIf( exitDelay == 0, Close, Open );


// defaults as per the article
ShortTermPds	= Param( "Short Term M.A. Periods", 10, 1, 50, 1 ); // short term M.A. periods
LongTermPds		= 10 * ShortTermPds; // long term M.A. periods

ShortTermMA		= MA( C, ShortTermPds );
LongTermMA		= MA( C, LongTermPds );

OversoldLevel 	= -1; // Z-Score
OverboughtLevel = 1;

LongExitLevel	= -0.5;
ShortExitLevel	= 0.5;

Z_ScorePds 		= Param( "Period", 10, 1, 50, 1 ); // the article uses 10 days as default
ZScore 			= ( Close - MA( Close, Z_ScorePds ) ) / StDev( Close, Z_ScorePds );

Buy 			= ShortTermMA > LongTermMA AND Cross( OversoldLevel, ZScore );
Sell 			= Cross( ZScore, LongExitLevel );

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

Short 			= ShortTermMA < LongTermMA AND Cross( ZScore, OverboughtLevel );
Cover 			= Cross( ShortExitLevel, ZScore );

Short 			= ExRem( Short, Cover );
Cover 			= ExRem( Cover, Short );

InLong 			= Flip( Buy, Sell ); // not sure this is necessary but 
InShort 		= Flip( Short, Cover ); // I am using it in the exploration output

// Explore //
// for output chart like in the article
TextList = "Out\nLong\nShort\nLong and Short";
TextSelector = 1 * InLong + 2 * InShort; // the last condition of "3" better not happen or I messed up

Filter = 1;
Z_Color = IIf( ZScore < OversoldLevel, colorGreen, IIf( ZScore > OverboughtLevel, colorRed, colorDefault ) );
stMAcolor = IIf( ShortTermMA > LongTermMA, colorlime, IIf( ShortTermMA < LongTermMA, colorRose, colorDefault ) );
Position_color = IIf( InLong, colorGreen, IIf( InShort, colorRed, colorDefault ) );

AddColumn( C, "Close" );
AddColumn( StDev( Close, Z_ScorePds ), "Std", 1.2 );
AddColumn( ZScore, "Z-Score", 1.2, colorDefault, Z_Color );
AddMultiTextColumn( TextSelector, TextList, "Position", 1.2, Position_color, colorDefault );
AddColumn( ShortTermMA, "MA(" +  ShortTermPds  + ")", 1.2, colorDefault, stMAcolor );
AddColumn( LongTermMA, "MA(" +  LongTermPds  + ")" );
//AddColumn( Buy, "Buy" );
//AddColumn( Sell, "Sell" );

// Charting the Z Score //
Plot( ZScore, "Z-Score", colorLightBlue, styleLine | styleThick );
PlotGrid( OversoldLevel, colorlime, 1 );
PlotGrid( 0, colorWhite, 1 );
PlotGrid( OverboughtLevel, colorRed, 1 );

Results look something like this
image

And an Exploration similar to (but more colorful than) the author's example,
image

I hope it is of some entertainment to some and I am open to anyone improving upon this effort.

22 Likes

Great job. Thank you so much for the contribution.

1 Like