Traders' Tip text
We programmed the long-only Tr&nd stop strategy for Wealth-Lab 5 in C#. You can use the sliders to adjust the
Period and
atrFactor Strategy Parameters to eyeball an optimization, or using WLP 5.4 you can now run full Exhaustive and Monte Carlo optimizations. A portfolio simulation ($5000 size, $8 1-way commissions) on the Dow 30 symbols over the last 6 years yielded the 2-Parameter optimization curve in Figure 1.
Figure 1. While the optimization didn’t inspire confidence in the strategy’s stability over a wide range of parameters, ATR Factors around 2 helped improve the overall profit, while the Period did not affect the results significantly.
WealthScript Code (C#)
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
namespace WealthLab.Strategies
{
public class SVETrendsStopStrategy : WealthScript
{
StrategyParameter atrFactor;
StrategyParameter period;
public SVETrendsStopStrategy()
{
atrFactor = CreateParameter("ATR Factor", 2.8, 1, 10, 0.2);
period = CreateParameter("Period", 10, 2, 100, 2);
}
public DataSeries TrndsStop(Bars b, int period, double factor )
{
DataSeries loss = factor * TASCIndicators.ATRModified.Series(b, period);
DataSeries resistance = b.Close + loss;
DataSeries support = new DataSeries(b, "Support(" + period + "," + factor + ")");
DataSeries trends = new DataSeries(b, "TrendsStop(" + period + "," + factor + ")");
for (int bar = 0; bar < period; bar++)
support[bar] = b.Low[bar];
for (int bar = period; bar < b.Count; bar++)
{
double b2 = b.Low[bar-2];
double prev = trends[bar-1];
if( (b.Low[bar] >= b2) && (b.Low[bar-1] >= b2) && (b.Low[bar-3] >= b2) && (b.Low[bar-4] >= b2) )
support[bar] = b2;
else if ( b.Low[bar] > b.High[bar-1] * 1.0013 )
support[bar] = b.High[bar-1] * 0.9945;
else if ( b.Low[bar] > support[bar-1] * 1.1 )
support[bar] = support[bar-1] * 1.05;
else
support[bar] = support[bar-1];
if( (b.High[bar] > prev) && (b.High[bar-1] > prev) )
trends[bar] = Math.Max(prev, support[bar]);
else if( (b.High[bar] < prev) && (b.High[bar-1] < prev) )
trends[bar] = Math.Min(prev, resistance[bar]);
else if( (b.High[bar] >= prev) )
trends[bar] = support[bar];
else
trends[bar] = resistance[bar];
}
return trends;
}
protected override void Execute()
{
DataSeries stop = TrndsStop(Bars, period.ValueInt, atrFactor.Value);
PlotSeries(PricePane, stop, Color.Blue, LineStyle.Solid, 2);
for(int bar = 20; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
if( CrossUnder(bar, High, stop) )
SellAtMarket(bar + 1, LastPosition);
}
else if( CrossOver(bar, Close, stop) )
BuyAtMarket(bar + 1);
}
}
}
}