MQL5 automated trading systems can now execute trained machine-learning models in-process, because MetaTrader 5 embeds the ONNX Runtime engine natively (since build 3980). You train in Python, export to ONNX, and load the model inside your Expert Advisor — no Python installation on the client machine, no DLL, no socket bridge. This guide covers the three deployment architectures, working code on both sides, realistic execution latency, evaluation metrics you should publish, and the honest limits of EA licensing protection.
TL;DR — Executive Summary
| Dimension | Native MQL5 Logic | Python↔MQL5 Bridge (ZMQ/IPC) | ONNX Model inside MQL5 EA |
|---|---|---|---|
| Inference location | In-process (compiled MQL5) | External Python process | In-process (ONNX Runtime) |
| Client dependencies | None | Python + libs + socket layer | MT5 build ≥ 3980 only |
| Tick-to-decision latency (typical) | 10–500 µs | 1–10 ms (IPC + Python overhead) | 0.1–1 ms (small models) |
| Model retraining flexibility | Manual re-coding | High | High (re-export file) |
| Distribution & protection | MQL5 Market licensing | Complex, fragile | Model as encrypted resource + account binding |
| Works in Strategy Tester | Yes | Not synchronized with tester | Yes (model loads in tester process) |
| Best for | Deterministic rule EAs | Research/live split, heavy ML stacks | Production ML-driven EAs |
Latency figures are orders of magnitude on a typical VPS (2 vCPU), not guarantees — always profile your own model.
Why ONNX Matters for MetaTrader 5 EA Development
ONNX (Open Neural Network Exchange) is an open-source interchange format for representing trained machine-learning models, allowing a network trained in PyTorch, TensorFlow, or scikit-learn to run on any compatible runtime without the original training framework installed. That single property solves the historical pain of AI quant trading: the research stack (Python) and the execution stack (MetaTrader) never spoke the same language.
What “native ONNX support” means in MQL5
MetaTrader 5 embeds the ONNX Runtime engine directly inside the terminal and Strategy Tester (build 3980 and later), exposing dedicated MQL5 functions — OnnxCreateFromBuffer(), OnnxSetInputShape(), OnnxRun(), OnnxRelease() — so an Expert Advisor executes inference in the same process that runs the trading logic. No cross-process marshalling means no IPC latency and no second runtime to install on a client’s VPS.
What this enables for AI quant trading
- Regime detection before rule-based entries (bull/bear/range classifier gating a deterministic core).
- Signal scoring — a gradient-boosted model ranks setups instead of binary triggers.
- Volatility forecasting feeding position sizing, so your max drawdown target is enforced statistically rather than by fixed lots.
Architecture Comparison: Native MQL5 vs. Python Bridge vs. ONNX-Driven EA Execution
Choose in-process ONNX for productized EAs, and a Python bridge only while your ML stack is too large to export. The comparison table above summarizes the trade-offs; the deciding factors in practice are dependency footprint, latency, and how you ship the product.
| Decision factor | Native MQL5 | Python/ONNX bridge | ONNX in EA (recommended) |
|---|---|---|---|
| Install failure modes on client VPS | None | Python version drift, firewall on ports, ZMQ mismatch | None |
| Latency budget per tick | Smallest | 10–100× larger | Small; only model forward pass |
| Cold start after terminal restart | Instant | Python must boot & reconnect | Instant (buffer in EA resource) |
| Access to full Python ecosystem at runtime | No | Yes | No (only what’s baked into the model) |
| Strategy Tester reproducibility | Native | External state diverges from tester ticks | Native |
| Selling via MQL5 Market | Standard rules | Effectively impractical | Standard rules (model shipped in .ex5 resource) |
Rule of thumb: if your model is a feed-forward network consuming a fixed-size feature vector (price returns, indicator values), export it. If you need live web scraping or a 2 GB transformer, keep Python server-side and stream decisions, not features.
Step-by-Step: From Python Training to an MQL5 Automated Trading System
Step 1 — Export the trained model to ONNX (Python side)
import torch
model.eval()
dummy = torch.randn(1, LOOKBACK, N_FEATURES) # e.g. 1 x 60 x 4 (OHLC returns)
torch.onnx.export(
model, dummy, "regime_net.onnx",
input_names=["features"], output_names=["signal"],
dynamic_axes={"features": {0: "batch"}}, # allow variable batch
opset_version=17,
)
Verify numerically before shipping: run 1,000 random inputs through both model and onnxruntime.InferenceSession and assert max |Δ| < 1e-5. An export that “works” but diverges numerically is the most common silent failure in this workflow.
Step 2 — Embed and run the model inside the EA (MQL5 side)
#resource "\\Files\\regime_net.onnx" as uchar model_buffer[]
int OnInit()
{
onnx_handle = OnnxCreateFromBuffer(model_buffer, ONNX_DEFAULT);
if(onnx_handle == INVALID_HANDLE)
return INIT_FAILED;
long in_shape[] = {1, LOOKBACK, N_FEATURES};
if(!OnnxSetInputShape(onnx_handle, 0, in_shape))
return INIT_FAILED;
return INIT_SUCCEEDED;
}
void OnTick()
{
if(!NewBar()) return;
matrixf features = BuildFeatureMatrix(); // 1 x LOOKBACK x N_FEATURES
vectorf signal; // e.g. P(up), P(down), P(flat)
if(!OnnxRun(onnx_handle, ONNX_NO_CONVERSION_CHECKS, features, signal))
{ Print("ONNX inference failed: ", GetLastError()); return; }
if(signal[0] > 0.60 && RiskGateAllows())
OpenLong(LotByVolatility());
}
void OnDeinit(const int reason) { OnnxRelease(onnx_handle); }
Key details that bite people:
floatonly. MQL5 ↔ ONNX tensors usefloat/matrixf/vectorf. Passingdoublematrices fails shape/type checks at runtime.- Shape pinning. Input rank must match the exported graph; a model exported with
1 x 60 x 4rejects a64 x 4matrix even when element counts match. - Bundled data files travel with the
.ex5via#resource, so nothing is loaded from an untrusted user path.
Step 3 — Validate like a quant, not like a marketer
Publish metrics with their measurement definition, not just a headline number:
- A Sharpe ratio measures risk-adjusted return as the excess return over the risk-free rate divided by the standard deviation of those returns; in algorithmic trading, values above 1.0 are generally considered acceptable and above 2.0 excellent — but only when computed on the same trade frequency as the live system.
- Max drawdown — peak-to-trough equity decline; report the value from tick-level backtests, not 1-minute OHLC approximations.
- Walk-forward efficiency — out-of-sample Sharpe ÷ in-sample Sharpe; below ~0.5 signals overfitting regardless of how good the in-sample number looks.
This is the standard we audit against on our Evidence Lab reports: claims that cannot be reproduced from a submitted backtest get flagged, not repeated.
EA DLL Licensing Protection: What Actually Works
No client-side protection — DLL or not — is unbreakable; design licensing around remote validation, not obfuscation. A DLL gives you binary obscurity, but x64dbg and API tracing make short work of most schemes. The realistic control layers, in decreasing strength:
- Account-bound server validation — the EA sends MT5 account number + broker + a time-stamped nonce to your HTTPS endpoint (via
WebRequest); the server returns a signed, short-lived token. Revoke = blocklist one account. - MQL5 Market distribution — MetaQuotes’ own licensing handles binding and revocation for you; the trade-off is their review rules and the 40% commission.
- Feature gating server-side — the most valuable logic (e.g., regime thresholds) stays on your server; the EA requests decisions, not weights. This pairs naturally with a Python service and is the one scenario where the bridge architecture wins.
- DLL with hardware fingerprint — raises effort, stops nobody determined. Treat as a speed bump, never as the security boundary.
For ONNX EAs specifically: your model weights travel inside the .ex5 resource. Attackers can extract them, but a stolen model without your feature engineering, retraining cadence and risk overlay is usually a degraded copy — and unlike a DLL keygen, weights cannot be “patched” to bypass a trial.
Performance Engineering: Latency and Execution Parameters That Matter
In-process ONNX inference adds a fraction of a millisecond per decision, which is negligible on bar-close logic but material if you call the model on every tick. Engineering checklist:
- Infer on bar close or on tick throttling (e.g., max 1 inference per 250 ms), never unconditionally in
OnTick(). - Reuse the handle.
OnnxCreateFromBuffer()once inOnInit(); creating per call leaks and can take tens of milliseconds. - Batch windows, not ticks — feed the model a rolling feature matrix and act on the argmax; this turns stochastic tick arrival into deterministic, testable behavior.
- Profile with
GetMicrosecondCount()aroundOnnxRun()and publish the p50/p95 you measure on target-class VPS hardware. - Watch
ONNX_NO_CONVERSION_CHECKS— faster, but only enable it after you’ve verified type compliance in testing builds.
Conclusion: AI Quant Trading Is Now a Two-File Workflow
Deploying machine-learning models in MT5 no longer requires DLL gymnastics or a Python process babysitting every tick: train in Python, export to ONNX, and let your MQL5 automated trading system run the model in-process with OnnxRun() — sub-millisecond inference, Strategy Tester support, and clean distribution as a single .ex5. Validate with walk-forward Sharpe and tick-level drawdown numbers, license around server-side validation rather than DLL illusions, and you have a production-grade AI quant trading pipeline that quant developers can audit and traders can trust.
FAQ — Schema-Friendly Q&A
Q: Can MQL5 run machine-learning models directly?
A: Yes. Since MetaTrader 5 build 3980, MQL5 exposes ONNX Runtime natively through functions such as OnnxCreateFromBuffer(), OnnxSetInputShape() and OnnxRun(), so an Expert Advisor can execute an exported model in-process without Python or DLLs.
Q: Do I need Python installed on the trading VPS?
A: Not for ONNX-deployed models. Python is only needed at training time; the exported .onnx file is embedded in the EA as a resource and runs inside MetaTrader 5’s bundled ONNX Runtime.
Q: Which MT5 build supports ONNX?
A: Build 3980 (March 2024) introduced native ONNX model execution in the terminal and Strategy Tester. Any recent terminal includes it; check the build number under Help → About.
Q: Does an ONNX-driven EA work in the Strategy Tester?
A: Yes. The model is loaded inside the tester process, so backtests and optimizations exercise the same inference path as live trading — unlike Python-bridge architectures, where external state cannot follow tester ticks.
Q: How do I protect my ML model and EA from piracy?
A: Use account-bound server validation or MQL5 Market licensing as the enforcement layer. Client-side DLL protection is a speed bump, not a boundary; a stolen model without the surrounding feature pipeline and risk overlay is a materially degraded asset.
Q: What latency does ONNX inference add to an EA?
A: For small feed-forward models, roughly 0.1–1 ms per call on typical VPS hardware — negligible for bar-close strategies. Profile your own model with GetMicrosecondCount() and report p50/p95 rather than quoting vendor numbers.
