Custom indicator fields null in cbot

Created at 13 Jun 2019, 06:06
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!
CA

calgodemo

Joined 28.05.2019

Custom indicator fields null in cbot
13 Jun 2019, 06:06


Hey all,

I've written out a custom indicator that displays a trendline on the chart. When I add the indicator to the chart, I see the trendlines - so far so good.

Now I've written a cbot which says, if price breaks this trendline, enter a position.(or in this case display an arrow which i'll replace later)

double _trendlinevalue = MDE.LastupChannel.CalculateY(MarketSeries.Close.Count);
                if (MarketSeries.Close.LastValue < _trendlinevalue)
                {
                    Chart.DrawIcon("sell a/1 wave" + MarketSeries.Close.Count.ToString(), ChartIconType.DownArrow, MarketSeries.Close.Count, MarketSeries.High.LastValue + 0.003, "green");
                  
                }

 I've referenced my MDE indicator properly and everything is compiling 

MDE = Indicators.GetIndicator<MDEv2>(Source);

However, even though I can see the "Last up line" drawn on my chart, in debugging, this value is null.

What have I done wrong? There are zero values for certain integers like the indicies I use to draw the trendline, if I am drawing it succesfully on the indicator - why when I reference the same indicator are these values 0 - the same as when they were initiallized?

In the indicator, the following code executes perfectly

Chart.DrawTrendLine("Uptrend" + Dlb.ToString(), Dlb_last, CalcMarketHigh(Dlb_last), Dlb, CalcMarketHigh(Dlb), "lightblue", 3);

Where Dlb and Dlb_last are indicies. In my cbot on debugging, both these indiciesa are zero.

Thanks for your time!!!

cAD


@calgodemo
Replies

PanagiotisCharalampous
13 Jun 2019, 09:55

Hi calgodemo,

Can you share the cBot and Indicator code? 

Best Regards,

Panagiotis


@PanagiotisCharalampous

calgodemo
13 Jun 2019, 19:38

RE:

Panagiotis Charalampous said:

Hi calgodemo,

Can you share the cBot and Indicator code? 

Best Regards,

Panagiotis

Thanks for replying Panagiotis, 

here is the cbot, all I'm doing at this point is drawing text on the chart.

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 MDE : Robot
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }
        [Parameter(DefaultValue = 60, MinValue = 5)]
        public int Timeframe { get; set; }

        // Declare indicator.
        public MDEv2I MDE;

        // here are some variables I am creating along the way.


        protected override void OnStart()
        {
            // instantiate custom indicator
            MDE = Indicators.GetIndicator<MDEv2I>(Source);



        }

        protected override void OnBar()
        {
            // count indicies and display to chart to test indicator values are being read correctly
       Chart.DrawStaticText("D_Orange", "Last orange dot index is " + MDE.D_Orange.ToString(), VerticalAlignment.Center, HorizontalAlignment.Right, "orange");
        }

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

