EA Generate & Compile
Turns the finished run into compile-ready MQL5 that mirrors the Python engine expression for expression, compiles it with MetaEditor, and copies the binary into the terminal.
What this stage does
gen_ea.py --engine lr --symbol XAUUSD --tf M5 --all9
# the 24-hour variant, tagged so it cannot overwrite the above
gen_ea.py --engine lr --symbol XAUUSD --tf M5 --all9 --no-hours --tag 24X
<root>/<folder>/summary.json and configs.json
— the slot parameters, features and magic numbers.
best_hours.json, or empty if --no-hours was given.
The resolution order is strict — see below.
.ex5 into the selected terminal's
MQL5\Experts folder.
Choosing what to emit
| Flag | Emits | Slots |
|---|---|---|
--all9 | One portfolio EA for the canonical nine sets | 9 |
--all6 | One portfolio EA for the first six sets | 6 |
--per-set | One EA per feature set | 5 each |
--set <name> | One EA for a single set | 5 |
--set all | An EA for every per-set result on disk | 5 each |
Filenames
# portfolio EA
strategies_lr_m5/all9/FxMath_AST_allstar_ALL9_M5.mq5
# per-set EA
strategies_lr_m5/base9/FxMath_BAS_base9_LR_M5.mq5
# with a tag
strategies_lr_m5/all9/FxMath_AST_allstar_ALL9_24X_M5.mq5
# non-XAUUSD symbols get the symbol in the suffix
strategies_dowjones30_m5/all9/FxMath_AST_allstar_ALL9_DOWJONES30_M5.mq5
AST stands for the allstar build; the per-set name uses the set's
abbreviation. For XAUUSD the timeframe suffix is just _M5; for any other
symbol it is _<SYMBOL>_<TF> so files from different instruments
cannot collide.
--tag for a variant
The tag is inserted before the timeframe suffix. Without it, a second build of the
same portfolio overwrites the first — and you lose the ability to compare a
hours-baked EA against a 24-hour one, or to A/B two configurations.
The hours resolution order
Each slot's InpSlot<N>Hours value is resolved in this strict order, first match wins:
HOURS_DISABLE--no-hours. Forces every slot to "" (24 hours). Checked first, so a stale hours file cannot defeat it.(tf, set) → spec map, used by the study scripts to test specific windows.<OUT_ROOT>/best_hours.jsonbest_windows[0].spec — the top-ranked window.best_hours.json is absent but a known-good default exists.best_hours.json is missing, an XAUUSD build will quietly use the
hardcoded table rather than 24 hours. That is usually fine, but it means the file
you generated does not reflect the run you just completed. Confirm
best_hours.json exists before generating, or use
--no-hours to be explicit.
What the generated EA contains
| Section | Purpose |
|---|---|
| Header block | Copyright, version, description, and a //| Data: <file> | line recording which CSV the run was built from. |
| Compile-time constants | N_FEATURES, FEATURE_LOOKBACK, MAX_TRAIN, MAX_SLOTS, TRADE_TF, and #define LAM 0.001 — the last one annotated as needing to match the Python engine. |
SlotConfig struct | Magic, slMult, rr, trainingBars, retrainInterval, lookaheadBars, learning rates, maxIter, thresholds. |
SlotState struct | Weights, bias, feature mean/std, the training buffer, model-trained flag, bars-since-train, last probability and signal, and the 24-entry hourOk[] array. |
ParseHours() | An exact MQL5 mirror of the Python parser, including wrap-around ranges. |
| Per-slot inputs | InpSlot<N>Enable, InpSlot<N>Lot, InpSlot<N>Hours. |
ComputeFeaturesAt() | The feature primitives, emitted as MQL5 expressions that mirror feature_sets.py. For a portfolio EA this is a switch dispatching into each set's own expression block. |
| The LR implementation | Sigmoid, standardisation, batch gradient descent with L2, and the online momentum step — matching the engine's update rules. |
| Trading loop | Per-bar feature computation, hour gate, per-slot probability and signal, position management with SL/TP, and magic+symbol-matched position scanning. |
Two details worth knowing
TRADE_TF is compiled in as a constant, so the EA reads its own timeframe's
bars regardless of which chart it is attached to. Attaching an M5 EA to an H1 chart
does not change its behaviour — which is convenient, but means a casual look at the
chart tells you nothing about what the EA is actually reading.
MAX_TRAIN = 1800, sized to cover the largest searched
training_bars (1500) plus the largest lookahead (8) plus
FEATURE_LOOKBACK (51) = 1559, with headroom. The same 51-bar lookback is
mirrored in the data validator's trainability check.
MetaEditor's two traps
.ex5
must exist, be newer than the previous build, and the log must report
0 errors.
The subtle half: when a build fails outright, MetaEditor still writes a fresh
0 errors log next to the old
.ex5. A log-only check would report success. That is why mtime is
checked as well as the log contents.
N errors, M warnings summary is taken from the last match in
the file — because included header files can print their own summary before the final
one, and reading the first would report the wrong count.
The compile log is shown verbatim on the EA page, with the real diagnostics also extracted into a table of severity / code / file / line / message. The raw log is what you want when something fails for an unexpected reason.
Deployment
Deployment copies the compiled .ex5 into the selected terminal's
MQL5\Experts folder. Getting the right folder is the whole difficulty,
because two MetaTrader installs on the same machine keep entirely separate
%APPDATA% data directories.
The Settings page pairs each install with its data directory by reading that directory's
origin.txt and shows the exact MQL5\Experts path that
deployment will target. That path is the thing to verify when an EA compiles
successfully but does not appear.
The staleness check on the EA page
The EA page is the one place where staleness is treated as an error, not a warning. There are two reasons, and both are about accidentally trading something you did not test.
| Condition | Verdict |
|---|---|
.ex5 older than its .mq5 |
stale — the binary does not correspond to the source. You are looking at a build of older code. |
An .ex5 with the same name exists elsewhere at a different size |
warning naming both paths — identically-named binaries from earlier runs are the single easiest way to backtest the wrong EA. |
Progress output
hours filter DISABLED: every slot gets InpSlot<N>Hours = "" (trade 24x)
EA: strategies_lr_m5/all9/FxMath_AST_allstar_ALL9_M5.mq5
EA: strategies_lr_m5/base9/FxMath_BAS_base9_LR_M5.mq5 (3921 lines)
skip all6: no summary under strategies_lr_m5/all6
compiling with MetaEditor ...
0 errors, 0 warnings
-> strategies_lr_m5/all9/FxMath_AST_allstar_ALL9_M5.ex5
deploying to MQL5\Experts ...
copied to C:\Users\...\MetaQuotes\Terminal\D0694EE...CE8\MQL5\Experts
Nothing generated. is not an error
If no portfolio folder was found, the generator prints
Nothing generated. and returns successfully. So a
green-looking run with no output is possible. Check that the folder you asked for
actually exists and has a summary.json.
The Expert Advisor page
best_hours.json) or 24-hour. The 24-hour option emits InpSlot<N>Hours = "" on every slot and tags the file 24X so both variants coexist..mq5 and shows the line count..ex5 into the selected terminal's MQL5\Experts..ex5 elsewhere in the repository whose name collides with a local one.Checkpoint
- The compile reported 0 errors, 0 warnings.
- The
.ex5exists and is newer than the.mq5— no STALE badge. - No colliding binaries are listed, or you know which one is which.
- The deploy target is the
MQL5\Expertspath of the terminal you actually use. - You generated the 24-hour variant too, if you plan to compare it.
| Symptom | Cause | Fix |
|---|---|---|
| "MetaEditor64.exe not found" | The selected terminal folder is wrong or the terminal is not installed. | Settings → MetaTrader 5 → Browse to the folder containing metaeditor64.exe. |
| Compile reports failure but the log says "0 errors" | Old log, old .ex5, or a stale build detected by the mtime check. |
Delete the .ex5 and the log, then recompile. |
| Compiled EA not visible in MT5 | Deployed to a different terminal's data directory, or the Navigator is not refreshed. | Verify the MQL5 path in Settings, then refresh the MT5 Navigator. |
Nothing generated. |
No portfolio folder with a summary.json was found. |
Confirm Step 3 wrote the folder you are asking for. |
| STALE badge on the EA | The .mq5 is newer than the .ex5. |
Recompile. The binary does not correspond to the current source. |
| Unexpected hours in the EA | The generator fell back to the hardcoded table because best_hours.json was missing. |
Run Step 4, or regenerate with --no-hours to be explicit about 24-hour trading. |