Traders' Tip text
This WealthScript Strategy implements the simplified version of Perry J. Kaufman's triple-divergence trading system from June 2014 issue. Users have the control to turn the system into long-only, as well as to configure its sensitivity by triggering a trading signal after one, two or three divergences on the same bar.
Figure 1 illustrates the application of the system's rules on the Daily chart of QQQ. The lower pane shows the 5-, 8-, and 13-day linear regression slope of the recent close price.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
enum Side { Buy = 1, Sell = -1, NA = 0 }
public class TASC201406_Kaufman : WealthScript
{
Side SingleDivergence( int bar, int period, int momperiod,
DataSeries ps, DataSeries ms, out bool trendup, out bool trenddn, out int p, out int m )
{
trendup = (psbar > 0 && msbar > 0);
trenddn = (psbar < 0 && msbar < 0);
p = psbar >= 0 ? 1 : psbar < 0 ? -1 : 0;
m = msbar >= 0 ? 1 : msbar < 0 ? -1 : 0;
return ( psbar > 0 && msbar < 0 ) ? Side.Buy :
( psbar < 0 && msbar > 0 ) ? Side.Sell : Side.NA;
}
void Colorize( int bar, Side side )
{
SetBackgroundColor( bar, Color.FromArgb(30, side == Side.Buy ? Color.Green : Color.Red ) );
}
private StrategyParameter paramNumDiv;
private StrategyParameter paramLongOnly;
public TASC201406_Kaufman()
{
paramNumDiv = CreateParameter("Divergences", 1, 1, 3, 1);
paramLongOnly = CreateParameter("Long Only", 0, 0, 1, 1);
}
protected override void Execute()
{
int momperiod = 10, entrynumber = paramNumDiv.ValueInt,
dvgperiod1 = 5, dvgperiod2 = 8, dvgperiod3 = 13, maxdivergences = 3;
bool longonly = (paramLongOnly.ValueInt == 0 ? false : true);
LinearRegSlope lsp1 = LinearRegSlope.Series( Close,dvgperiod1 );
LinearRegSlope lsp2 = LinearRegSlope.Series( Close,dvgperiod2 );
LinearRegSlope lsp3 = LinearRegSlope.Series( Close,dvgperiod3 );
StochK fastK = StochK.Series(Bars,momperiod);
LinearRegSlope lsm1 = LinearRegSlope.Series( fastK,dvgperiod1 );
LinearRegSlope lsm2 = LinearRegSlope.Series( fastK,dvgperiod2 );
LinearRegSlope lsm3 = LinearRegSlope.Series( fastK,dvgperiod3 );
ClearDebug(); HideVolume(); LineStyle ls = LineStyle.Solid;
ChartPane lrspPane = CreatePane( 40,false,true );
PlotSeries( lrspPane, lsp1, Color.DarkGreen, ls, 1 );
PlotSeries( lrspPane, lsp2, Color.Blue, ls, 1 );
PlotSeries( lrspPane, lsp3, Color.Red, ls, 1 );
//ChartPane lrsmPane = CreatePane( 30,false,true );
//PlotSeries( lrsmPane, fastK, Color.Black, ls, 1 );
for(int bar = GetTradingLoopStartBar(Math.Max(momperiod,dvgperiod3)); bar < Bars.Count; bar++)
{
int nbuys = 0, nsells = 0, ps1 = 0, ps2 = 0, ps3 = 0, ms1 = 0, ms2 = 0, ms3 = 0,
npriceslopeup = 0, npriceslopedown = 0, nmomslopeup = 0, nmomslopedown = 0;
bool trend1up = false, trend2up = false, trend3up = false,
trend1dn = false, trend2dn = false, trend3dn = false;
Side _d1 = SingleDivergence( bar, dvgperiod1, momperiod, lsp1, lsm1, out trend1up, out trend1dn, out ps1, out ms1 );
Side _d2 = SingleDivergence( bar, dvgperiod2, momperiod, lsp2, lsm2, out trend2up, out trend2dn, out ps2, out ms2 );
Side _d3 = SingleDivergence( bar, dvgperiod3, momperiod, lsp3, lsm3, out trend3up, out trend3dn, out ps3, out ms3 );
int d1 = (int)_d1;
int d2 = (int)_d2;
int d3 = (int)_d3;
if( d1 > 0 ) nbuys += 1; if( d1 < 0 ) nsells += 1;
if( d2 > 0 ) nbuys += 1; if( d2 < 0 ) nsells += 1;
if( d3 > 0 ) nbuys += 1; if( d3 < 0 ) nsells += 1;
if( ps1 > 0 ) npriceslopeup += 1; if( ps1 < 0 ) npriceslopedown += 1;
if( ps2 > 0 ) npriceslopeup += 1; if( ps2 < 0 ) npriceslopedown += 1;
if( ps3 > 0 ) npriceslopeup += 1; if( ps3 < 0 ) npriceslopedown += 1;
if( ms1 > 0 ) nmomslopeup += 1; if( ms1 < 0 ) nmomslopedown += 1;
if( ms2 > 0 ) nmomslopeup += 1; if( ms2 < 0 ) nmomslopedown += 1;
if( ms3 > 0 ) nmomslopeup += 1; if( ms3 < 0 ) nmomslopedown += 1;
if( nbuys >= entrynumber )
Colorize( bar, Side.Buy );
else
if( nsells >= entrynumber )
Colorize( bar, Side.Sell );
if( false )
PrintDebug( "bar: " + bar + ", d1: " + d1 + ", d2: " + d2 + ", d3: " + d3 + ", nbuys: " + nbuys + ", nsells: " + nsells +
", npriceslopeup: " + npriceslopeup + ", npriceslopedown: " + npriceslopedown +
", nmomslopeup: " + nmomslopeup + ", nmomslopedown: " + nmomslopedown );
if (IsLastPositionActive)
{
Position p = LastPosition;
if( p.PositionType == PositionType.Long )
{
if( nsells >= entrynumber)
SellAtClose( bar, p, "revLong");
}
else //if( p.PositionType == PositionType.Short )
{
if( nbuys >= entrynumber)
CoverAtClose( bar, p, "revShort");
}
if( (npriceslopeup == maxdivergences && nmomslopeup == maxdivergences) ||
(npriceslopedown == maxdivergences && nmomslopedown == maxdivergences) )
{
ExitAtMarket( bar+1, p, p.PositionType == PositionType.Long ? "xLall" : "xSall" );
}
}
else
{
if( nbuys >= entrynumber)
BuyAtMarket(bar+1, "newBuy");
else
if( nsells >= entrynumber && longonly == false)
ShortAtMarket(bar+1, "newSell");
}
}
}
}
}
Eugene
Wealth-Lab team
www.wealth-lab.com