Traders' Tip text
In this month's issue, Mr. Kaufman's article promises an interesting new take on pairs trading. As presented in the article, combining the new Stochastic-derived intermarket “Stress” indicator with few clear position sizing and risk management rules lays the foundation of a long-only market timing system.
Figure 1. A Wealth-Lab 6 chart illustrating the application of the system's rules on a Daily chart of HES (the middle pane). A SPY chart is shown in the upper pane, and the Stress indicator is plotted on the bottom pane.To execute the included trading system, Wealth-Lab users need to install (or update) the latest version of the
TASCIndicators library from the
Extensions section of our website if they haven't already done so, and restart Wealth-Lab.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using TASCIndicators;
namespace WealthLab.Strategies
{
public class PJKPairs1 : WealthScript
{
private StrategyParameter paramPeriod;
private StrategyParameter paramBuy;
private StrategyParameter paramSell;
public PJKPairs1()
{
paramPeriod = CreateParameter("Period", 60, 10, 100, 10);
paramBuy = CreateParameter("Buy", 10, 10, 30, 10);
paramSell = CreateParameter("Sell", 50, 50, 90, 10);
}
protected override void Execute()
{
int period = paramPeriod.ValueInt;
int buy = paramBuy.ValueInt;
int sell = paramSell.ValueInt;
string stock = Bars.Symbol;
string idx = "SPY";
Bars index = GetExternalSymbol( idx, true );
DataSeries indexTrend = SMA.Series( index.Close, period );
DataSeries stress = Stress.Series( Bars, index, period );
ChartPane sPane = CreatePane( 30, false, true );
PlotSeries( sPane, stress, Color.Coral, LineStyle.Solid, 2 );
DrawHorzLine( sPane, 10, Color.Blue, LineStyle.Solid, 1 );
DrawHorzLine( sPane, 90, Color.Red, LineStyle.Solid, 1 );
ChartPane idxPane = CreatePane( 30, true, true );
PlotSymbol( idxPane, index, Color.DarkGreen, Color.DarkMagenta );
HideVolume();
for(int bar = Bars.FirstActualBar + period; bar < Bars.Count; bar++)
{
List<Position> lst = new List<Position>();
lst.AddRange(Positions);
if( SymbolIsActive(stock) )
{
if( stress[bar] >= sell )
{
int lastActivePositionInStock = LastActivePositionInSym(lst,stock);
if( (stress[bar] >= sell) && lastActivePositionInStock > -1 )
SellAtMarket( bar+1, Positions[lastActivePositionInStock], "Xrule" );
}
if( SymbolIsActive(idx))
{
if( indexTrend[bar] < indexTrend[bar-1] )
{
int lastActivePositionInIndex = LastActivePositionInSym(lst,idx);
if( lastActivePositionInIndex > -1 )
{
SetContext( idx, true );
SellAtMarket( bar+1, Positions[lastActivePositionInIndex], "Sell " + idx );
RestoreContext();
}
}
}
else
{
if( indexTrend[bar] < indexTrend[bar-1] )
{
SetContext( idx, true );
BuyAtMarket( bar+1, "Buy " + idx );
RestoreContext();
}
}
}
else
{
if( stress[bar] <= buy )
{
BuyAtMarket( bar+1, "Buy " + stock );
}
}
}
}
private bool SymbolIsActive(string sym)
{
foreach (Position p in ActivePositions)
if( sym == p.Bars.Symbol )
return true;
return false;
}
private int LastActivePositionInSym( List<Position> lst, string symbol )
{
return lst.FindLastIndex( delegate(Position pos) { return pos.Symbol.Equals(symbol, StringComparison.Ordinal); });
}
}
}
Eugene
Wealth-Lab team
www.wealth-lab.com