Traders' Tip text
The accompanying WealthScript C# code demonstrates how to implement a trading Strategy based on the rules by Mr. Katsanos. Here they are:
- “Buy high” when Stiffness crosses above 90 and SPY's EMA is rising, OR
- “Buy pullback” - if the close price is above 100-day SMA, Stiffness is at or above 90, SPY's 100-day EMA is rising, and short-term RSI turns up from below 40.
- Sell when Stiffness crosses below 50, or
- Sell after 84 days in a Position
To change system’s behavior from “buy high” to “buy on pullback”, drag synonymous slider at the bottom of Wealth-Lab’s main workspace. In accordance with the article, entering when the short-term
RSI turns up from a pullback in established trend is believed to be more efficient.
Figure 1 illustrates typical trades on a chart of GoodYear.As the current abnormal bullish market has started 9 years ago, we weren’t convinced by author’s choice of 10 years of latest data. Our backtest with 5% equity per position on a sample of historic Dow 30 stocks as of 1/1/2000 spans the 10-year range up until 1/1/2010. In addition to a vibrant recovery, this includes two bear markets. The buy-on-pullback version finished with the net profit beating Buy&Hold’s (49% vs. ~17%, after commissions). More so, with significantly lower risk (maximum drawdown -13% vs. -59.3%) and market exposure (39.2% vs. 100%).
Figure 2 highlights system’s weakness: it can lose to Buy&Hold in strong bull markets.On a closing note, make sure to load enough historical data to run this backtest. Indicators like
EMA (used as the broad market direction condition) require a fair amount of seed data (here: three times the 100-bar
EMA period) to stabilize their calculation before they can be used reliably in a trading system.
Codeusing System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;
namespace WealthLab.Strategies
{
// Dow 30 Y2K stocks included AA AXP BA C CAT CVX DIS GE GM GT HD HWP IBM INTC IP JNJ JPM KO KODK MCD MRK MSFT PG PM SHLD T UTX WMT XOM
public class TASCNov2018 : WealthScript
{
private StrategyParameter slider1;
private StrategyParameter slider2;
private StrategyParameter slider3;
private StrategyParameter slider4;
private StrategyParameter slider5;
private StrategyParameter slider6;
public TASCNov2018()
{
slider6 = CreateParameter("Pullback?",1,0,1,1);
slider1 = CreateParameter("Stiffness MA",100,2,100,10);
slider2 = CreateParameter("Stiffness Period",60,2,100,10);
slider3 = CreateParameter("Stiffness Devs",0.2,0.1,3,0.2);
slider4 = CreateParameter("Bars since",84,10,200,2);
slider5 = CreateParameter("RSI Period",3,3,6,1);
}
protected override void Execute()
{
int maPeriod = slider1.ValueInt, stiffPeriod = slider2.ValueInt,
exitAfter = slider4.ValueInt, rsiPeriod = slider5.ValueInt;
var devs = slider3.Value;
var stiffness = Stiffness.Series(Close,maPeriod,stiffPeriod,devs);
var rsi = RSI.Series(Close, rsiPeriod);
bool useRsiTurnup = slider6.ValueInt == 1 ? true : false;
var spy = GetExternalSeries("SPY", Close);
var spyEma = EMAModern.Series(spy, maPeriod);
for(int bar = GetTradingLoopStartBar( 100 ); bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if ( bar+1 - p.EntryBar >= exitAfter ) //Bars since entry ? 84 (four months)
SellAtMarket( bar+1, p, "Timed" );
if( CrossUnder( bar, stiffness, 50) ) //Stiffness(100,60) crosses under 50
SellAtMarket( bar+1, p, "Stiffness < 50" );
}
else
{
if( !useRsiTurnup )
{
if( CrossOver(bar, stiffness, 90) ) //Stiffness crosses over 90
if( spyEma[bar] > spyEma[bar - 1] ) //EMA (SPY,100) > EMA (SPY,100)
BuyAtMarket( bar+1);
}
else
{
if( Close[bar] > SMA.Series(Close, maPeriod)[bar] )
if( stiffness[bar] >= 90 ) //Stiffness is bullish
if( spyEma[bar] > spyEma[bar - 1] ) //EMA (SPY,100) > EMA (SPY,100)
if( rsi[bar - 1] < 40 && TurnUp( bar, rsi) ) //RSI is oversold and turns up
BuyAtMarket( bar+1, "RSI TurnUp");
}
}
}
ChartPane paneSpy = CreatePane(30,true,true);
PlotSeries( paneSpy,spy,Color.Black,LineStyle.Solid,2);
PlotSeries( paneSpy,spyEma,Color.Blue,LineStyle.Solid,1);
ChartPane paneStiffness = CreatePane(30,false,true);
PlotSeries( paneStiffness,stiffness,Color.Orange,LineStyle.Histogram,2);
PlotSeries( PricePane, SMA.Series(Close, maPeriod),Color.Blue,LineStyle.Solid,1);
PlotSeries( PricePane, SMA.Series(Close, maPeriod) - (devs * StdDev.Series(Close, maPeriod, StdDevCalculation.Sample)),
Color.Red,LineStyle.Solid,1);
ChartPane paneRsi = CreatePane(30,false,true); HideVolume();
PlotSeries( paneRsi,rsi,Color.Violet,LineStyle.Solid,2);
}
}
}
Eugene (Gene Geren)
Wealth-Lab team
www.wealth-lab.com