Skip to content

ML Engine

Version: v.2.0.0.0

ML Engine

Description

Universal ML engine for directional signal filtering (chart and strategies) and optional contract quantity forecasting (strategies only). Direction models use VWAP, Slope, Cumulative delta, MACD, ATR, GAP, and Commitment of Traders (COT) features.

Important

For probability forecasting and for this indicator to work, you must add to Input Series the data series of another indicator that provides directional signals: > 0 for long and < 0 for short. The ML Engine does not work on its own; it only works in combination with such an indicator.

This indicator requires an active NinjaTrader Order Flow + subscription.

Commitment of Traders (COT)

The engine loads the built-in COT indicator (Noncommercial Net, Commercial Net, Nonreportable Positions Net) and feeds normalized COT ratios into the direction ensemble together with VWAP, Slope, Delta, MACD, ATR, and GAP.

Enable COT in NinjaTrader global settings so reports download automatically:

Control Center → Tools → Settings → Market Data — turn on Download COT data at startup.

If COT values are missing or invalid, COT inputs are skipped for that bar; direction training and MLSignal inference continue with the remaining features.

Properties

ML Engine

  • Enable Logging [default: false] — Print() to Output window and write MLEngine.log.
  • Show Metrics Table [default: true] — Show ensemble metrics table on chart.
  • Show Probability [default: true] — Show probability label on chart.
  • Use Metrics Filter [default: false] — Block signals if metrics below thresholds.
  • Use Qty Metrics Filter [default: false] — Block quantity forecast if quantity metrics below thresholds.
  • Use Auto Weights [default: true] — Auto weight models by AUC and F1.
  • Use Qty Auto Weights [default: true] — Auto weight quantity models by R2.
  • Min Probability [default: 0.5, range: 0–1] — Minimum ensemble probability to pass signal.
  • Bars Ahead [default: 60, range: 1–∞] — Bars ahead used for labeling training samples.
  • Records Before Retrain [default: 10, range: 1–∞] — Minimum samples before retraining.
  • Use Quantity Forecast [default: true] — Activates a model ensemble to forecast the number of contracts per trade.
  • Min Contracts [default: 1, range: 1–∞] — Minimum contracts allowed for quantity forecast.
  • Max Contracts [default: 10, range: 1–∞] — Maximum contracts allowed for quantity forecast.
  • Max Qty Step [default: 1, range: 1–∞] — Maximum contract change per recommendation (0 = no step limit).

Direction Ensemble Models

  • Use LightGbm [default: true] — Enable LightGbm classifier.
  • Use FastTree [default: true] — Enable FastTree classifier.
  • Use FastForest [default: true] — Enable FastForest classifier.
  • Use SDCA LogReg [default: true] — Enable SDCA logistic regression.
  • Use LBFGS LogReg [default: true] — Enable LBFGS logistic regression.
  • Use Averaged Perceptron [default: true] — Enable Averaged Perceptron classifier.
  • Use SGD Calibrated [default: true] — Enable SGD calibrated classifier.

Quantity Ensemble Models

  • Use Qty LightGbm [default: true] — Enable LightGbm quantity regressor.
  • Use Qty FastTree [default: true] — Enable FastTree quantity regressor.
  • Use Qty FastForest [default: true] — Enable FastForest quantity regressor.
  • Use Qty SDCA [default: true] — Enable SDCA quantity regressor.
  • Use Qty FastTree Tweedie [default: true] — Enable FastTree Tweedie quantity regressor.
  • Use Qty OGD [default: true] — Enable Online Gradient Descent quantity regressor.
  • Use Qty LBFGS Poisson [default: true] — Enable LBFGS Poisson quantity regressor.

