Traders' Tip text
At first it may seem that the idea presented in the current month's article is trivial. After all, what else we don't know about the many variations of a moving average crossover? However, author Sylvain Vervoort takes the technique a step further, applying moving average crossovers on his modified Renko chart with an added twist of Heikin Ashi. The premise behind this is to reduce the noise of a typical used fixed-time-related chart and to produce less losing trades.
First, we build two moving averages: the fast is the SMA of the Renko-based typical price and the slow is a SMA of Heikin-Ashi recalculated prices. For simplicity of our example Strategy, we take a standard Renko chart and use Daily prices. Despite using the same period, the HA-based average always lags behind due to added smoothing. The rules are:
- When the 8-period “fast” average crosses above the “slower” counterpart of the same period, a long position is established.
- When the 8-period “fast” average crosses below the “slower” average of the same period, the long position is closed.
Figure 1. A Wealth-Lab 6 chart illustrating the application of the system's rules on a Daily chart of AXP (American Express).The green and red bricks on Figure 1 show Renko bricks supermiposed on the usual OHLC chart.
To execute the enclosed trading system, Wealth-Lab users may copy/paste the enclosed strategy’s C# code or simply let Wealth-Lab do the job: in the “Open Strategy” dialog, click “Download” to get the strategy code.
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using WealthLab.ChartStyles.Trending;
namespace WealthLab.Strategies
{
public class VervoortOct2014 : WealthScript
{
StrategyParameter paramRPU;
StrategyParameter paramPeriod;
public VervoortOct2014()
{
paramRPU = CreateParameter("Renko Units", 1, 1, 10, 1);
paramPeriod = CreateParameter("MA Period", 8, 2, 20, 1);
}
protected override void Execute()
{
double rpu = paramRPU.Value;
int period = paramPeriod.ValueInt;
TRenko renko = new TRenko(Bars, rpu);
DataSeries dsOpen = new DataSeries(Bars,"R-Open"), dsHigh = new DataSeries(Bars,"R-High"),
dsLow = new DataSeries(Bars,"R-Low"), dsClose = new DataSeries(Bars,"R-Close");
DataSeries haOpen = new DataSeries(Bars,"HA-Open"), haHigh = new DataSeries(Bars,"HA-High"),
haLow = new DataSeries(Bars,"HA-Low"), haClose = new DataSeries(Bars,"HA-Close");
for(int bar = 1; bar < Bars.Count; bar++)
{
Renko rko = renko.Columns[bar];
// Create Renko-based OHLC and Heikin Ashi for averaging
if( rko.Col > -1 )
{
if( rko.Col > renko.Columns[bar-1].Col )
{
Renko prev = renko.Columns[bar-1];
double open = rko.DirectionUp ? rko.Low : rko.High;
double close = !rko.DirectionUp ? rko.Low : rko.High;
double high = rko.High;
double low = rko.Low;
double prevOpen = prev.DirectionUp ? prev.Low : prev.High;
double prevClose = !prev.DirectionUp ? prev.Low : prev.High;
double prevHigh = prev.High;
double prevLow = prev.Low;
double _haClose = (open + high + low + close) / 4;
double _haOpen = (prevOpen + prevClose) / 2;
double _haHigh = Math.Max( Math.Max(high, open), close );
double _haLow = Math.Min( Math.Min(low, open), close );
dsOpen[bar] = open;
dsHigh[bar] = high;
dsLow[bar] = low;
dsClose[bar] = close;
haOpen[bar] = _haOpen;
haHigh[bar] = _haHigh;
haLow[bar] = _haLow;
haClose[bar] = _haClose;
}
else
{
dsOpen[bar] = dsOpen[bar-1];
dsHigh[bar] = dsHigh[bar-1];
dsLow[bar] = dsLow[bar-1];
dsClose[bar] = dsClose[bar-1];
haOpen[bar] = haOpen[bar-1];
haHigh[bar] = haHigh[bar-1];
haLow[bar] = haLow[bar-1];
haClose[bar] = haClose[bar-1];
}
}
}
//The first and faster average is the SMA of the typical price (HLC/3)
//The second average is a SMA of heikin ashi re-calculated prices or haOpen + haHigh + haLow + haClose divided by four
DataSeries maTypical = (SMA.Series( dsHigh, period ) + SMA.Series( dsLow, period ) + SMA.Series( dsClose, period )) / 3;
DataSeries maHeikin = (SMA.Series( haOpen, period ) + SMA.Series( haHigh, period ) + SMA.Series( haLow, period ) + SMA.Series( haClose, period )) / 4;
maTypical.Description = "SMA of Renko-based typical price";
maHeikin.Description = "SMA of Renko-based Heikin Ashi";
PlotSeries( PricePane, maTypical, Color.Blue, LineStyle.Solid, 1 );
PlotSeries( PricePane, maHeikin, Color.Red, LineStyle.Solid, 1 );
for(int bar = 1; bar < Bars.Count; bar++)
{
// Detect crossover/crossunder and store state in a variable
bool maXo = CrossOver(bar, maTypical, maHeikin);
bool maXu = CrossUnder(bar, maTypical, maHeikin);
Position p = LastPosition;
if ( IsLastPositionActive )
{
if ( maXu )
SellAtMarket( bar + 1, p );
}
else
{
if ( maXo )
BuyAtMarket( bar + 1 );
}
}
}
}
}
Eugene
Wealth-Lab team
www.wealth-lab.com