ZZ2_EA MQL5 Conversion: Resolving Compilation and Order Execution Failures
Development Log · 2025-05
1. Title
ZZ2_EA MQL5 Conversion: Resolving Compilation and Order Execution Failures
2. Date / Phase
Date: May 2025 (pre-KOOeda6 era — no KOOeda6/AMARA/RAIDER/HROOM references apply) Phase: Early Development / EA Debugging & Stabilization
3. Background
The session began with the conversion of an MQL4 Expert Advisor
(ZZ2_EA) into MQL5, named ZZ2_EA_fixed_MQL5.mq5. The EA
employs a dual-ZigZag swing-detection strategy — a "major" ZigZag (Depth
12) and a "minor" ZigZag (Depth 5) — to generate directional
signals:
- Buy signal: Major trend up (higher major swing) + minor trend down (lower minor swing)
- Sell signal: Major trend down (lower major swing) + minor trend up (higher minor swing)
Each signal requires confirmation by two consecutive candles in the signal direction before entry, with Stop Loss anchored to the most recent minor swing (± offset) and a fixed Take Profit.
The initial problem was a compilation error in MQL5, followed by a second, more serious problem: after the EA compiled and ran successfully, adjusting parameters produced no order execution at all.
4. Key Insights
Insight 1 — MQL5 does not expose a program-version
constant. The original code attempted to read
MQL5_PROGRAM_VERSION, which does not exist in MQL5. The
MQL5InfoString() function accepts
ENUM_MQL5_INFO_STRING values, none of which represent a
version number. The correct approach is to hardcode the version string
or derive it from __FILE__. This was the direct cause of
the compilation error (undeclared identifier at line
65).
Insight 2 — Silent failure is the dominant risk in EA design. The second problem — EA runs but opens no orders — revealed that the EA had no obligation to inform the developer why it abstained from trading. This is the central insight of the session: an EA that does nothing produces no error. Absence of trades is not evidence of correct behavior; it is an unobservable state unless logging is deliberately designed into every decision branch.
Insight 3 — The confirmation logic was a likely
bottleneck. The EA required two consecutive confirmed
candles (cnt == 2) after signal generation. In
quiet markets or on higher timeframes, this condition may rarely trigger
before the 3-bar timeout cancels the signal. This was identified as the
most probable silent gatekeeper.
Insight 4 — SL/TP geometry has many rejection paths.
Before sending an order, the EA performs multiple validation checks:
SL/TP side correctness, SL-to-TP distance comparison, minimum distance
threshold, and broker StopLevel compliance. Any of these can silently
abort the trade, and the EA set signalType = 0 and returned
without alerting the user.
Insight 5 — Environmental prerequisites are external to
strategy logic. Trade permission
(TERMINAL_TRADE_ALLOWED), AutoTrading state, margin
sufficiency, symbol trade session, and correct ZigZag indicator path
(Examples\ZigZag) are all outside the strategy's logic but
can fully suppress execution.
Insight 6 — Parameter defaults may be mismatched to the
instrument. TPPoints = 700 with
SLPoints = 30 creates a large asymmetry; combined with
broker StopLevel constraints, this may cause the EA to reject setups
that would otherwise be valid.
5. Decisions
Fix the version identifier. Replace
MQL5_PROGRAM_VERSIONwith a hardcoded version string ("1.16") and remove the enum cast that caused the compilation error.Correct a secondary typo.
ORDER_TYPE_SELLL→ORDER_TYPE_SELL.Preserve original trading logic. No changes were made to the dual-ZigZag signal rules, confirmation logic, or SL/TP anchoring. The philosophy is minimal intrusive correction — fix the compiler error without altering strategy behavior.
Adopt a diagnostic-first approach to the "no orders" problem. The recommended path is not to change strategy logic first, but to add observability:
- Log
signalType,majorDir,minorDir, swing values, and the confirmation counter at every branch. - Log every early-return path in
ExecuteTrade()with the exact reason (SL side, TP side, distance, StopLevel). - Log
GetLastError()andtrade.ResultRetcodeDescription()on failure.
- Log
Suggest a controlled relaxation for testing. Temporarily change the confirmation threshold from
cnt == 2tocnt >= 1solely to verify the pipeline fires, then restore it. This isolates the question "is the strategy silent?" from "is the execution pipeline broken?".Recommend Strategy Tester first. Test with Tick-by-Tick mode and inspect the Journal tab before touching a live or demo account.
Consider parameter recalibration as a follow-up, not a first step. Reducing
TPPoints(e.g., 300) and increasingSLPoints(e.g., 100) is a tuning action, not a debugging action, and should only be done after confirming the pipeline itself works.
6. Philosophy
The session surfaced a principle that extends beyond this EA: silence is not success. In automated trading, an EA has three observable states — trade opened, trade rejected with a reason, and nothing happened. The third is the most dangerous, because it looks identical whether the market genuinely offered no setup or whether a misconfigured indicator path silently returned zero for months. Therefore, every branch that decides not to act must still speak. Logging is not a debugging tool; it is the EA's only honest testimony about its own reasoning.
A second principle: fix only what is broken, and only as much as is needed. The version constant was broken; the strategy was not. Resisting the urge to "improve" the ZigZag logic or "optimize" the confirmation rule during a compilation-fix task keeps the change surface minimal and preserves the ability to attribute future behavior to a known baseline. Evolution here is not addition — it is clarity.
A third principle: debug from the outside inward. Environment (Trade permission, connection, session, margin, indicator presence) → Signal generation → Confirmation → Risk validation → Order send. The EA was silent, and silence can come from any of the outer rings; the discipline is to prove each ring is alive before suspecting the core.
7. Future Work
- Instrument every decision branch. Rewrite
CheckNewSwing()andExecuteTrade()so that everyreturnis preceded by aPrintnaming the exact reason for abstention. - Add an environment preflight check in
OnInit(): verifyTERMINAL_TRADE_ALLOWED,MQLInfoInteger(MQL_TRADE_ALLOWED), andSymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE). - Verify ZigZag loading. Confirm
Examples\ZigZagresolves on the target installation; otherwise bundle a customZigZag.mq5. - Test with
cnt >= 1temporarily to prove the execution path, then restorecnt == 2. - Parameter re-baselining. After confirming execution
works, sweep
TPPoints,SLPoints,ZZ1_Depth, andZZ2_Depthin Strategy Tester to find settings where signals actually appear. - Magic number externality. Make
MagicNumberunique per instance to allow parallel testing. - Add trailing-stop and time-filter options as optional extensions, only after the base EA proves stable.
- Document the strategy's assumption — that dual-ZigZag divergence between major and minor trends is a meaningful reversal precursor — and plan a statistical validation pass on historical data.
8. Closing Note
This session marks a small but structurally important step in the EA's evolution: it moved from "compiles and runs" to "compiles, runs, and can be made to explain itself." The compilation error was trivial — an identifier that MQL5 simply does not have — but the second problem, the EA's silence in the face of parameters, exposed a deeper truth about automated systems. An EA that does nothing is not a quiet EA; it is an unreadable one. The remedy is not more logic but more language: every branch that declines to trade must leave a written trace of its reason. The strategy itself was left untouched, and that restraint is deliberate — evolution here is not the accumulation of features but the sharpening of visibility. What remains is to give the EA a voice, listen to what it says, and only then decide whether its silence was wisdom or blindness.
