ML Engine
Version: v.2.0.0.0

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.MLEnginefield.
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:
- instantiate your indicators
- create
BaseSignal - initialize
MLEngine - 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:
- work only on the primary series
- ensure enough bars are loaded
- calculate
BaseSignal - use
MLSignalfor entries - 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 ContractsMax Contracts- applies:
Max Qty StepUse Qty Metrics Filter- returns
defaultQtywhen: - 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.