variables from the indicator for use in the bot

Created at 14 Sep 2021, 16:12
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!
TR

travkinsm1

Joined 05.04.2018

variables from the indicator for use in the bot
14 Sep 2021, 16:12


Hello! I am facing the following problem. I needed a boolean variable from an indicator in a bot, which changes when Calculate is called. The only way I've found to call it is to create an IndicatorDataSeries that takes the value 1 if it's false, and 2 if it's true. It turned out that this is very inconvenient for testing, because all the time the graph is reset to the position where this variable is displayed, capturing the values ​​1 and 2. How can you solve my problem? Thanks in advance. I am attaching an example to illustrate my problem.

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 TestTI : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

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

        public bool b;
        protected override void Initialize()
        {
            b = false;
        }

        public override void Calculate(int index)
        {
            b = !b;
            // Calculate value at specified index
            // Result[index] = ...
        }
    }
}
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 BoolBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        private TestTI ind;
        protected override void OnStart()
        {
            ind = Indicators.GetIndicator<TestTI>(1.0);
        }

        protected override void OnTick()
        {
            Print(ind.b);
        }

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

 


@travkinsm1
Replies

amusleh
15 Sep 2021, 11:08

Hi,

Right now there is only one standard way to share memory data between an indicator and cBot, its IndicatorDataSeries.

But there is a workaround, change your cBot code to this:

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 BoolBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        private TestTI ind;
        protected override void OnStart()
        {
            ind = Indicators.GetIndicator<TestTI>(1.0);
        }

        protected override void OnTick()
        {
            ind.Calculate(Bars.Count - 1);
            Print(ind.b);
        }

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

Add the call to indicator Calculate method at the top of your cBot OnTick method and it should work.


@amusleh

travkinsm1
15 Sep 2021, 16:57

RE:

Thanks for the quick response. Do I understand correctly that the Calculate function will be called again?

 


@travkinsm1

amusleh
16 Sep 2021, 09:23

RE: RE:

travkinsm1 said:

Thanks for the quick response. Do I understand correctly that the Calculate function will be called again?

 

Hi,

No, its not called twice, indicators are lazy loaded, the API doesn't call an indicator Calculate method unless you access one of its data series values.

Try this:

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 TestTI : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

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

        public bool b;
        protected override void Initialize()
        {
            b = false;
        }

        public override void Calculate(int index)
        {
            Result[index] = index;
        
            b = !b;
            // Calculate value at specified index
            // Result[index] = ...
        }
    }
}
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 BoolBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }
        private TestTI ind;
        protected override void OnStart()
        {
            ind = Indicators.GetIndicator<TestTI>(1.0);
        }

        protected override void OnTick()
        {
            Print(ind.Result.LastValue);
            Print(ind.b);
        }

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

 


@amusleh

travkinsm1
21 Sep 2021, 15:05

Thanks a lot. It helped me.


@travkinsm1

travkinsm1
22 Sep 2021, 17:40

At the same time, there can be no confusion when calling several indicators of the following type.

ind0.Calculate(Bars.Count - 1);
ind1.Calculate(Bars.Count - 1);
ind2.Calculate(Bars.Count - 1);
ind3.Calculate(Bars.Count - 1);
ind4.Calculate(Bars.Count - 1);
           

Because on backtesting, the variable I call behaves strangely. Very strangely.


@travkinsm1

amusleh
23 Sep 2021, 09:05

RE:

travkinsm1 said:

At the same time, there can be no confusion when calling several indicators of the following type.

ind0.Calculate(Bars.Count - 1);
ind1.Calculate(Bars.Count - 1);
ind2.Calculate(Bars.Count - 1);
ind3.Calculate(Bars.Count - 1);
ind4.Calculate(Bars.Count - 1);
           

Because on backtesting, the variable I call behaves strangely. Very strangely.

Hi,

I recommend you to use an indicator data series output to get data back from indicator, and if possible you can move your indicators logic to your cBot instead of referencing them.

If your indicators aren't using indicator data series output then move the logic to your cBot, use indicator reference only if your indicator has an output data series.


@amusleh