Description
This overlay indicator sets up the 34 EMA Wave and paints the GRaB candles used extensively by Raghee Horner and followers of her trading style.
Additionally this indicator draws vertical lines to show the minimum and maximum Lookback advocated by Raghee when identifying the trend in a specific time frame.
For more information on what these are and how Raghee advocates using them take a look at https://youtu.be/L06MjjgwYnw
Limitations:
The cTrader/cAlgo API does not allow developers to detect when the Zoom level has changed or what it is. This means I have to use a specific width setting when painting candle bodies. The default used is 5 but I have provided a parameter that allows you to change to anywhere between 1 and 15. If you zoom in and out all the time this can be a bit tedious but not a lot I can do about it until the API changes to allow developers to determine things like Zoom level and/or view port dimensions.
Also the API dos not support colour or line setting parameters. There is a hack/work around using Outputs but we have actual outputs in this indicator so I haven't used it. When the API supports colour and line style as individual parameters I will update the indicator to allow customising colours used to paint candles and the look back lines.
Constructive criticism and feedback are always welcome
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Indicator("Raghee Wave and GRaB Candles", IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class RagheeWaveandGRaBCandles : Indicator
{
private ExponentialMovingAverage closeMa;
private ExponentialMovingAverage hiMa;
private ExponentialMovingAverage loMa;
private const Colors LookbackMinColor = Colors.Yellow;
private const Colors LookbackMaxColor = Colors.YellowGreen;
private const LineStyle LookbackLineStyle = LineStyle.DotsVeryRare;
private readonly Dictionary<TimeFrame, LookbackConfig> lookback = new Dictionary<TimeFrame, LookbackConfig>();
[Parameter("Candle Width", DefaultValue = 5, MinValue = 1, MaxValue = 15, Step = 1)]
public double CandleWidth { get; set; }
[Output("Wave Mid", LineStyle = LineStyle.Solid, Thickness = 1, Color = Colors.Blue)]
public IndicatorDataSeries Close { get; set; }
[Output("Wave Hi", LineStyle = LineStyle.Solid, Thickness = 1, Color = Colors.Green)]
public IndicatorDataSeries Hi { get; set; }
[Output("Wave Lo", LineStyle = LineStyle.Solid, Thickness = 1, Color = Colors.Red)]
public IndicatorDataSeries Lo { get; set; }
public override void Calculate(int index)
{
this.Hi[index] = this.hiMa.Result[index];
this.Close[index] = this.closeMa.Result[index];
this.Lo[index] = this.loMa.Result[index];
var color = this.GetCandleColor(index);
this.PaintCandle(index, color);
if (this.IsLastBar)
{
this.PaintLookbackRange(index);
}
}
private void PaintLookbackRange(int index)
{
if (!this.lookback.ContainsKey(this.TimeFrame))
{
this.Print("Time Frame not supported");
return;
}
var lookbackConfig = this.lookback[this.TimeFrame];
var minLookbackDateTime = this.MarketSeries.OpenTime[index - lookbackConfig.MinPeriods];
var maxLookbackDateTime = this.MarketSeries.OpenTime[index - lookbackConfig.MaxPeriods];
this.ChartObjects.DrawVerticalLine("minlookback", minLookbackDateTime, LookbackMinColor, 1, LookbackLineStyle);
this.ChartObjects.DrawVerticalLine("maxlookback", maxLookbackDateTime, LookbackMaxColor, 1, LookbackLineStyle);
}
protected override void Initialize()
{
this.hiMa = this.Indicators.ExponentialMovingAverage(this.MarketSeries.High, 34);
this.closeMa = this.Indicators.ExponentialMovingAverage(this.MarketSeries.Close, 34);
this.loMa = this.Indicators.ExponentialMovingAverage(this.MarketSeries.Low, 34);
this.lookback.Add(TimeFrame.Minute5, new LookbackConfig
{
MinPeriods = 576,
MaxPeriods = 1440
});
this.lookback.Add(TimeFrame.Minute15, new LookbackConfig
{
MinPeriods = 336,
MaxPeriods = 672
});
this.lookback.Add(TimeFrame.Minute30, new LookbackConfig
{
MinPeriods = 672,
MaxPeriods = 1344
});
this.lookback.Add(TimeFrame.Hour, new LookbackConfig
{
MinPeriods = 360,
MaxPeriods = 1080
});
this.lookback.Add(TimeFrame.Hour4, new LookbackConfig
{
MinPeriods = 270,
MaxPeriods = 540
});
this.lookback.Add(TimeFrame.Daily, new LookbackConfig
{
MinPeriods = 365,
MaxPeriods = 366
});
this.lookback.Add(TimeFrame.Weekly, new LookbackConfig
{
MinPeriods = 260,
MaxPeriods = 261
});
}
private Colors GetCandleColor(int index)
{
var open = this.MarketSeries.Open[index];
var close = this.MarketSeries.Close[index];
var hiMaValue = this.hiMa.Result[index];
var closeMaValue = this.closeMa.Result[index];
var loMaValue = this.loMa.Result[index];
var isBearish = this.IsBearish(index);
if (open > hiMaValue && close > hiMaValue)
{
return isBearish ? Colors.Green : Colors.DarkGreen;
}
if (open < loMaValue && close < loMaValue)
{
return isBearish ? Colors.Red : Colors.DarkRed;
}
return isBearish ? Colors.Blue : Colors.DarkBlue;
}
private bool IsBearish(int index)
{
return this.MarketSeries.Close[index] >= this.MarketSeries.Open[index];
}
private void PaintCandle(int index, Colors color)
{
var open = this.MarketSeries.Open[index];
var close = this.MarketSeries.Close[index];
var hi = this.MarketSeries.High[index];
var lo = this.MarketSeries.Low[index];
var candleY1 = open >= close ? open : close;
var candleY2 = open >= close ? close : open;
this.ChartObjects.DrawLine(string.Format("wick{0}", index), index, hi, index, lo, color, 1, LineStyle.Solid);
this.ChartObjects.DrawLine(string.Format("candle{0}", index), index, candleY1, index, candleY2, color, this.CandleWidth, LineStyle.Solid);
}
private class LookbackConfig
{
internal int MaxPeriods { get; set; }
internal int MinPeriods { get; set; }
}
}
}
cTKit
Joined on 15.09.2016
- Distribution: Paid
- Language: C#
- Trading platform: cTrader Automate
- File name: Raghee Wave and GRaB Candles.algo
- Rating: 0
- Installs: 2850
- Modified: 13/10/2021 09:54
TIP: As mentioned several times in the support forums, chart objects rendered using the cTrader API do not seem to match up with the candles. In this indicator you will probably notice the candles painted by the indicator do not always cover existing candles. The indicator uses the hi/lo, open and close values provided by the API to render lines that over paint the candles, but they don't render the same as the candles rendered by cTrader. I have no idea which is accurate and which is not, either way if you want to eliminate the traces of the original candles do the following:
I am trying to find a solution, but the API is quite limited so may have to wait until it matures a little more.