Let me post the part of the indicator that generates the D_orange variable I'm trying to count the index of. 

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

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MDEv2I : Indicator
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Output("MACD", LineColor = "blue", Thickness = 3)]
        public IndicatorDataSeries Blueline { get; set; }
        [Output("Signal", LineColor = "red", Thickness = 3)]
        public IndicatorDataSeries Redline { get; set; }
        [Output("Histogram", IsHistogram = true, LineColor = "lightblue", Thickness = 4)]
        public IndicatorDataSeries Histogram { get; set; }

        [Output("D_Orange")]
        public int D_O { get; set; }

        #region declaring variables
        public MacdCrossOver Macd;
        public int Dr_last;
        public int Dr;
        public int Vg_last;
        public int Vg;
        public int D_Orange;
        public int D_Orange_Last;
        #endregion

        protected override void Initialize()
        {
            Macd = Indicators.MacdCrossOver(Source, 26, 12, 9);
            Dr = 0;
            Vg = 0;
            Dr_last = 0;
            Vg_last = 0;
            D_Orange = 0;
            D_Orange_Last = 0;
        }

        public override void Calculate(int index)
        {
            Blueline[index] = Macd.MACD[index];
            Redline[index] = Macd.Signal[index];
            Histogram[index] = Macd.Histogram[index];

            if (CalcHistZero() != 0)
            {
                D_Orange_Last = D_Orange;
                D_Orange = index;
                D_O = D_Orange;
            }
            if (CalcMacdZeroCross() != 0)
            {
                Vg_last = Vg;
                Vg = index;
            }
        }

        public int CalcHistZero()
        {
            int tempindex = 5;
            int period = 0;
            if (Vg != 0 && D_Orange != 0)
            {
                tempindex = Math.Max(Vg, D_Orange);
            }
            period = Histogram.Count - tempindex;
            for (int calc = (Histogram.Count - 1); calc > (Histogram.Count - period); calc--)
            {
                if (Blueline[calc] > 0)
                {
                    if (Histogram[calc - 1] > 0 && Histogram[calc] < 0)
                        return calc;
                }
                if (Blueline[calc] < 0)
                {
                    if (Histogram[calc - 1] < 0 && Histogram[calc] > 0 || Histogram[calc - 1] > 0 && Histogram[calc] < 0)
                        return calc;
                }
            }
            return 0;
        }
        public int CalcMacdZeroCross()
        {
            int tempindex = 5;
            int period = 0;
            if (Vg != 0 && D_Orange != 0)
            {
                tempindex = Math.Max(Vg, D_Orange);
            }
            period = Histogram.Count - tempindex;
            for (int calc = Blueline.Count; calc > (Blueline.Count - period); calc--)
            {
                // crossing below zero line
                if (Blueline[calc] > 0)
                {
                    if (Blueline[calc - 1] > 0 && (Blueline[calc] > 0 && Blueline[calc + 1] < 0))
                    {
                        return calc;
                    }
                }
                // crossing above zero line
                if (Blueline[calc] < 0)
                {
                    if (Blueline[calc - 1] < 0 && (Blueline[calc] < 0 && Blueline[calc + 1] > 0))
                    {
                        return calc;
                    }
                }
            }
            return 0;
        }        
      }
}

 

So the quick question I'm facing, is that when I choose the indicator from the custom indicators list and run the cbot in backtesting.... I see the following.

https://gyazo.com/417a8b01c94c37dd19910b734876cdd4

The indicator is drawing the dots, at the different indicies, but the readout from the cbot is identical to when the variable was initialized...0. 

Hope that clarifies some things, appreciate your time looking into it. Thank you!

cAD


@calgodemo

calgodemo
14 Jun 2019, 06:13

Further development on this:

 

I'm getting nullreference crashes on the indicator where it draws to the indicatorArea.... says the IndicatorArea is null.... 


@calgodemo

calgodemo
14 Jun 2019, 08:00

RE:

Panagiotis Charalampous said:

Hi calgodemo,

Can you share the cBot and Indicator code? 

Best Regards,

Panagiotis

General question: How do I reference the Indicator's IndicatorArea?

When I run the indicator in backtesting or live without debugging I can see all the stuff drawn in the indicatorarea without issue. As soon as I go to debug it throws a nullreferenceexception on the indicatorarea when I want to do anything with it... the nullreference is thrown in the indicator code! I am debugging an instance of the cbot.

This is extremely frustrating - the Indicator isoverlay property is set to false as you can see from the code above - I have no idea how to get over this exception, where in the API does it say I have to instaniate an indicator area... in the indicator? Is that even possible, intellisense doesn't suggest so.

please help! 

 

Thanks!

cAD


@calgodemo

PanagiotisCharalampous
14 Jun 2019, 09:48

Hi calgodemo,

It seems that the code you shared is not complete. There are no dots drawn on the chart using the posted indicator.

Best Regards,

Panagiotis


@PanagiotisCharalampous

calgodemo
14 Jun 2019, 18:25

public override void Calculate(int index)
        {
            Blueline[index] = Macd.MACD[index];
            Redline[index] = Macd.Signal[index];
            Histogram[index] = Macd.Histogram[index];
 
            if (CalcHistZero() != 0)
            {
                D_Orange_Last = D_Orange;
                D_Orange = index;
                IndicatorArea.DrawIcon("orangedot" + index.ToString(), ChartIconType.Diamond, D_Orange, Blueline[D_Orange], "orange");
            }
            if (CalcMacdZeroCross() != 0)
            {
                Vg_last = Vg;
                Vg = index;
            }
        }

When I was editing the post I guess I got overzealous and removed the line.... see above for line included in the Calculate method - it will throw a nullreferenceexception and die right there at 

IndicatorArea.DrawIcon("orangedot" + index.ToString(), ChartIconType.Diamond, D_Orange, Blueline[D_Orange], "orange");

