Signals from Custom Indicators to Robot

Created at 31 Jul 2020, 07:32
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!
BJ

BJORNBERNAU

Joined 21.07.2020

Signals from Custom Indicators to Robot
31 Jul 2020, 07:32


Hello! 

I am neither the seasoned C# programmer nor a rookie. 

I believe I haven't made the usual mistakes on customization of an indicator, like missing out on parameters, initializing or managing references to the indicator, as can be seen below with a second example of a successfully built custom indicator for cBot. I am stuck with the same problem now for several days and wonder if it would be possible to get any assistance?  I've oversimplified to find the snag in a version of a modified Bollinger signal to be transferred to cBot, as shown here.  

 

INDICATOR

 

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class aCBOTbaseBOLLINGER : Indicator
    {
        [Output("B", PlotType = PlotType.Points, LineColor = "#FFFFD700", Thickness = 4)]
        public IndicatorDataSeries B { get; set; }

        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("BandPeriod", DefaultValue = 18)]
        public int BandPeriod { get; set; }

        [Parameter("Std", DefaultValue = 1.8)]
        public double Std { get; set; }

        [Parameter("MAType")]
        public MovingAverageType MAType { get; set; }


        public BollingerBands boll;


        protected override void Initialize()
        {
            boll = Indicators.BollingerBands(Source, BandPeriod, Std, MAType);
        }

        public override void Calculate(int index)
        {

            var BBT = boll.Top[index];
            var HP = Bars.HighPrices[index];
            var high = HP - BBT;

            if (high > 0)
            {
                B[index] = boll.Top[index];
            }
        }
    }
}

 

 

ROBOT

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

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


        [Output("B")]
        public IndicatorDataSeries B { get; set; }

        [Parameter()]
        public DataSeries Source { get; set; }

        [Parameter("BandPeriod", DefaultValue = 18)]
        public int BandPeriod { get; set; }

        [Parameter("Std", DefaultValue = 1.8)]
        public double Std { get; set; }

        [Parameter("MAType")]
        public MovingAverageType MAType { get; set; }

        private aCBOTbaseBOLLINGER S1;

        protected override void OnStart()
        {
            S1 = Indicators.GetIndicator<aCBOTbaseBOLLINGER>(B, BandPeriod, Std, MAType);
        }

        protected override void OnBar()
        {
            Print("     B     ", S1.B);
        }
    }
}
 

ERROR MESSAGES ARE 

02/04/2020 21:00:00.000 |      B     IndicatorDataSeries (Count: 0, LastValue: ¤¤¤)
02/04/2020 21:00:00.000 | Crashed in Calculate with NullReferenceException: The object reference has no not been declared an instance of an object (Translated from swedish, see next.).
02/04/2020 21:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 21:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 21:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 20:00:00.000 |      B     IndicatorDataSeries (Count: 0, LastValue: ¤¤¤)
02/04/2020 20:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 20:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 20:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.
02/04/2020 20:00:00.000 | Crashed in Calculate with NullReferenceException: Objektreferensen har inte angetts till en instans av ett objekt.                                                                          02/04/2020 21:00:00.000 |      B     IndicatorDataSeries (Count: 0, LastValue: ¤¤¤)

Although there are no situations where there is a null signal, there is a message saying NullReferenceException. 

Even excluding the first 18 periods for the first Bollinger calulations for Count 0 to count 17 doesn't solve this problem. In addition it is hard to understand why there should be liberated four instances of an object that have no reference? 

In addition, the correct references to the Count and LastValue never appear. 

Nowhere is explained that all the parameters have to be included in the Robot, that are included in the Indicator, even if they're never used, as shown below. Missing out on any of the parameters between the bot and the indicator, stops the execution. That is ...., except for the Source, that shouldn't be included in the indicator reference in the cBot, as it is in the indicator, but never referenced. Faulty declarations of parameters don't elucidate the problem. So this doesn't seem to be the reason for the faulty object reference. If e.g. declaring parameters newer used by either robot or indicator, there is no error for missed object reference, as in below posted example which runs without a snag.

So what is the problem? 

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class aCBOTbaseINDICATOR : Indicator
    {


        [Output("a", PlotType = PlotType.Points, LineColor = "#FFFFD700", Thickness = 4)]
        public IndicatorDataSeries a { get; set; }

        [Output("B", PlotType = PlotType.Points, LineColor = "#FFFFD700", Thickness = 4)]
        public IndicatorDataSeries B { get; set; }

        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("BandPeriod", DefaultValue = 18)]
        public int BandPeriod { get; set; }

        [Parameter("MAType")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Std", DefaultValue = 1.8)]
        public double Std { get; set; }

        public BollingerBands boll;


        protected override void Initialize()
        {
        }

        public override void Calculate(int index)
        {
            {
                B[index] = Bars.ClosePrices[index];
            }
        }
    }
}

 

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

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

        [Parameter(DefaultValue = 100000)]
        public int Volume { get; set; }

        [Output("a")]
        public IndicatorDataSeries a { get; set; }

        [Output("B")]
        public IndicatorDataSeries B { get; set; }

        [Parameter("Source")]
        public DataSeries Source { get; set; }

        [Parameter("BandPeriod", DefaultValue = 18)]
        public int BandPeriod { get; set; }

        [Parameter("MAType")]
        public MovingAverageType MAType { get; set; }

        [Parameter("Std", DefaultValue = 1.8)]
        public double Std { get; set; }


        private aCBOTbaseINDICATOR S1;



        protected override void OnStart()
        {
            S1 = Indicators.GetIndicator<aCBOTbaseINDICATOR>(B, BandPeriod, MAType, Std);
        }


        protected override void OnBar()
        {

            Print(S1.B);

            ExecuteMarketOrder(TradeType.Buy, Symbol.Name, Volume, "buy1", 14, 80);
        }
    }
}

 