Direction Feature Params

  • (Slope) Start Bars Ago [default: 14, range: 1–∞] — Start bar for VWAP slope.
  • (Slope) End Bars Ago [default: 0, range: 0–∞] — End bar for VWAP slope.
  • (Delta) Type [default: BidAsk] — Cumulative delta calculation type.
  • (Delta) Period [default: Session] — Cumulative delta period.
  • (Delta) Size Filter [default: 0, range: 0–∞] — Delta size filter (0 = off).
  • (VWAP) Resolution [default: Tick] — Data resolution for VWAP.
  • (VWAP) Standard deviations [default: Two] — VWAP standard deviations.
  • (VWAP) SD1/SD2/SD3 Multiplier [default: 0.75, 1.5, 3, range: 0.001–∞] — VWAP SD multipliers.
  • (ATR) Period [default: 14, range: 1–∞] — ATR period for features.
  • (MACD) Fast/Slow/Smooth [default: 12, 26, 9, range: 1–∞] — MACD periods.
  • (Gap) Session Start Time [default: 08:30] — Session start for gap calculation.
  • Signal Offset Bars [default: 0, range: 0–∞] — Bars ago to read input signal.

ML Metrics Filter

  • Min AUC [default: 0.0, range: 0–1] — Minimum AUC required to pass metrics filter.
  • Min F1 [default: 0.0, range: 0–1] — Minimum F1 score required to pass metrics filter.
  • Min Accuracy [default: 0.0, range: 0–1] — Minimum accuracy required to pass metrics filter.
  • Min Precision [default: 0.0, range: 0–1] — Minimum precision required to pass metrics filter.
  • Min Recall [default: 0.0, range: 0–1] — Minimum recall required to pass metrics filter.
  • Min Qty R2 [default: -1.0, range: -∞–∞] — Minimum quantity ensemble R2 required to use quantity forecast.
  • Max Qty MAE [default: 1000000.0, range: 0–∞] — Maximum quantity ensemble MAE allowed to use quantity forecast.

Table Style

  • Table position [default: TopLeft] — Corner of chart where metrics table is drawn.
  • Table font — Font family for metrics table.
  • Table text color — Text color for metrics table.
  • Table background — Background fill for metrics table.
  • Table outline — Border/outline color for metrics table.
  • Table opacity [default: 75, range: 0–100] — Opacity table (0-100).

Probability Style

  • Probability font — Font family for probability labels.
  • Probability color — Text color for probability labels on chart.
  • Probability offset (ticks) [default: 0, range: -∞–∞] — Vertical offset in ticks.

For developers: using ML Engine in strategies


Below is a complete step-by-step example of how to integrate ML Engine into your own NinjaTrader strategy, use MLSignal for directional filtering, and optionally enable Quantity Forecast for adaptive contract sizing.


1. Create a new strategy

Create a new NinjaScript Strategy (example: MLEngineTest) inside the NinjaTrader.NinjaScript.Strategies namespace.

using NinjaTrader.NinjaScript;
using NinjaTrader.NinjaScript.Indicators;

namespace NinjaTrader.NinjaScript.Strategies
{
    public class MLEngineTest : Strategy
    {
        // ...
    }
}

2. Declare fields for base signal and ML Engine

Inside the strategy class, add:

  • any indicators that will generate your base directional signal (e.g. EMAs);
  • a Series<double> for that base signal;
  • an Indicators.ASF.MLEngine field.
private EMA EMA1;
private EMA EMA2;

private Series<double> BaseSignal = null;
private Indicators.ASF.MLEngine ml = null;

3. Add required data series (State.Configure)

ML Engine requires additional Tick(1) and Day(1) series.

These series are mandatory and must be added in State.Configure.

else if (State == State.Configure)
{
    AddDataSeries(BarsPeriodType.Tick, 1);
    AddDataSeries(BarsPeriodType.Day, 1);
}

4. Create ML Engine (State.DataLoaded)

In State.DataLoaded:

  1. instantiate your indicators
  2. create BaseSignal
  3. initialize MLEngine
  4. optionally add the indicator to the chart
