Read value of a custom indicator in a cBot
Read value of a custom indicator in a cBot
28 Sep 2024, 07:43
Hi there!
I have a bot and a custom indicator, from which the bot want to request a value in its OnBar method.
The bot runs on a different TimeFrame than the bot - e.g. the bot runs on Minute-Bars, and the Indicator usually runs on Daily-Bars.
I am able to initialize the indicator in the bots “OnStart” method:
````
// impulseSystem is the custom indicator
impulseSystem = Indicators.GetIndicator<ImpulseSystem>(12, 26, 9, 13);
````
I can see the logs from the indicators "Initialize" method, and I can see that my bot's impulseSystem private field is not null.
But later in the “OnBar” method, I basically want to read the last value from the indicators data series, like this:
````
protected override void OnBar()
{
double systemBarColor = impulseSystem.GetLastElderColor();
}
````
For completeness I will paste the whole indicators code here, but from my point of view the “GetLastElderColor” method is most important. Additionally, I have the feeling that the Calculate method of the indicator is never executed..
````
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ImpulseSystem : Indicator
{
/*
[Parameter("Source")]
public DataSeries Source { get; set; }
*/
[Parameter("MACD Fast Length", DefaultValue = 12, MinValue = 1)]
public int MacdFastLength { get; set; }
[Parameter("MACD Slow Length", DefaultValue = 26, MinValue = 1)]
public int MacdSlowLength { get; set; }
[Parameter("MACD Signal Length", DefaultValue = 9, MinValue = 1)]
public int MacdSignalLength { get; set; }
[Parameter("EMA Length", DefaultValue = 13, MinValue = 1)]
public int EmaLength { get; set; }
[Output("Elder Color 1: Green, 0: Blue, -1: Red")]
public IndicatorDataSeries Result;
private ExponentialMovingAverage _ema;
private ExponentialMovingAverage _macdFast;
private ExponentialMovingAverage _macdSlow;
private ExponentialMovingAverage _macdSignal;
private IndicatorDataSeries _macdDifference;
// Data series to store the bar colors (1 = green, -1 = red, 0 = blue)
private IndicatorDataSeries _barColors;
private Bars _dailyBars;
protected override void Initialize()
{
Print("Initializing.....");
_dailyBars = MarketData.GetBars(TimeFrame.Daily);
_ema = Indicators.ExponentialMovingAverage(_dailyBars.ClosePrices, EmaLength);
_macdFast = Indicators.ExponentialMovingAverage(_dailyBars.ClosePrices, MacdFastLength);
_macdSlow = Indicators.ExponentialMovingAverage(_dailyBars.ClosePrices, MacdSlowLength);
_macdDifference = CreateDataSeries();
_macdSignal = Indicators.ExponentialMovingAverage(_macdDifference, MacdSignalLength);
_barColors = CreateDataSeries();
Print("Impulse System Initialized");
}
public override void Calculate(int index)
{
Print("Calling Calculate"); // I never see this in the bots logs
_macdDifference[index] = _macdFast.Result[index] - _macdSlow.Result[index];
double macd = _macdDifference[index];
double macdSignal = _macdSignal.Result[index];
double macdHistogram = macd - macdSignal;
double previousMacdHistogram = _macdDifference[index - 1] - _macdSignal.Result[index - 1];
double emaCurrent = _ema.Result[index];
double emaPrevious = _ema.Result[index - 1];
bool isBullish = emaCurrent > emaPrevious && macdHistogram > previousMacdHistogram;
bool isBearish = emaCurrent < emaPrevious && macdHistogram < previousMacdHistogram;
if (isBullish)
{
//Chart.SetBarColor(index, Color.Green);
Result[index] = 1;
Print("Setting Result to 1");
_barColors[index] = 1;
}
else if (isBearish)
{
//Chart.SetBarColor(index, Color.Red);
Result[index] = -1;
Print("Setting Result to -1");
_barColors[index] = -1;
}
else
{
//Chart.SetBarColor(index, Color.Blue);
Result[index] = 0;
Print("Setting Result to 0");
_barColors[index] = 0;
}
}
public double GetLastElderColor()
{
Print("GetLastElderColor: _barColors ", _barColors.Count); // is always 0
// Print("GetLastElderColor: Result", Result.Count); // throws Exception Object reference not set to an instance of an object.
Print("GetLastElderColor dailySeries last bar close: ", _dailyBars.Last(0).OpenTime, _dailyBars.Last(0).Close); // This prints the correct previously completed daily bar
return _barColors.LastValue; // or the last value from Result, something that the Calculate method is setting
}
}
}
````
So how can I get the indicator to calculate values and store them in _barColors (or somewhere else) where I can access them from the bot code?
Any help is highly appreciated! Thank you!
P.S. I am proficient in programming (TypeScript), so C# reads very familiar, but this is my first time developing on the cTrader platform :)
PanagiotisCharalampous
30 Sep 2024, 06:21
Hi there,
Indicators implement a lazy loading pattern. So for the Calculate() method to be executed, you need to call the Result data source somewhere in your cBot's code before you call your custom method e.g.
Best regards,
Panagiotis
@PanagiotisCharalampous