When you are testing your indicator, remember to test with both
CalculateBarOnClose = true and CalculateBarOnClose = false;
This has been the cause of so many weird bugs for me I thought I'd summarise.
Background
Bars are numbered from Left to Right.
The First bar in a series is 0, rising to the most recent bar = "n"
The number of the bar can be obtained using the Bars.CurrentBar property.
Most other properties also use this numbering scheme. Including ChartControl.FirstBarPainted & ChartControl.LastBarPainted these are really handy when overriding the PLOT method.
The DataSeries that hold the Bars are Indexed from Right to Left.
The most recent bar in a dataSeries has an Index of 0 eg: Close[0]. As you scroll left you move move toward the oldest bar eg: Close[ n].
To convert from one to the other
So the way you map the values in the data series (ie Close[n]) to the bar displayed on the screen is to subtract your index from CurrentBar eg: Close[CurrentBar - cntBar]
How CalculateBarOnClose hurts you.
If CalculateBarOnClose = false the CurrentBar property is the same as described above & it all works well.
Beware if CalculateBarOnClose = true.
The CurrentBar property is 1 less than it would be if CalculateBarOnClose = false. You need to change your algorithm to compensate for that.
This is because the trader has told you they don't want to see the bar that is forming. So there is 1 less bar you are supposed to draw. But the number of bars since you started are still the same. Its just the CurrentBar value is 1 less than the total number of bars. So implicitly your calculation becomes "(Close[ (CurrentBar-1) - cntBar]" & your index result of the rightmost, partially complete bar becomes "-1". This is invalid index value for the array. You are not supposed to access it nor display your indicator at that position. If you do, you'll see an error message in the log & your indicator will not display.
To prevent this issue always check with something like
if ((CurrentBar - cntBar) < 0) continue;
// ---< For each bar that is displayed on the screen >--- for(int cntBar = ChartControl.FirstBarPainted; cntBar <= ChartControl.LastBarPainted; cntBar++) { // if (!ChartControl.ShowBarsRequired && cntBar < BarsRequired) // continue; if ((CurrentBar - cntBar) < 0) continue; float x = ChartControl.GetXByBarIdx(cntBar); graphics.DrawString( CurrentBar.ToString(), textFont, textBrush, x, y3, stringFormat); graphics.DrawString( cntBar.ToString(), textFont, textBrush, x, y2, stringFormat); graphics.DrawString( (CurrentBar - cntBar).ToString(), textFont, textBrush, x, y, stringFormat); }
Dave