Manual looping support?

Questions about MultiCharts .NET and user contributed studies.
pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Manual looping support?

Postby pthegr8 » 20 May 2021

I'm starting to get more familiar with creating studies.
from the MC.net Programming Guide:

"The script begins to work through all of the historic bars of the symbol and on each bar the CalcBar() method is called"

Is there a way you can decide whether how much (if any) to loop, instead of executing code for all bars in the bar data array?

calcBar() automatically loops through all the bars and does the code's calculations for each and every bar of the bar data array.

I don't want this behavior; I need to be able to create my own loop(s) through the bar data array.

A very simplistic example:

loop through bar(50) to bar(60) and find the lowest low.

if this is done inside CalcBar() method. it would find the lowest low between bar(50) and bar(60) for every bar in the bar data array.

User avatar
Kate MultiCharts
Posts: 591
Joined: 21 Oct 2020
Has thanked: 9 times
Been thanked: 148 times

Re: Manual looping support?

Postby Kate MultiCharts » 26 May 2021

Hello pthegr8,

Here's an example you can refer to in order to achieve your goal:

Code: Select all

protected override void CalcBar(){ // skiping logic if (Bars.CurrentBar < 50) return; if (Bars.CurrentBar > 60) return; // indicator logic }

pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Re: Manual looping support?

Postby pthegr8 » 12 Jun 2021

It is still very confusing . for example consider the following code:

Code: Select all

using System; using System.Drawing; using System.Linq; using PowerLanguage.Function; using System.Windows.Forms; namespace PowerLanguage.Indicator{ public class test_bars_1 : IndicatorObject { public test_bars_1(object _ctx):base(_ctx){} protected override void Create() { } protected override void StartCalc() { for (int i = 10; i < 14; i++) { MessageBox.Show("Barlow: ", Bars.FullSymbolData.Low[i].ToString()); } } protected override void CalcBar(){ } } }
added this on a chart of SPY 3min, with "data range 30 bars back from 6/12/21".

Attached is a chart, with a bar index added on top.
as well as the result for two different settings on the for loop:
for (int i = 10; i < 14; i++) and for (int i = 16; i < 20; i++)
for the 1st loop I get the lows for bar# 24 through 27, for the 2nd loop I get the lows for Bar# 20 through 24
How is that possible? I'm supposedly addressing a range of bars shifted by 6 bars, but I get the results of a range of bars shifted 4 bars!
Attachments
SPY-30bars.jpg
(237.75 KiB) Not downloaded yet
LOOP-RESULTS.jpg
(62.15 KiB) Not downloaded yet

pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Re: Manual looping support?

Postby pthegr8 » 12 Jun 2021

In addition;
as per previous example if you have a data range limit set at, in this case, 30bars, then addressing for example Bars.FullSymbolData.Low[10]. should I expect to get the low of the 10th bar from the left of the chart, or the 10th bar from the right of the chart?

Neither one of these appear to be true; for example in that first loop of for (int i = 10; i < 14; i++) the first return I get (where i=10) is the lowvalue for Bar# 24 on the index I drew on the chart. so that's the 6th bar from the left. or the 24th bar from the right. I would expect to get either the low of bar20 (10bars from left), or the low of bar 9 (10bars from the right of the chart), depending whether MC starts indexing bars from the most current back, or from the oldest to the newest bar.
I'm migrating from another platform. so I must be completely misinterpreting how bars are getting addressed in the index. it's making no sense to me at this point.

pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Re: Manual looping support?

Postby pthegr8 » 15 Jun 2021

solved by reading page 23 of the MultiCharts.NET-ProgrammingGuide-v.1.2.pdf
"Please note that bar indexation is executed, starting from the current bar, leftwards with positive indices, and rightwards with negative ones."

so to walk through the bar index from left to right, needed to use negative index:
MessageBox.Show("Barlow: ", Bars.FullSymbolData.Low[-i].ToString());


Only problem I have left is to recalc either on every tick, or at a specific interval.
I enabled "Update on every tick", but it doesn't do it. I need to manually stop and start my indicator to have it recalculate.
also tried :
[SameAsSymbol(true), SkipIdenticalTicks(true), UpdateOnEveryTick(true)]
and same result.
I tried the example indicator on page 23 of the manual, that calculates an average price of totalbars, and also does not recalculate.
what am I missing?

pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Re: Manual looping support?

Postby pthegr8 » 17 Jun 2021

From the manual:
“The StarCalc() method of study class is called every time before the calculation starts.”
I could be wrong but I interpret this that the code in the StartCalc() method is being called on every tick, or on every close of every new bar. Depending on the setting. But that doesn't seem the case:

A simple example;
the following finds the Low of the last 15 bars, and labels it BarA.
This works using StartCalc() method, but it doesn't recalculate with new data on the chart. i have to stop and start the indicator to update.

Code: Select all

using System; using System.Drawing; using System.Linq; using PowerLanguage.Function; using System.Collections.Generic; using System.Windows.Forms; namespace PowerLanguage.Indicator{ [SameAsSymbol(true), SkipIdenticalTicks(true), UpdateOnEveryTick(true)] public class Test_BarA : IndicatorObject { [Input] public int Range_Pattern { get; set; } private int[] range = new int[2]; public int barA; public Test_BarA(object _ctx):base(_ctx) { Range_Pattern = 15; } protected override void Create() {} protected override void StartCalc() { range[1] = Bars.FullSymbolData.Count; range[0] = range[1]+1- Range_Pattern; barA = range[0]; for (int i = range[0]; i < range[1]; i++) { if (Bars.FullSymbolData.Low[-i] <= Bars.FullSymbolData.Low[-barA]) { barA = i; } } DrawText(Bars.FullSymbolData.Time[-barA], Bars.FullSymbolData.Low[-barA], "BARA"); } protected override void CalcBar() { } private void DrawText(DateTime barTime, double priceValue, string text) { ITextObject myText = DrwText.Create(new ChartPoint(barTime, priceValue), text); myText.Locked = true; } } }
then when I try to use the same code in the CalcBar() method, with one addition; to check if we're on the last bar of the chart, so it doesn't do the code for all the bars in the index, just only for the last bar:

Code: Select all

using System; using System.Drawing; using System.Linq; using PowerLanguage.Function; using System.Collections.Generic; using System.Windows.Forms; namespace PowerLanguage.Indicator{ [SameAsSymbol(true), SkipIdenticalTicks(true), UpdateOnEveryTick(true)] public class Test_BarA : IndicatorObject { [Input] public int Range_Pattern { get; set; } private int[] range = new int[2]; public int barA; public Test_BarA(object _ctx):base(_ctx) { Range_Pattern = 15; } protected override void Create() {} protected override void StartCalc() { } protected override void CalcBar() { range[1] = Bars.FullSymbolData.Count; range[0] = range[1]+1- Range_Pattern; barA = range[0]; if (Bars.LastBarOnChart) { for (int i = range[0]; i < range[1]; i++) { if (Bars.FullSymbolData.Low[-i] <= Bars.FullSymbolData.Low[-barA]) { barA = i; } } } DrawText(Bars.FullSymbolData.Time[-barA], Bars.FullSymbolData.Low[-barA], "BARA"); } private void DrawText(DateTime barTime, double priceValue, string text) { ITextObject myText = DrwText.Create(new ChartPoint(barTime, priceValue), text); myText.Locked = true; } } }

it gives me an Max bars forward error.
What am I missing?

pthegr8
Posts: 27
Joined: 30 Apr 2021
Has thanked: 1 time
Been thanked: 2 times

Re: Manual looping support?

Postby pthegr8 » 06 Jul 2021

Figured it out.
startcalc() method addresses the bar index different than calcbar() method.
for example, if you select 300 bars as data range;
in calcbar() the most recent bar is bar 0. and the oldest bar will be 299.
while in startcalc() the oldest bar is index 0, and the most recent bar is index 299.

as a side note, it would be nice to have a command to disable the looping through the index in calcbar()
I used another platform prior to MCN, and it had a command : autoloop=false so you could run your own loops.

I know you can use if (Bars.LastBarOnChart)
but that still will loop through your bars unnecessarily if you have an indicator that will only calculate when its on the LastBar.


Return to “MultiCharts .NET”