Produces a perfect series, despite declaring parameters never used, above. 
 

01/11/2011 22:00:00.000 | IndicatorDataSeries (Count: 143, LastValue: 1,37103)
01/11/2011 21:00:00.000 | IndicatorDataSeries (Count: 142, LastValue: 1,37359)
01/11/2011 20:00:00.000 | IndicatorDataSeries (Count: 141, LastValue: 1,36788)
01/11/2011 19:00:00.000 | IndicatorDataSeries (Count: 140, LastValue: 1,36739)
01/11/2011 18:00:00.000 | IndicatorDataSeries (Count: 139, LastValue: 1,36653)
01/11/2011 17:00:00.000 | IndicatorDataSeries (Count: 138, LastValue: 1,36561)
01/11/2011 16:00:00.000 | IndicatorDataSeries (Count: 137, LastValue: 1,36353)
01/11/2011 15:00:00.000 | IndicatorDataSeries (Count: 136, LastValue: 1,3682)
01/11/2011 14:00:00.000 | IndicatorDataSeries (Count: 135, LastValue: 1,3697)
01/11/2011 13:00:00.000 | IndicatorDataSeries (Count: 134, LastValue: 1,37009)
01/11/2011 12:00:00.000 | IndicatorDataSeries (Count: 133, LastValue: 1,37023)
01/11/2011 11:00:00.000 | IndicatorDataSeries (Count: 132, LastValue: 1,37728)
01/11/2011 10:00:00.000 | IndicatorDataSeries (Count: 131, LastValue: 1,37686)
01/11/2011 09:00:00.000 | IndicatorDataSeries (Count: 130, LastValue: 1,38128)
01/11/2011 08:00:00.000 | IndicatorDataSeries (Count: 129, LastValue: 1,38125)
01/11/2011 07:00:00.000 | IndicatorDataSeries (Count: 128, LastValue: 1,38426)
01/11/2011 06:00:00.000 | IndicatorDataSeries (Count: 127, LastValue: 1,38424)
01/11/2011 05:00:00.000 | IndicatorDataSeries (Count: 126, LastValue: 1,38451)
01/11/2011 04:00:00.000 | IndicatorDataSeries (Count: 125, LastValue: 1,3849)
01/11/2011 03:00:00.000 | Backtesting started

 

Other morsels of important information never declared in the website, is what happens when you amend the Indicator. When you press the build button, the changes are not transferred via the reference to the cBot, you have additionally to build the cBot again, to make changes transfer to the cBot before running cBot. It took me quite a while to realise this. I think the complications with a custom indicator are too many to be realised even IF you have som C# skills. You have declared how you build a custom indicator, but now how to transfer signals to the cBot, which includes a lot of amendments in the cBot, except the simple thing of managing references to the indicator. 

The snag that really puts things on hold is not the initialization of the Bollingerbands in the indicator in the above first example. It is when you declare the Bollinger signal 

var BBT = boll.Top[index];

the system doesn't work. It is not possible to convert this variable, a double array, into a parameter, which I also tried. 

 

Sincerely 

 

Björn Bernau 

Sweden 


@BJORNBERNAU
Replies

PanagiotisCharalampous
31 Jul 2020, 09:43

Hi Björn,

Your mistake is here

     S1 = Indicators.GetIndicator<aCBOTbaseBOLLINGER>(B, BandPeriod, Std, MAType);

 I guess this is what you wanted to code instead

 S1 = Indicators.GetIndicator<aCBOTbaseBOLLINGER>(Source, BandPeriod, Std, MAType);

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

BJORNBERNAU
01 Aug 2020, 14:52

RE:

PanagiotisCharalampous said:

Hi Björn,

Your mistake is here

     S1 = Indicators.GetIndicator<aCBOTbaseBOLLINGER>(B, BandPeriod, Std, MAType);

 I guess this is what you wanted to code instead

 S1 = Indicators.GetIndicator<aCBOTbaseBOLLINGER>(Source, BandPeriod, Std, MAType);

Best Regards,

Panagiotis 

Join us on Telegram

 

Yes indeed! 

Thank you, l am now entangled in the next issue, as posted. 

 

Björn 


@BJORNBERNAU

... Deleted by UFO ...