TASC 2019-05 | Backtesting A Mean Reversion Strategy (Garner)

Modified on 2019/04/22 14:26 by Eugene — Categorized as: TASC Traders Tips

Traders' Tip text

Wealth-Lab owes to C# for the power of extensibility and ability to express trading rules of any complexity. However, its strong point is also that no programming may be required to "wire-frame" a trading system idea.

The Strategy Builder lets us throw building blocks known as Rules onto a "drawing board", group them together or divide them into separate chunks:

  1. Add a pair of few entry Buy/Sell rules (or Short/Cover if you prefer)
  2. Drag and drop some "Indicator crosses below (above) a value" and pick "ZScore" from the Community Indicators group (requires Community Indicators library v2019.04 or greater)
  3. Do the same for "Fast moving average is above (below) Slow moving average" to take trades only if the long term trend is in your favor
  4. For the exit repeat step #2 with an opposite Z-Score value.


Image

Figure 1. Creating a mean-reversion Strategy in the Rule Wizard.


There's one more exit rule in author's Python code which liquidates positions if Z-Score flips from positive to negative or vice versa without going through the neutral zone. As shown on Figure 1, implementing it is a matter of dropping an OR divider with a couple of extra conditions below it.

If everything's done right your trading system will generate trades similar to those on Figure 2. Those of you who prefer C# to take complete control will find a sample Strategy code below.


Image

Figure 2. Characteristic trades on a Daily chart of Coca Cola (data provided by Yahoo)


Bottom line: the advantage of Wealth-Lab over software packages that require coding is that we can come up with a mean reversion system like the one presented by Anthony Garner in a minute of our time.

WealthScript Code (C#)

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using Community.Indicators;

namespace WealthLab.Strategies { public class MeanReversion : WealthScript { private StrategyParameter paramPeriod; public MeanReversion() { paramPeriod = CreateParameter("Period", 10, 5, 30, 5); } protected override void Execute() { int period = paramPeriod.ValueInt; int lmaPeriod = period * 10; SMA sma = SMA.Series( Close, period ); SMA lma = SMA.Series( Close, lmaPeriod ); DataSeries zscore = ZScore.Series( Close, period, StdDevCalculation.Sample ); PlotSeries( PricePane, sma, Color.Red, LineStyle.Solid, 1 ); PlotSeries( PricePane, lma, Color.Blue, LineStyle.Solid, 2 ); ChartPane zPane = CreatePane( 30, true, true ); PlotSeries( zPane, zscore, Color.DarkViolet, LineStyle.Histogram, 3 ); DrawHorzLine( zPane, 1.0, Color.Red, LineStyle.Dashed, 1 ); DrawHorzLine( zPane, -1.0, Color.Blue, LineStyle.Dashed, 1 ); //The trigger is a move up or down by more than one standard deviation from the 10-day average price: //a z-score of over +1 triggers a sell and a z-score of less than -1 triggers a buy. for(int bar = GetTradingLoopStartBar(1); bar < Bars.Count; bar++) { if (IsLastPositionActive) { // exit all positions if zscore flips from positive to negative or vice versa // without going through the neutral zone if( (zscore[bar - 1] > 0.5 && zscore[bar] < -0.5) || (zscore[bar - 1] < -0.5 && zscore[bar] > 0.5) || // Clear positions if the z-score between -.5 and .5 Math.Abs(zscore[bar]) < 0.5 ) SellAtMarket(bar+1, LastPosition); } else { // Buy long if the z-score is < -2 and the longer term trend is positive if( zscore[bar] < -2 && sma[bar] > lma[bar]) BuyAtMarket(bar+1); } } } } }

Gene Geren (Eugene)
Wealth-Lab team