Skip to main content

Custom Plots

Demonstrates StrategyPlotIndicator for drawing custom plot lines on the chart. Two indicators are created: one overlaid on the price chart, and one on a separate panel below.

Source: [INSTALL PATH]/API/Samples/CustomPlots.cs Class: CustomPlots : MZpackStrategyBase

What It Covers

  • Subclassing StrategyPlotIndicator for custom plots
  • Overlay plots on the price chart
  • Panel plots below the chart (IsOnPanel = true)
  • Accessing footprint bar data (IFootprintBar) from a plot indicator
  • Configuring plot strokes, visibility, and panel height

Chart Overlay Indicator

CustomPlotsIndicator plots two lines on the price chart — one above bar highs, one below bar lows (intermittently):

class CustomPlotsIndicator : StrategyPlotIndicator
{
int c;

public CustomPlotsIndicator(MZpackStrategyBase strategy,
ISeries<double> input)
: base(strategy, input, new Series<double>[2]) // 2 plots
{
}

public override string IndicatorName() => "Custom Plots";

public override void BarUpdate()
{
if (__CurrentBar > 0)
{
int currBarIdx = __CurrentBar - 1;
// Plot 0: above bar high
Values[0][currBarIdx] = __High[1] + 2 * strategy.TickSize;

// Plot 1: below bar low (only 4 out of 8 bars)
c++;
if (c <= 4)
Values[1][currBarIdx] = __Low[1] - 2 * strategy.TickSize;
else if (c >= 8)
c = 0;
}
}
}

Panel Indicator

CustomPlotsOnPanelIndicator plots COT High/Low from footprint data on a separate panel:

class CustomPlotsOnPanelIndicator : StrategyPlotIndicator
{
public CustomPlotsOnPanelIndicator(MZpackStrategyBase strategy,
ISeries<double> input)
: base(strategy, input, new Series<double>[2])
{
}

public override string IndicatorName() => "Custom Plots on Panel";

public override void BarUpdate()
{
if (__CurrentBar > 0)
{
int currBarIdx = __CurrentBar - 1;
IFootprintBar bar;
if ((strategy as CustomPlots).FootprintIndicator
.FootprintBars.TryGetValue(currBarIdx, out bar))
{
Values[0][currBarIdx] = bar.COTHigh;
Values[1][currBarIdx] = bar.COTLow;
}
}
}
}

Configuration

Both indicators are configured in CreateIndicators:

// Overlay indicator
customPlotsIndicator = new CustomPlotsIndicator(this, Close);
customPlotsIndicator.Calculate = Calculate.OnBarClose;
customPlotsIndicator.Strokes[0] = new Stroke(Brushes.Red, 2);
customPlotsIndicator.Strokes[1] = new Stroke(Brushes.Green, 2);
customPlotsIndicator.Visible = true;

// Panel indicator
customPlotsOnPanelIndicator = new CustomPlotsOnPanelIndicator(this, Close);
customPlotsOnPanelIndicator.Calculate = Calculate.OnBarClose;
customPlotsOnPanelIndicator.IsOnPanel = true;
customPlotsOnPanelIndicator.PanelHeight = 400;
customPlotsOnPanelIndicator.IsUpperPanel = false;
customPlotsOnPanelIndicator.Strokes[0] = new Stroke(Brushes.DodgerBlue, 2);
customPlotsOnPanelIndicator.Strokes[1] = new Stroke(Brushes.Yellow, 2);
customPlotsOnPanelIndicator.Visible = true;

StrategyPlotIndicator Key Points

Property / MethodDescription
Constructor new Series<double>[N]Number of plot series
IndicatorName()Display name for the indicator
BarUpdate()Called on each bar close — write values to Values[n][barIdx]
Strokes[n]Plot line color and width
IsOnPaneltrue = render on separate panel, false = overlay on chart
PanelHeightPanel height in pixels (when IsOnPanel = true)
IsUpperPanelPanel position: above (true) or below (false) the chart
VisibleShow/hide the indicator
CalculateOnBarClose or OnEachTick

See Also