GRaB Candles on 1H/4H timeframes with a 50D Moving Average

Created at 08 Jun 2021, 10:10
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
HI

hirgentcekaj

Joined 19.02.2019

GRaB Candles on 1H/4H timeframes with a 50D Moving Average
08 Jun 2021, 10:10


Hello, 

I am currently trying to build an indicator but I am at a complete loss right now. I'm trying to plot a daily moving average on the 4H and 1H timeframe with GRaB candles that would take the daily moving average into its calculation. However, I have no clue how I'm supposed to continue about this. I'm a complete novice when it comes to coding indicators.

The screenshot below is how it should look. I'm using a 300 period average on the 4H which is very unpractical and inaccurate. On the 1H, I would have to use a 1200 period average which I would need to combine it with Bars.LoadMoreHistory so the indicator has enough data to calculate. If I wanted to switch timeframes I would need to adjust the period value which is an extreme hassle.

I have tried to put something together but I get no results. I know for a fact my indexing is completely wrong. Any help would very much be appreciated.

using System;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MTFGRaBCandles : Indicator
    {
        [Parameter("MA Period", DefaultValue = 300)]
        public int maPeriod { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MAType { get; set; }

        [Parameter("Candle width", DefaultValue = 5)]
        public int CandleWidth { get; set; }

        [Parameter("Wick width", DefaultValue = 1)]
        public int WickWidth { get; set; }

        [Parameter("Above up color", DefaultValue = "LimeGreen")]
        public string AboveUpColor { get; set; }

        [Parameter("Above down color", DefaultValue = "DarkGreen")]
        public string AboveDownColor { get; set; }

        [Parameter("Middle up color", DefaultValue = "LightBlue")]
        public string MiddleUpColor { get; set; }

        [Parameter("Middle down color", DefaultValue = "DodgerBlue")]
        public string MiddleDownColor { get; set; }

        [Parameter("Below up color", DefaultValue = "Tomato")]
        public string BelowUpColor { get; set; }

        [Parameter("Below down color", DefaultValue = "Crimson")]
        public string BelowDownColor { get; set; }

        [Output("High Moving Average", Color = Colors.Red, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries HMaResult { get; set; }

        [Output("Low Moving Average", Color = Colors.LimeGreen, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries LMaResult { get; set; }

        [Output("Middle Moving Average", Color = Colors.Blue, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        private MovingAverage _Hma;
        private MovingAverage _Lma;
        private MovingAverage _ma;

        private MarketSeries D1;

        private Colors _AboveUpColor;
        private Colors _AboveDownColor;
        private Colors _MiddleUpColor;
        private Colors _MiddleDownColor;
        private Colors _BelowUpColor;
        private Colors _BelowDownColor;
        private Colors color;

        private bool _incorrectColors;
        private Random _random = new Random();


        protected override void Initialize()
        {
            D1 = MarketData.GetSeries(TimeFrame.Daily);

            _Hma = Indicators.MovingAverage(D1.HighPrices, maPeriod, MAType);
            _Lma = Indicators.MovingAverage(D1.LowPrices, maPeriod, MAType);
            _ma = Indicators.MovingAverage(D1.ClosePrices, maPeriod, MAType);

            if (!Enum.TryParse<Colors>(AboveUpColor, out _AboveUpColor) || !Enum.TryParse<Colors>(AboveDownColor, out _AboveDownColor) || !Enum.TryParse<Colors>(BelowUpColor, out _BelowUpColor) || !Enum.TryParse<Colors>(BelowDownColor, out _BelowDownColor) || !Enum.TryParse<Colors>(MiddleUpColor, out _MiddleUpColor) || !Enum.TryParse<Colors>(MiddleDownColor, out _MiddleDownColor))
                _incorrectColors = true;
        }

        public override void Calculate(int index)
        {
            if (_incorrectColors)
            {
                var errorColor = _random.Next(2) == 0 ? Colors.Red : Colors.White;
                ChartObjects.DrawText("Error", "Incorrect colors", StaticPosition.Center, errorColor);
                return;
            }
            var open = D1.OpenPrices[index];
            var high = D1.HighPrices[index];
            var low = D1.LowPrices[index];
            var close = D1.ClosePrices[index];

            var HMA = _Hma.Result[index];
            var LMA = _Lma.Result[index];
            var MA = _ma.Result[index];

            HMaResult[index] = HMA;
            LMaResult[index] = LMA;
            MaResult[index] = MA;

            if (close > HMA)
                color = open > close ? _AboveDownColor : _AboveUpColor;

            if (close < LMA)
                color = open > close ? _BelowDownColor : _BelowUpColor;

            if (close >= LMA && close <= HMA)
                color = open > close ? _MiddleDownColor : _MiddleUpColor;

            ChartObjects.DrawLine("candle" + index, index, open, index, close, color, CandleWidth, LineStyle.Solid);
            ChartObjects.DrawLine("line" + index, index, high, index, low, color, WickWidth, LineStyle.Solid);
        }
    }
}

 


@hirgentcekaj
Replies

amusleh
08 Jun 2021, 11:46

Hi,

There are several issues on your code, I recommend you to take a look on Automate API references and multi time frame indicator samples.

I fixed some of the issues for you:

using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MTFGRaBCandles : Indicator
    {
        [Parameter("MA Period", DefaultValue = 300)]
        public int maPeriod { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Simple)]
        public MovingAverageType MAType { get; set; }

        [Parameter("Candle width", DefaultValue = 5)]
        public int CandleWidth { get; set; }

        [Parameter("Wick width", DefaultValue = 1)]
        public int WickWidth { get; set; }

        [Parameter("Above up color", DefaultValue = "LimeGreen")]
        public string AboveUpColor { get; set; }

        [Parameter("Above down color", DefaultValue = "DarkGreen")]
        public string AboveDownColor { get; set; }

        [Parameter("Middle up color", DefaultValue = "LightBlue")]
        public string MiddleUpColor { get; set; }

        [Parameter("Middle down color", DefaultValue = "DodgerBlue")]
        public string MiddleDownColor { get; set; }

        [Parameter("Below up color", DefaultValue = "Tomato")]
        public string BelowUpColor { get; set; }

        [Parameter("Below down color", DefaultValue = "Crimson")]
        public string BelowDownColor { get; set; }

        [Output("High Moving Average", Color = Colors.Red, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries HMaResult { get; set; }

        [Output("Low Moving Average", Color = Colors.LimeGreen, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries LMaResult { get; set; }

        [Output("Middle Moving Average", Color = Colors.Blue, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        private MovingAverage _Hma;
        private MovingAverage _Lma;
        private MovingAverage _ma;

        private Bars D1;

        private Color _AboveUpColor;
        private Color _AboveDownColor;
        private Color _MiddleUpColor;
        private Color _MiddleDownColor;
        private Color _BelowUpColor;
        private Color _BelowDownColor;

        protected override void Initialize()
        {
            D1 = MarketData.GetBars(TimeFrame.Daily);

            _Hma = Indicators.MovingAverage(D1.HighPrices, maPeriod, MAType);
            _Lma = Indicators.MovingAverage(D1.LowPrices, maPeriod, MAType);
            _ma = Indicators.MovingAverage(D1.ClosePrices, maPeriod, MAType);

            _AboveUpColor = GetColor(AboveUpColor);
            _AboveDownColor = GetColor(AboveDownColor);

            _MiddleUpColor = GetColor(MiddleUpColor);
            _MiddleDownColor = GetColor(MiddleDownColor);

            _BelowUpColor = GetColor(BelowUpColor);
            _BelowDownColor = GetColor(BelowDownColor);
        }

        public override void Calculate(int index)
        {
            var dailyIndex = D1.OpenTimes.GetIndexByTime(Bars[index].OpenTime);

            var open = D1.OpenPrices[dailyIndex];
            var high = D1.HighPrices[dailyIndex];
            var low = D1.LowPrices[dailyIndex];
            var close = D1.ClosePrices[dailyIndex];

            var HMA = _Hma.Result[index];
            var LMA = _Lma.Result[index];
            var MA = _ma.Result[index];

            HMaResult[index] = HMA;
            LMaResult[index] = LMA;
            MaResult[index] = MA;

            Color color = Color.Black;

            if (close > HMA)
                color = open > close ? _AboveDownColor : _AboveUpColor;

            if (close < LMA)
                color = open > close ? _BelowDownColor : _BelowUpColor;

            if (close >= LMA && close <= HMA)
                color = open > close ? _MiddleDownColor : _MiddleUpColor;

            Chart.DrawTrendLine("candle" + index, index, open, index, close, color, CandleWidth, LineStyle.Solid);
            Chart.DrawTrendLine("line" + index, index, high, index, low, color, WickWidth, LineStyle.Solid);
        }

        private Color GetColor(string colorString, int alpha = 255)
        {
            var color = colorString[0] == '#' ? Color.FromHex(colorString) : Color.FromName(colorString);

            return Color.FromArgb(alpha, color);
        }
    }
}

You can't start developing indicators/cBots without a solid knowledge of C# basics and Automate API.

If you can't develop your indicator you can post a job request or contact one of our consultants.


@amusleh