Developer Reference

Third-Party & Custom Indicator
Compatibility Guide

Fusion Indicators discovers and loads NinjaTrader® 8 indicators dynamically. Because NinjaTrader® 8 indicators are built on a standard SDK, Fusion can inspect their architecture and handle them directly. Third-party and custom indicators may also work, but compatibility depends on how they were built. Share this guide with your NinjaScript developer to ensure compatibility.

The Compatibility Matrix

Third-party and custom indicators may also work with Fusion, but compatibility depends on how they were built. Because their internal code is not available to us, Fusion cannot detect hidden dependencies or unconventional output patterns. The rules below describe what makes any indicator compatible or incompatible.

Compatible — Will Work

Registers at least one plot output using NinjaTrader®’s standard AddPlot() method. Fusion discovers registered outputs automatically at load time.

Accepts a standard input series (e.g., Close, Open, or another indicator’s output) via the generic Input property. This allows Fusion to feed data from upstream blocks directly into the indicator.

Relies only on the primary data source — the main bar series of the chart the indicator is applied to. No hidden secondary instrument or timeframe loading required.

Exposes meaningful outputs as registered AddPlot() values — including signal lines, trigger values, or secondary outputs that should be routable through the pipeline.

Incompatible — Will Not Work

No registered plot outputs — purely visual tools like bar timers or chart drawing tools that output no mathematical values. (Note: Fusion includes its own signal processors that replicate many time and bar-state capabilities.)

Hidden internal data series — indicators that internally call AddDataSeries() to load their own instruments or timeframes. Fusion cannot detect or manage dependencies it doesn’t know about, which can create data synchronization conflicts.

Non-series outputs — indicators that store results as plain scalar values (e.g., double SignalOutput) instead of indexable series (e.g., Series<double> SignalOutput). Fusion needs continuous bar-by-bar data feeds, not single-point snapshots.

Proprietary dependencies — indicators that rely on internal data providers, custom indicator chaining, or a custom bar type not in NinjaTrader®’s standard BarsPeriodType enum.

Black box architecture — indicators that calculate values but store results only in internal fields rather than registered plots. If the data isn’t exposed through the standard plot interface, Fusion cannot access it.

C# Pseudo-Code Examples

Share these patterns with your indicator developer. The compliant example shows exactly what Fusion requires. The non-compliant example shows the three most common causes of incompatibility.

✓ Compliant Pattern
// COMPLIANT: Fusion can read and route this indicator.
protected override void OnStateChange()
{
    if (State == State.SetDefaults)
    {
        Name = "Compliant Custom SMA";
        // ✓ Fusion discovers and routes this standard plot output
        AddPlot(Brushes.Blue, "SMA_Output");
    }
}

protected override void OnBarUpdate()
{
    if (CurrentBar < Period) return;
    // ✓ Uses the generic Input array — Fusion can pipe data
    // from any Math Block or Signal Processor into this slot.
    Value[0] = Input[0] * 1.5;
}
✗ Non-Compliant Pattern
// NON-COMPLIANT: Fusion cannot read or route this indicator.
protected override void OnStateChange()
{
    if (State == State.SetDefaults)
    {
        Name = "Non-Compliant Indicator";
        // ✕ NO AddPlot() HERE — Fusion discovers routable outputs
        // at load time by scanning registered plots. Without at least
        // one AddPlot() or a public Series<double> property, this
        // indicator will appear in Fusion's scanner but expose no outputs.
    }
    if (State == State.Configure)
    {
        // ✕ INCOMPATIBLE: Fusion cannot detect or manage hidden internal series.
        // This causes data sync conflicts with Fusion's pipeline timing.
        AddDataSeries(Data.BarsPeriodType.Minute, 5);
    }
}

protected override void OnBarUpdate()
{
    // ✕ INCOMPATIBLE: Hardcoding Close prevents Fusion from
    // routing Math Block or Signal Processor output into this indicator.
    double myValue = Close[0] * 1.5;

    // ✕ INCOMPATIBLE: Plain double field — NOT a Series<double>.
    // Fusion reads continuous data feeds via indexable Series<double> properties.
    // A plain double stores only the current bar's value; it cannot be
    // used as a routable pipeline output. If this were declared as
    // public Series<double> CustomOutput, Fusion could read it via reflection.
    double CustomHiddenOutput; // NOT Series<double> — Fusion cannot route this.
    CustomHiddenOutput = myValue;
}

Data Synchronization & Calculate Mode

The following technical notice applies to all multi-timeframe and secondary series configurations within the Global Data Series Manager.

A Note on Secondary Data Series & Calculate Mode

When utilizing secondary data series via the Global Data Series Manager (GDSM), Fusion reads the last completed bar value from each series, mapped by timestamp to the primary chart.

The primary chart’s Calculate Mode governs all secondary series. If your primary chart is set to Calculate On Bar Close, your secondary series will also calculate on bar close. This is standard NinjaTrader® behavior, not a Fusion-specific restriction.

Edge cases involving mixed calculate modes (e.g., a tick-updating secondary series on a bar-close primary chart) are not currently supported and may produce unexpected synchronization results.