I guessed it was doing this because the underlying framework detected a line that was plotted below what is considered to be a safe minimum price. I followed the process recommended in the online documentation for OnCalculateMinMax() but frustratingly this just seemed to cause more problems.
Eventually I found the problem(s) and I will share them here in the hopes that it saves you going through the frustrating process of trying to figure it out. This is what it looks like (when I got it working):
They were two things that I needed to change:
- My indicator loads multiple time-frames of the same instrument, and this was causing havoc in the OnCalculateMinMax() function which I had copied directly from the example provided.
- The example provides a buffer of 50 ticks above and below the chart, which caused strangely scaled charts at different zoom scales
- Not use the standard Close.GetValueAt() because of the multiple data series that the indicator contains. Simply changing this to Closes[0].GetValueAt() solved that problem.
- Instead of adding a buffer as a number of ticks, I calculate the buffer as a percentage of the full price range (in this case 5%)
Here is the code which successfully handles auto-scaling of the multiple data series indicator:
public override void OnCalculateMinMax()
{
if (State != State.Historical)
{
try
{
// make sure to always start fresh values to calculate new min/max values
double tmpMin = double.MaxValue;
double tmpMax = double.MinValue;
// For performance optimization, only loop through what is viewable on the chart
for (int index = ChartBars.FromIndex; index <= ChartBars.ToIndex; index++)
{
// since using Close[0] is not guaranteed to be in sync
// retrieve "Close" value at the current viewable range index
double plotValue = Closes[0].GetValueAt(index);
// return min/max of close value
tmpMin = Math.Min(tmpMin, plotValue);
tmpMax = Math.Max(tmpMax, plotValue);
}
double buffer = (50 * TickSize); // default
if(buffer>(tmpMax-tmpMin)/20) buffer=(tmpMax-tmpMin)/20; //5% of price range
double lowbuffer = buffer;
// adjust by 4 diamonds
if(lowbuffer<last_diamond_height*4) lowbuffer=last_diamond_height*4;
// Finally, set the minimum and maximum Y-Axis values to the buffers (+/- 50 ticks from the primary close value by default)
MinValue = tmpMin - lowbuffer;
MaxValue = tmpMax + buffer;
}
catch(Exception ex)
{
Print("Error calculating max/min: " + ex.Message);
}
}

Comment