For completeness sake the whole indicator modified take 2 is included below:

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
 
namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MDEv2I : Indicator
    {
        [Parameter("Source")]
        public DataSeries Source { get; set; }
 
        [Output("MACD", LineColor = "blue", Thickness = 3)]
        public IndicatorDataSeries Blueline { get; set; }
        [Output("Signal", LineColor = "red", Thickness = 3)]
        public IndicatorDataSeries Redline { get; set; }
        [Output("Histogram", IsHistogram = true, LineColor = "lightblue", Thickness = 4)]
        public IndicatorDataSeries Histogram { get; set; }
 
        #region declaring variables
        public MacdCrossOver Macd;
        public int Dr_last;
        public int Dr;
        public int Vg_last;
        public int Vg;
        public int D_Orange;
        public int D_Orange_Last;
        #endregion
 
        protected override void Initialize()
        {
            Macd = Indicators.MacdCrossOver(Source, 26, 12, 9);
            Dr = 0;
            Vg = 0;
            Dr_last = 0;
            Vg_last = 0;
            D_Orange = 0;
            D_Orange_Last = 0;
        }
 
        public override void Calculate(int index)
        {
            Blueline[index] = Macd.MACD[index];
            Redline[index] = Macd.Signal[index];
            Histogram[index] = Macd.Histogram[index];
 
            if (CalcHistZero() != 0)
            {
                D_Orange_Last = D_Orange;
                D_Orange = index;
                IndicatorArea.DrawIcon("orangedot" + index.ToString(), ChartIconType.Diamond, D_Orange, Blueline[D_Orange], "orange");
            }
            if (CalcMacdZeroCross() != 0)
            {
                Vg_last = Vg;
                Vg = index;
            }
        }
 
        public int CalcHistZero()
        {
            int tempindex = 5;
            int period = 0;
            if (Vg != 0 && D_Orange != 0)
            {
                tempindex = Math.Max(Vg, D_Orange);
            }
            period = Histogram.Count - tempindex;
            for (int calc = (Histogram.Count - 1); calc > (Histogram.Count - period); calc--)
            {
                if (Blueline[calc] > 0)
                {
                    if (Histogram[calc - 1] > 0 && Histogram[calc] < 0)
                        return calc;
                }
                if (Blueline[calc] < 0)
                {
                    if (Histogram[calc - 1] < 0 && Histogram[calc] > 0 || Histogram[calc - 1] > 0 && Histogram[calc] < 0)
                        return calc;
                }
            }
            return 0;
        }
        public int CalcMacdZeroCross()
        {
            int tempindex = 5;
            int period = 0;
            if (Vg != 0 && D_Orange != 0)
            {
                tempindex = Math.Max(Vg, D_Orange);
            }
            period = Histogram.Count - tempindex;
            for (int calc = Blueline.Count; calc > (Blueline.Count - period); calc--)
            {
                // crossing below zero line
                if (Blueline[calc] > 0)
                {
                    if (Blueline[calc - 1] > 0 && (Blueline[calc] > 0 && Blueline[calc + 1] < 0))
                    {
                        return calc;
                    }
                }
                // crossing above zero line
                if (Blueline[calc] < 0)
                {
                    if (Blueline[calc - 1] < 0 && (Blueline[calc] < 0 && Blueline[calc + 1] > 0))
                    {
                        return calc;
                    }
                }
            }
            return 0;
        }        
      }
}

 


@calgodemo

calgodemo
14 Jun 2019, 18:31

I've also read on other threads here that one must invoke the calculate method in the cbot... I've done this as well both onbar and ontick with the same result.

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 MDE : Robot
    {

        [Parameter("Source")]
        public DataSeries Source { get; set; }
        [Parameter(DefaultValue = 60, MinValue = 5)]
        public int Timeframe { get; set; }

        // Declare indicator.
        public MDEv2I MDE;
        // here are some variables I am creating along the way.

        protected override void OnStart()
        {
            // instantiate custom indicator
            MDE = Indicators.GetIndicator<MDEv2I>(Source);
        }

        protected override void OnBar()
        {
       MDE.Calculate(MarketSeries.Open.Count - 1);
            // count indicies and display to chart to test indicator values are being read correctly

       Chart.DrawStaticText("D_Orange", "Last orange dot index is " + MDE.D_Orange.ToString(), VerticalAlignment.Center, HorizontalAlignment.Right, "orange");
        }
        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 


@calgodemo