Issue with Indicators that require the whole Bars object as argument
Issue with Indicators that require the whole Bars object as argument
19 May 2021, 11:57
Hello,
I have a custom indicator based on the ADX indicator. The ADX indicator requires the whole Bars object to be provided in it's overloaded constructor. Unfortunately, this makes it impossible to reference it correctly from a bot for the purposes of a MTF setup, as Bars is not allowed to be declared as a Parameter for an indicator.
The workaround proposed was to directly set the Bars object after creating the indicator. This works to an extend, because if you reference the same custom indicator twice, both instances will have the last assigned Bars value to them.
You can look the issue with the code below:
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 NewcBot : Robot
{
private MyDiPlus _diPlusSignal;
private MyDiPlus _diPlusFilter;
private DirectionalMovementSystem _adx;
private Bars SignalBars;
protected override void OnStart()
{
SignalBars = MarketData.GetBars(TimeFrame.Minute5);
_adx = Indicators.DirectionalMovementSystem(14);
_diPlusFilter = Indicators.GetIndicator<MyDiPlus>(14);
_diPlusFilter.Bars = Bars;
_diPlusFilter.Init();
_diPlusSignal = Indicators.GetIndicator<MyDiPlus>(14);
_diPlusSignal.Bars = SignalBars;
_diPlusSignal.Init();
}
protected override void OnTick()
{
var index = Bars.Count - 1;
var signalIndex = GetIndexByDate(SignalBars, Bars.OpenTimes[index]);
_diPlusFilter.Calculate(index);
_diPlusSignal.Calculate(signalIndex);
}
protected override void OnBar()
{
Print("_diPlusFilter.TimeFrame " + _diPlusFilter.TimeFrame);
Print("_diPlusFilter.Bars.TimeFrame " + _diPlusFilter.Bars.TimeFrame);
Print("_diPlusSignal.TimeFrame " + _diPlusSignal.TimeFrame);
Print("_diPlusSignal.Bars.TimeFrame " + _diPlusSignal.Bars.TimeFrame);
Print("DI+ Real Value: " + _adx.DIPlus.LastValue.ToString("n2"));
Print("Filter DI+ Value: " + _diPlusFilter.DiPlus.LastValue.ToString("n2"));
Print("Signal DI+ Value: " + _diPlusFilter.DiPlus.LastValue.ToString("n2"));
}
public static int GetIndexByDate(Bars series, DateTime time)
{
for (int i = series.ClosePrices.Count - 1; i > 0; i--)
{
if (time == series.OpenTimes[i])
return i;
}
return -1;
}
}
}
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 MyDiPlus : Indicator
{
private DirectionalMovementSystem _adx;
[Parameter(DefaultValue = 14)]
public int ADXPeriods { get; set; }
[Output("Di Plus", LineColor = "Green")]
public IndicatorDataSeries DiPlus { get; set; }
public Bars Bars;
protected override void Initialize()
{
}
public void Init()
{
_adx = Indicators.DirectionalMovementSystem(Bars, ADXPeriods);
}
public override void Calculate(int index)
{
DiPlus[index] = _adx.DIPlus[index];
}
}
}
My proposal for a cleaner solution is to have an extra overload for indicators that require the whole Bars object, with the (usually) required 4 DataSeries (High/Low/Open/Close).
With Best Regards
Replies
cAlgoBuddy
19 May 2021, 15:42
RE:
PanagiotisCharalampous said:
Hi cAlgoBuddy,
This happens because in the following case, the constructor method returns the same indicator.
_diPlusFilter = Indicators.GetIndicator<MyDiPlus>(14); _diPlusFilter.Bars = Bars; _diPlusFilter.Init(); _diPlusSignal = Indicators.GetIndicator<MyDiPlus>(14); _diPlusSignal.Bars = SignalBars; _diPlusSignal.Init();
_diPlusFilter and _diPlusSignal are references to the same object. To force the constructor to return a new object, create a dummy parameter and pass a differrert value every time e.g.
_diPlusFilter = Indicators.GetIndicator<MyDiPlus>("Bars", 14); _diPlusFilter.Bars = Bars; _diPlusFilter.Init(); _diPlusSignal = Indicators.GetIndicator<MyDiPlus>("Signal", 14); _diPlusSignal.Bars = SignalBars; _diPlusSignal.Init();
Hope this helps.
Best Regards,
Panagiotis
Many thanks, it works fine like this!
@cAlgoBuddy
PanagiotisCharalampous
19 May 2021, 15:05
Hi cAlgoBuddy,
This happens because in the following case, the constructor method returns the same indicator.
_diPlusFilter and _diPlusSignal are references to the same object. To force the constructor to return a new object, create a dummy parameter and pass a differrert value every time e.g.
Hope this helps.
Best Regards,
Panagiotis
Join us on Telegram
@PanagiotisCharalampous