Traders' Tip text
Below you'll find the C# code that implements Premier Stochastic oscillator in Wealth-Lab 6. We've set up a system with entries triggered on Premier Stochastic and a pair of percentage-based profit target and stop loss exits. Following Lee Leibfarth's guidelines on keeping the reward/risk ratio, a profit target by default is twice the size of stop loss — but you can interactively configure all of them by simply dragging the parameter sliders (see at the lower left corner of Figure 1).
Figure 1. The Premier Stochastic oscillator turned out to be a timely counter-trend technique.
A test of this strategy on a portfolio of liquid ETFs revealed its profitability without optimization, and the drawdown was quite moderate.
Figure 2. A combined view of Net profit and Drawdown (%) of the Premier Stochastic strategy available in WL Developer 5.1.
Long trades:
- Premier stochastic crosses below 0.90,
- Premier stochastic crosses below 0.20
Short trades:
- Premier stochastic crosses above -0.90,
- Premier stochastic crosses above -0.20
Strategy Code
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
// Premier Stochastic
public class PremierStochastic : DataSeries
{
public PremierStochastic(Bars bars): base(bars, "Premier Stochastic")
{
this.FirstValidValue = 8*3;
EMACalculation m = EMACalculation.Modern;
StochK K = StochK.Series( bars, 8 );
EMA S = EMA.Series( EMA.Series( ( (K - 50) * 0.1 ), 5, m ), 5, m );
for (int bar = FirstValidValue; bar < bars.Count; bar++)
{
thisbar = ( Math.Exp( Sbar ) - 1 ) / ( Math.Exp( Sbar ) + 1 );
}
}
public static PremierStochastic Series(Bars bars)
{
string description = string.Concat(new object[] { "PremierStochastic" });
if (bars.Cache.ContainsKey(description))
{
return (PremierStochastic)bars.Cachedescription;
}
PremierStochastic _PremierStochastic = new PremierStochastic(bars);
bars.Cachedescription = _PremierStochastic;
return _PremierStochastic;
}
}
public class PremierStochasticStrategy : WealthScript
{
private StrategyParameter paramPTShort;
private StrategyParameter paramPTLong;
private StrategyParameter paramSLShort;
private StrategyParameter paramSLLong;
public PremierStochasticStrategy()
{
paramPTLong = CreateParameter("Profit Target (L)", 1.08, 1.01, 1.30, 0.01);
paramSLLong = CreateParameter("Stop Loss (L)", 0.96, 0.85, 0.99, 0.01);
paramPTShort = CreateParameter("Profit Target (S)", 0.92, 0.70, 0.99, 0.01);
paramSLShort = CreateParameter("Stop Loss (S)", 1.04, 1.01, 1.15, 0.01);
}
protected override void Execute()
{
PremierStochastic PS = PremierStochastic.Series( Bars );
bool xo1, xo2, xu1, xu2;
double stop, profit;
for(int bar = PS.FirstValidValue; bar < Bars.Count; bar++)
{
xo1 = CrossOver(bar, PS, -0.9);
xo2 = CrossOver(bar, PS, -0.2);
xu1 = CrossUnder(bar, PS, 0.9);
xu2 = CrossUnder(bar, PS, 0.2);
if (IsLastPositionActive)
{
Position p = LastPosition;
if ( p.PositionType == PositionType.Long )
{
stop = p.EntryPrice * paramSLLong.Value;
profit = p.EntryPrice * paramPTLong.Value;
} else
{
stop = p.EntryPrice * paramSLShort.Value;
profit = p.EntryPrice * paramPTShort.Value;
}
if( !ExitAtStop( bar+1, p, stop, "Stop Loss" ) )
ExitAtLimit( bar+1, p, profit, "Profit Target" );
}
else
{
if( xo1 || xo2 )
{
if( ShortAtMarket( bar+1 ) != null )
LastPosition.Priority = -PSbar;
} else
if( xu1 || xu2 )
{
if( BuyAtMarket( bar+1 ) != null )
LastPosition.Priority = PSbar;
}
}
}
HideVolume();
ChartPane psPane = CreatePane( 40, false, true );
DrawHorzLine( psPane, 0.90, Color.LightBlue, LineStyle.Solid, 2 );
DrawHorzLine( psPane, 0.20, Color.LightBlue, LineStyle.Solid, 2 );
DrawHorzLine( psPane, -0.20, Color.LightCoral, LineStyle.Solid, 2 );
DrawHorzLine( psPane, -0.90, Color.LightCoral, LineStyle.Solid, 2 );
PlotSeriesOscillator( psPane, PS, 0, 0, Color.FromArgb(60, Color.Blue),
Color.FromArgb(60, Color.Red ), Color.Transparent, LineStyle.Solid, 1 );
PlotSeries( psPane, PS, Color.Black, LineStyle.Solid, 1 );
}
}
}