Incorrect behavior of ISeries objects

Questions about MultiCharts .NET and user contributed studies.
roughtrader
Posts: 2
Joined: 11 Mar 2022

Incorrect behavior of ISeries objects

Postby roughtrader » 11 Mar 2022

I've been easing into the latest MC.net in the past several months, but only yesterday discovered strange behavior with ISeries objects.
I created a very simple indicator to illustrate:

using System;
using System.Linq;
using System.Collections.Generic;
using PowerLanguage.Function;

namespace PowerLanguage.Indicator
{
public class i_DebugByConsole : IndicatorObject
{
int bar_count = 0;

public i_DebugByConsole(object _ctx):base(_ctx)
{
}

protected override void Create()
{
}

protected override void StartCalc()
{
}

protected override void CalcBar()
{
if (Environment.IsRealTimeCalc && Bars.Status == EBarState.Close)
{
Output.WriteLine(String.Empty);
Output.WriteLine(String.Concat("-------- Bar ", bar_count.ToString(), " --------"));
bar_count++;

for (int idx = 0; idx < 30; idx++)
Output.WriteLine(String.Concat("C[", idx.ToString(), "]: ", Bars.Close[idx].ToString()));
}
}
}
}


The code is applied to real-time 1-minutes ES data from TS. At the close of each bar, the code should print the last 30 closing prices to the output window.

Here is the actual output:


-------- Bar 0 --------
C[0]: 4232

-------- Bar 1 --------
C[0]: 4232.25
C[1]: 4232
C[2]: 4233
C[3]: 4233
C[4]: 4233.25
C[5]: 4232.5
C[6]: 4233.75

-------- Bar 2 --------
C[0]: 4231.25
C[1]: 4232.25
C[2]: 4232
C[3]: 4233
C[4]: 4233
C[5]: 4233.25
C[6]: 4232.5
C[7]: 4233.75
C[8]: 4233
C[9]: 4234.5
C[10]: 4235.5
C[11]: 4235.5
C[12]: 4233.75

-------- Bar 3 --------
C[0]: 4231
C[1]: 4231.25
C[2]: 4232.25
C[3]: 4232
C[4]: 4233
C[5]: 4233
C[6]: 4233.25
C[7]: 4232.5
C[8]: 4233.75
C[9]: 4233
C[10]: 4234.5
C[11]: 4235.5
C[12]: 4235.5
C[13]: 4233.75
C[14]: 4233.5
C[15]: 4230.25
C[16]: 4230.75
C[17]: 4232
C[18]: 4234.5
C[19]: 4235.25
C[20]: 4234.25
C[21]: 4233.25

-------- Bar 4 --------
C[0]: 4231.25
C[1]: 4231
C[2]: 4231.25
C[3]: 4232.25
C[4]: 4232
C[5]: 4233
C[6]: 4233
C[7]: 4233.25
C[8]: 4232.5
C[9]: 4233.75
C[10]: 4233
C[11]: 4234.5
C[12]: 4235.5
C[13]: 4235.5
C[14]: 4233.75
C[15]: 4233.5
C[16]: 4230.25
C[17]: 4230.75
C[18]: 4232
C[19]: 4234.5
C[20]: 4235.25
C[21]: 4234.25
C[22]: 4233.25
C[23]: 4235
C[24]: 4234.75
C[25]: 4237.25
C[26]: 4235.75
C[27]: 4235.25
C[28]: 4235.25
C[29]: 4234.25

-------- Bar 5 --------
C[0]: 4231.75
C[1]: 4231.25
C[2]: 4231
C[3]: 4231.25
C[4]: 4232.25
C[5]: 4232
C[6]: 4233
C[7]: 4233
C[8]: 4233.25
C[9]: 4232.5
C[10]: 4233.75
C[11]: 4233
C[12]: 4234.5
C[13]: 4235.5
C[14]: 4235.5
C[15]: 4233.75
C[16]: 4233.5
C[17]: 4230.25
C[18]: 4230.75
C[19]: 4232
C[20]: 4234.5
C[21]: 4235.25
C[22]: 4234.25
C[23]: 4233.25
C[24]: 4235
C[25]: 4234.75
C[26]: 4237.25
C[27]: 4235.75
C[28]: 4235.25
C[29]: 4235.25