else if (State == State.DataLoaded)
{
    EMA1 = EMA(Close, 14);
    EMA2 = EMA(Close, 50);

    BaseSignal = new Series<double>(this, MaximumBarsLookBack.Infinite);

    ml = MLEngine(
        BaseSignal,                                      // 1. ISeries<double> input - Main input series (price or custom signal)

        // === Logging & Display Settings ===
        true,                                            // 2. enableLogging
        true,                                            // 3. showMetricsTable
        true,                                            // 4. showProbabilityOnChart
        true,                                            // 5. useMetricsFilter
        true,                                            // 6. useQtyMetricsFilter      ← New: Filter quantity models by metrics
        true,                                            // 7. useAutoWeights
        true,                                            // 8. useQtyAutoWeights        ← New: Auto weights for quantity prediction

        // === Core ML Settings ===
        0.5,                                             // 9.  mLMinProbabilityThreshold
        60,                                              // 10. barsAhead - Forecast horizon in bars
        10,                                              // 11. recordsBeforeRetrain

        // === Quantity Forecast Settings ===
        true,                                            // 12. useQuantityForecast     ← New
        1,                                               // 13. minContracts
        10,                                              // 14. maxContracts
        1,                                               // 15. maxQtyStepPerTrade

        // === Directional ML Models ===
        true,                                            // 16. useLightGbm
        true,                                            // 17. useFastTree
        true,                                            // 18. useFastForest
        true,                                            // 19. useSdcaLogisticRegression
        true,                                            // 20. useLbfgsLogisticRegression
        true,                                            // 21. useAveragedPerceptron
        true,                                            // 22. useSgdCalibrated

        // === Quantity ML Models ===
        true,                                            // 23. useQtyLightGbm
        true,                                            // 24. useQtyFastTree
        true,                                            // 25. useQtyFastForest
        true,                                            // 26. useQtySdca
        true,                                            // 27. useQtyFastTreeTweedie
        true,                                            // 28. useQtyOnlineGradientDescent
        true,                                            // 29. useQtyLbfgsPoissonRegression

        // === Slope Features ===
        0,                                               // 30. slopeStartBarsAgo
        0,                                               // 31. slopeEndBarsAgo

        // === Cumulative Delta ===
        CumulativeDeltaType.BidAsk,                      // 32. deltaType
        CumulativeDeltaPeriod.Session,                   // 33. deltaPeriod
        0,                                               // 34. deltaSizeFilter

        // === VWAP Settings ===
        VWAPResolution.Tick,                             // 35. resolution
        VWAPStandardDeviations.Two,                      // 36. standardDeviations
        0.75,                                            // 37. sD1Multiplier
        1.5,                                             // 38. sD2Multiplier
        3.0,                                             // 39. sD3Multiplier

        // === ATR + MACD ===
        14,                                              // 40. aTRPeriod
        12,                                              // 41. mACDFast
        26,                                              // 42. mACDSlow
        9,                                               // 43. mACDSmooth

        // === Session & Offset ===
        DateTime.Parse("08:30", System.Globalization.CultureInfo.InvariantCulture), // 44. sessionStartTime
        0,                                               // 45. signalOffsetBars

        // === Model Quality Thresholds ===
        0.0,                                             // 46. minAuc
        0.0,                                             // 47. minF1
        0.0,                                             // 48. minAccuracy
        0.0,                                             // 49. minPrecision
        0.0,                                             // 50. minRecall
        -1.0,                                             // 51. minQtyR2               ← New: Minimum R² for quantity models
        1000000.0,                                       // 52. maxQtyMAE              ← New: Maximum Mean Absolute Error for quantity

        // === Table UI Settings ===
        Indicators.ASF.MyMLEngineEnums.TableTextPosition.TopLeft, // 53. tablePosition
        new SimpleFont("Consolas", 11)                       // 54. tableFont
        {
            Size = 11,
            Bold = false
        },
        Brushes.Silver,                                  // 55. tableTextBrush
        Brushes.Black,                                   // 56. tableBackgroundBrush
        Brushes.Transparent,                             // 57. tableOutlineBrush
        75,                                              // 58. tableOpacity (0-100)

        // === Probability Text Settings ===
        new SimpleFont("Consolas", 11)                   // 59. probFont
        {
            Size = 11,
            Bold = false
        },
        Brushes.DodgerBlue,                              // 60. probBrush
        0                                                // 61. probVerticalOffsetTicks
    );

    AddChartIndicator(ml);
}

