Traders' Tip text
Our WealthScript solution automatically identifies the pattern on the chart with a routine called HighlightPattern that you might find useful in other pattern-recognition scripts. As can be seen in Figure 1, the three-bar pattern occurs more frequently that you otherwise might expect in the CL, SI, and GC (shown) electronic sessions.
Figure 1. The light gray and blue boxes highlight the short and long setups, respectively.
While testing the code, we noticed that short trade triggers (the last bar in the pattern) whose Close was below the Low of the previous bar had a better success rate than if the Close were simply lower than the previous Close. Just toggle the “Modified Short” parameter to test both versions of the Strategy. Although the modification made practically no difference for SI, it increased overall net profit for both GC and CL significantly over the test period.
The continuous futures data for Gold, silver, and Crude Oil used by the author are attached.
using System;
using System.Collections.Generic;
using System.Drawing;
using WealthLab;
namespace WealthLab.Strategies
{
public class ThreeBarPatternFutures : WealthScript
{
StrategyParameter _target;
StrategyParameter _stoploss;
StrategyParameter _modifiedShortTrigger;
public ThreeBarPatternFutures()
{
_target = CreateParameter("% Target", 0.75, 0.5, 2.5, 0.05);
_stoploss = CreateParameter("% Stop Loss", 0.75, 0.5, 2.5, 0.05);
_modifiedShortTrigger = CreateParameter("Modified Short", 1, 0, 1, 1);
}
private void HighlightPattern(int bar, Color color, int patternBars)
{
double hi = Highbar;
double lo = Lowbar;
if (patternBars > 1)
{
int p = patternBars - 1;
for (int n = bar - 1; n >= bar - p; n--)
{
hi = Highn > hi ? Highn : hi;
lo = Lown < lo ? Lown : lo;
}
}
int b1 = bar - patternBars;
int b2 = Math.Min(bar + 1, Bars.Count - 1);
DrawPolygon(PricePane, color, color, LineStyle.Invisible, 1, true, b1, hi, b2, hi, b2, lo, b1, lo);
}
protected override void Execute()
{
Position p = null;
double target = 1e6;
double stop = 0d;
PlotStops();
HideVolume();
for(int bar = 3; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
p = LastPosition;
if (!ExitAtStop(bar + 1, p, stop, "Stop Loss"))
ExitAtLimit(bar + 1, p, target, "Profit Target");
}
else
{
bool setup1L = Closebar - 3 < Closebar - 2;
bool setup1S = Closebar - 3 > Closebar - 2;
bool setup2 = Highbar - 2 > Highbar - 1 && Lowbar - 2 < Lowbar - 1;
bool setup3L = Closebar - 1 < Closebar;
bool setup3S = Closebar - 1 > Closebar;
if (_modifiedShortTrigger.ValueInt == 1)
setup3S = Lowbar - 1 > Closebar;
if (setup1L && setup2 && setup3L)
{
HighlightPattern(bar, Color.FromArgb(30, Color.Blue), 3);
if (BuyAtMarket(bar + 1) != null)
{
p = LastPosition;
target = p.EntryPrice * (1 + _target.Value/100d);
stop = p.EntryPrice * (1 - _stoploss.Value/100d);
}
}
else if (setup1S && setup2 && setup3S)
{
HighlightPattern(bar, Color.FromArgb(20, Color.Black), 3);
if (ShortAtMarket(bar + 1) != null)
{
p = LastPosition;
target = p.EntryPrice * (1 - _target.Value/100d);
stop = p.EntryPrice * (1 + _stoploss.Value/100d);
}
}
}
}
}
}
}