It appears that for the first several bars upon applying the indicator to the real-time chart, that the for-loop hangs when calling Bar.Close[k] for some k. The k value gets larger with each passing bar, so more ISeries data is retrieved before the loop hangs. In this particular example, the loop will stop hanging from Bar 4, and all bars after that show a print of all 30 close prices.

This is repeatable for many iteration values, not just 30. This is also not an issue of insufficient maxbarsback, I have plenty of bars on the chart well exceeding 30.

Is there an issue with ISeries objects?

Thanks for help and feedback.

roughtrader
Posts: 2
Joined: 11 Mar 2022

Re: Incorrect behavior of ISeries objects

Postby roughtrader » 13 Mar 2022

After a little more investigation, I have some insight as to what is happening. I have adjusted the above code in two major areas:

1) Instead of just choosing the last 30 bars, the code now reads all 1m close prices for only the current session, and stores the results in a List<double>.
2) I have allowed the indicator to keep storing data in the List<double for each bar in the entire history. The results will only be printed to Output in when Environment.IsRealTime = true.

Here is the code:

using System;
using System.Linq;
using System.Collections.Generic;
using PowerLanguage.Function;

namespace PowerLanguage.Indicator
{
public class i_DebugByConsole : IndicatorObject
{
private int bar_count;
private double BAR_INTERVAL;
private TimeSpan FIRST_BAR_TIME, LAST_BAR_TIME;
private List<double> c_history;

public i_DebugByConsole(object _ctx):base(_ctx)
{
}

protected override void Create()
{
c_history = new List<double>();
}

protected override void StartCalc()
{
BAR_INTERVAL = Convert.ToDouble(Bars.Info.Resolution.Size);
FIRST_BAR_TIME = Bars.Sessions[0].StartTime.Add(TimeSpan.FromMinutes(BAR_INTERVAL));
LAST_BAR_TIME = Bars.Sessions[0].EndTime;
}

protected override void CalcBar()
{
if (Bars.Status == EBarState.Close)
{
if (Bars.CurrentBar == 1)
bar_count = 0;

c_history.Clear();

int idx = 0;
bool read_complete = false;
while (!read_complete)
{
c_history.Add(Bars.Close[idx]);

if (TimeSpan.Compare(FIRST_BAR_TIME, Bars.Time[idx].TimeOfDay) == 0)
read_complete = true;
else
idx++;
}

if (Environment.IsRealTimeCalc)
{
Output.WriteLine(String.Empty);
Output.WriteLine(String.Concat("-------- Bar ", bar_count.ToString(), " --------"));
bar_count++;

for (int k = 0; k < c_history.Count; k++)
Output.WriteLine(String.Concat("C[", k.ToString(), "]: ", c_history.ElementAt(k).ToString()));
}
}
}
}
}



#1 is just an adjustment because I am actually interested in the current session bars, and no more than that. Just an adjustment for application.
#2 allows calls to ISeries objects in historical data before real-time data is encountered.

I have found that these adjustments solve the problem, but this is an issue that should be fixed in MC.net.
To the developers, please review your class implementation of ISeries so that if the class is instanced and called only in real-time, there won't be an issue with missing data called back to function/indicator.

Thanks.

User avatar
Svetlana MultiCharts
Posts: 645
Joined: 19 Oct 2017
Has thanked: 3 times
Been thanked: 163 times

Re: Incorrect behavior of ISeries objects

Postby Svetlana MultiCharts » 25 Mar 2022

Hi roughtrader,

MaxsBarsBack value shall be equal to the number of bars back the study needs to reference for calculation. E.g. if MaxBarsBack = 3 the study references 3 bars back starting from the 4th bar. If the study referenced back from the 3th bar inclusively – it would see 2 bars back and nothing instead for the 1st bar.

MultiCharts doesn’t look inside the code of the study and determine the exact number of bars required for calculation. That’s why this value is autodetected if the corresponding parameter is selected or if user specified value is incorrect.

In your case, the indicator calculates from the first bar and detects there are not enough bars for initial calculation. Then it recalculates (turns off and on) with an offset of 7 bars, and finds there are still not enough bars, then 12 bars and so on, until the value becomes equal to 34. This value is enough to refer to 30 bars back, therefore MaxBarsBack auto detection stops.

You can set the fixed value (31) for this indicator in Format Study - Format – Properties – Maximum number of bars study will reference - User Specified.


Return to “MultiCharts .NET”