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

  1. Fix the version identifier. Replace MQL5_PROGRAM_VERSION with a hardcoded version string ("1.16") and remove the enum cast that caused the compilation error.

  2. Correct a secondary typo. ORDER_TYPE_SELLL → ORDER_TYPE_SELL.

  3. 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.

  4. 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() and trade.ResultRetcodeDescription() on failure.
  5. Suggest a controlled relaxation for testing. Temporarily change the confirmation threshold from cnt == 2 to cnt >= 1 solely to verify the pipeline fires, then restore it. This isolates the question "is the strategy silent?" from "is the execution pipeline broken?".

  6. Recommend Strategy Tester first. Test with Tick-by-Tick mode and inspect the Journal tab before touching a live or demo account.

  7. Consider parameter recalibration as a follow-up, not a first step. Reducing TPPoints (e.g., 300) and increasing SLPoints (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() and ExecuteTrade() so that every return is preceded by a Print naming the exact reason for abstention.
  • Add an environment preflight check in OnInit(): verify TERMINAL_TRADE_ALLOWED, MQLInfoInteger(MQL_TRADE_ALLOWED), and SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE).
  • Verify ZigZag loading. Confirm Examples\ZigZag resolves on the target installation; otherwise bundle a custom ZigZag.mq5.
  • Test with cnt >= 1 temporarily to prove the execution path, then restore cnt == 2.
  • Parameter re-baselining. After confirming execution works, sweep TPPoints, SLPoints, ZZ1_Depth, and ZZ2_Depth in Strategy Tester to find settings where signals actually appear.
  • Magic number externality. Make MagicNumber unique 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.