You can replace these values with your own strategy properties.

To enable adaptive contract sizing, pass UseQuantityForecast = true.


5. Feed BaseSignal and use MLSignal (OnBarUpdate)

Inside OnBarUpdate:

  1. work only on the primary series
  2. ensure enough bars are loaded
  3. calculate BaseSignal
  4. use MLSignal for entries
  5. optionally use GetRecommendedContracts() for dynamic sizing

Example using EMA cross logic:

protected override void OnBarUpdate()
{
    if (BarsInProgress != 0)
        return;

    int requiredBars = 21 + SignalOffsetBars;

    // Ensure all series have enough bars
    if (CurrentBars[0] < requiredBars ||
        CurrentBars[1] < requiredBars ||
        CurrentBars[2] < 1)
        return;

    // Base directional signal
    BaseSignal[0] =
        CrossAbove(EMA1, EMA2, 1) ?  1 :
        CrossBelow(EMA1, EMA2, 1) ? -1 :
        0;

    // ML-filtered long entry
    if (ml.MLSignal[0] > 0)
    {
        int qty = ml != null
            ? ml.GetRecommendedContracts(DefaultQuantity)
            : DefaultQuantity;

        EnterLong(qty, "Long");
    }

    // ML-filtered short entry
    if (ml.MLSignal[0] < 0)
    {
        int qty = ml != null
            ? ml.GetRecommendedContracts(DefaultQuantity)
            : DefaultQuantity;

        EnterShort(qty, "Short");
    }
}

This same pattern can be reused with any custom strategy logic.

You only need to output:

  • positive values for longs
  • negative values for shorts
  • zero for neutral/no signal

into BaseSignal[0].


6. Quantity Forecast (optional)

When UseQuantityForecast is enabled, ML Engine can dynamically increase or decrease contract quantity over time.

The quantity model uses:

  • directional model accuracy
  • strategy trade performance snapshots

to determine whether position size should scale up or down.

GetRecommendedContracts(defaultQty):

  • clamps size between:
  • Min Contracts
  • Max Contracts
  • applies:
  • Max Qty Step
  • Use Qty Metrics Filter
  • returns defaultQty when:
  • quantity forecast is disabled
  • not enough training data exists yet

7. Train quantity model from closed trades (OnPositionUpdate)

After a trade closes and the strategy becomes flat, push strategy performance into the ML Engine.

This allows the quantity model to continuously learn from completed trades.

protected override void OnPositionUpdate(
    Position position,
    double averagePrice,
    int quantity,
    MarketPosition marketPosition)
{
    if (position.MarketPosition == MarketPosition.Flat)
    {
        if (UseQuantityForecast && ml != null)
        {
            ml.UpdateStrategySnapshot(
                SystemPerformance.AllTrades.TradesPerformance);
        }
    }
}

The first calls build the internal strategy snapshot.

After enough closed trades accumulate, labeled quantity samples are generated automatically and the quantity model begins adapting position size dynamically.


Notes

  • MLSignal[0] is the final ML-filtered directional output.
  • BaseSignal[0] is always your raw strategy logic before ML filtering.
  • Quantity Forecast is completely optional and can be disabled.
  • ML Engine works best after enough historical trades exist for training.
  • Any directional strategy can be connected to ML Engine by feeding a signed signal into BaseSignal.

Version Change History

v.1.0.0.0

1) Initial release: direction ensemble filter, metrics table, probability labels.

v.2.0.0.0 (May 25, 2026)

1) Direction forecast: added COT (Commitment of Traders) features.

2) Added contract quantity forecast module.