Accessing Custom Indicator Data in a Bot

Created at 12 May 2020, 14:56
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!
RG

rgasch

Joined 14.12.2017

Accessing Custom Indicator Data in a Bot
12 May 2020, 14:56


I am working on a custom indicator, the result of which is basically a data series of colors, thank of a color-coded moving average (for simplicity these are represented as an integer between -3 and 3). 

My code looks like this: 

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TestIndicator : Indicator
    {

        [Parameter(DefaultValue = 5, MinValue = 1)]
        public int Periods { get; set; }

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

        private MovingAverage maOpen;
        private MovingAverage maClose;
        public IndicatorDataSeries ColorData;

        protected override void Initialize()
        {
            maOpen = Indicators.MovingAverage(MarketSeries.Open, Periods, MAType);
            maClose = Indicators.MovingAverage(MarketSeries.Close, Periods, MAType);

            /** Init Color Data Structure **/
            ColorData = CreateDataSeries();
        }

        public override void Calculate(int index)
        {
            Colors Color;

            Color = this.GetBarColor(index);
            ChartObjects.DrawLine(<< some stuff here>>);

            /** Assign Color Data for each bar **/
            ColorData[index] = this.ColorToInt(Color);
        }
}

This indicator basically works (it's not done yet, but it so far correctly draws the chart).

Now, when I try to use this indicator in a bot, I have the problem that the ColorData is not set (ie: values return NaN). My bot code looks like this: 

 

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TestBot : Robot
    {

        [Parameter("MA Period", Group = "Heiken Ashi", DefaultValue = 5)]
        public int __Period { get; set; }

        [Parameter("MA Type", Group = "Heiken Ashi")]
        public MovingAverageType __Type { get; set; }

        private _TestIndicator;

        protected override void OnStart()
        {
           this._TestIndicator= Indicators.GetIndicator<MyTestIndicator>(__Period , __Type );
        }

        protected override void OnBar()
        {
            var haCurr = _TestIndicator.ColorData.Last(0);
            var haPrev = _TestIndicator.ColorData.Last(1);

            /** WHY?? **/
            Print(haCurr);  /* Returns NaN */
            Print(haPrev);  /* Returns NaN */
            
        }
    }
}

Does anybody know what I'm doing wrong here?


@rgasch
Replies

PanagiotisCharalampous
12 May 2020, 15:12

Hi rgasch,

To advise further we will need a workable version of the indicator that we can use.

Best Regards,

Panagiotis 

Join us on Telegram

 

 


@PanagiotisCharalampous

rgasch
12 May 2020, 16:47

RE:

Thank you for your reply. Please find attached a complete test case of a minimum reduced indicator and bot (the bot doesn't do anything useful, but it logs the test/evaluation of the color values the indicator fills). 

Indicator: 

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TestIndicator : Indicator
    {

        private MovingAverage _ma;

        [Parameter("MA Period", DefaultValue = 34)]
        public int maPeriod { get; set; }

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

        [OutputAttribute("Moving Average", LineColor = "Red", LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        public IndicatorDataSeries ColorData;



        protected override void Initialize()
        {
            _ma = Indicators.MovingAverage(Bars.ClosePrices, maPeriod, MAType);

            this.ColorData = CreateDataSeries();
        }


        public override void Calculate(int index)
        {
            var color = Color.White;
            var open = Bars.OpenPrices[index];
            var high = Bars.HighPrices[index];
            var low = Bars.LowPrices[index];
            var close = Bars.ClosePrices[index];

            var maValue = _ma.Result[index];
            MaResult[index] = maValue;

            ColorData[index] = open > close ? -1 : 1;
        }
    }
}

 

Bot

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TestBot : Robot
    {

        [Parameter("MA Period", Group = "Main Moving Average", DefaultValue = 25)]
        public int __MAPeriod { get; set; }

        [Parameter("MA Type", Group = "Main Moving Average")]
        public MovingAverageType __MAType { get; set; }

        [Parameter("Source", Group = "Main Moving Average")]
        public DataSeries __SourceSeries { get; set; }

        private TestIndicator _MA;
        private string _label = "TestBot";


        protected override void OnStart()
        {
            this._MA = Indicators.GetIndicator<TestIndicator>(__MAPeriod, __MAType);
            this._label = "TestBot " + this.SymbolName + this.TimeFrame;
        }


        protected override void OnBar()
        {
            var maCurr = _MA.ColorData.Last(0);
            var maPrev = _MA.ColorData.Last(1);

            Print(_MA.ColorData);
            Print(maCurr);
            Print(maPrev);
            if (maCurr != maPrev)
            {
                // Do something useful here
            }
        }


        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

Thank you for any insights. 

 

PanagiotisCharalampous said:

Hi rgasch,

To advise further we will need a workable version of the indicator that we can use.

Best Regards,

Panagiotis 

Join us on Telegram

 

 

 


@rgasch

PanagiotisCharalampous
13 May 2020, 09:34

Hi rgasch,

Thanks. To fix this just mark the ColorData parameter with an OutputAttribute. See below

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class TestIndicator : Indicator
    {

        private MovingAverage _ma;

        [Parameter("MA Period", DefaultValue = 34)]
        public int maPeriod { get; set; }

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

        [OutputAttribute("Moving Average", LineColor = "Red", LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries MaResult { get; set; }

        [OutputAttribute("Color Data")]
        public IndicatorDataSeries ColorData { get; set; }



        protected override void Initialize()
        {
            _ma = Indicators.MovingAverage(Bars.ClosePrices, maPeriod, MAType);
        }


        public override void Calculate(int index)
        {
            var color = Color.White;
            var open = Bars.OpenPrices[index];
            var high = Bars.HighPrices[index];
            var low = Bars.LowPrices[index];
            var close = Bars.ClosePrices[index];

            var maValue = _ma.Result[index];
            MaResult[index] = maValue;

            ColorData[index] = open > close ? -1 : 1;
        }
    }
}

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

rgasch
13 May 2020, 12:48

RE:

Thank you such much for your help; I knew it must have been something 'stupid' ...

 


@rgasch