TensorFlow doesn't write .onnx files directly. The bridge is tf2onnx, a Microsoft-maintained converter that reads TensorFlow's SavedModel format and emits ONNX. This article covers the general TF-to-ONNX workflow for any architecture — dense, conv, sequence, mixed.
What's in this article
The version-pinned install
Use a fresh virtual environment with these versions. Other combinations work but break sporadically:
Why TF 2.10? It's the last version with a native Windows GPU build on PyPI — later versions require WSL2 for GPU acceleration. MetaQuotes' own ONNX tutorials use 2.10 for exactly this reason.
Save as SavedModel (not HDF5)
tf2onnx reads SavedModel format reliably. HDF5 (.h5) sometimes loses subclass model metadata. Always save SavedModel:
Run tf2onnx
From the command line:
The --opset 17 targets the ONNX opset version MT5 reliably supports in Build 5572. See the opset guide for the full reasoning.
Input signature: when to provide one
tf2onnx auto-detects the input signature from the SavedModel. Sometimes the detection picks up unwanted dynamic dimensions, or misses a dtype. Override explicitly:
This pins the shape exactly the way you want for MT5. None means dynamic (the batch dim); concrete numbers stay fixed.
Common conversion errors
ModuleNotFoundError: No module named 'tf2onnx'
You're in the wrong virtualenv. Activate the one with tf2onnx installed.
Unsupported op type: TFLite_Detection_PostProcess
You used a TFLite-specific op. Rewrite that part in regular TF or do post-processing on the MQL5 side.
Conversion succeeds but ONNX output diverges from TF output
Almost always batch normalization in training mode. Make sure model.trainable = False or that you're using tf.keras.Model.save after training (which fixes the mode).
"Failed to load SavedModel" on the convert step
The SavedModel was created with a different TF version. Re-save with TF 2.10 in the same environment used for conversion.