ZigZag-Based EA: Order Validation, Pending Signal Logic, and Debugging Anomalous Trades
Development Log · 2025-06
1. Title
ZigZag-Based EA: Order Validation, Pending Signal Logic, and Debugging Anomalous Trades
2. Date / Phase
Date: June 2025
Phase: Strategy Refinement & Risk Control
Implementation
3. Background
The session began with a request to enhance an existing Expert Advisor (EA) that opens trades based on two ZigZag indicators (ZZ1 and ZZ2). The original EA logic generated a "Pending Signal" when ZZ1 and ZZ2 moved in opposite directions, and confirmed entry using a two-candle pattern. However, the system lacked safeguards against poor risk/reward setups.
The initial problem: the EA was opening trades even when the calculated Stop Loss was unreasonably far from the entry price relative to the Take Profit. For example, a BUY at 40,000 with a calculated SL at 39,600 (a 400-point distance) would still open despite a TP setting of only 300 points. This resulted in poor risk/reward ratios and exposed the account to excessive drawdown.
A secondary, more troubling issue emerged during debugging: orders were appearing in the trade history without any corresponding log entry — "ghost orders" that could not be traced. This raised concerns about duplicate signal processing, missing validation, or uncontrolled execution paths within the EA.
4. Key Insights
On Risk Validation:
The core insight was that a pending signal should not automatically
translate into an executed order. A new validation layer was needed
between signal generation and order placement — specifically, a check
that the distance from entry price to Stop Loss must not exceed the Take
Profit value. This single constraint converts the EA from a pure
signal-follower into a risk-aware system.
On Pending Signal Persistence:
Analysis of the log revealed that a Pending Sell Signal generated at
13:30 remained active through multiple failed entry attempts (13:40,
13:45) until finally executing at 14:40. This behavior was initially
perceived as a bug — "why isn't the pending signal cleared?" — but
deeper examination confirmed it was logically correct. The pending
signal persists as long as ZZ1 has not changed direction. This is
consistent with the ZigZag-based strategy: the structural trend remains
intact, so the signal remains valid. The entry attempts failed only
because the SL was too far, not because the signal was invalid.
On Ghost Orders:
The absence of Pending Signal messages preceding an order was traced to
a conditional in the code: the message only prints when the pending
state changes. If the signal was set on a previous bar and
simply maintained, no new message appears. This explained the "silent"
order execution. The order itself was legitimate — only the logging was
insufficient.
On Connection Checking:
The MQL5 function IsConnected() does not exist. The correct
approach is TerminalInfoInteger(TERMINAL_CONNECTED). This
was a straightforward technical correction, but it reinforced the
importance of verifying standard library functions against the MQL5
reference.
5. Decisions
Implement Risk Validation in
CheckStops():- For BUY: reject if
(price - SL) > TakeProfit - For SELL: reject if
(SL - price) > TakeProfit - Additionally, reject if SL/TP are too close to the broker's minimum stop level.
- For BUY: reject if
Preserve the Original Pending Signal Logic:
The decision was made to keep the pending signal persistent until either:- An order is successfully opened, or
- ZZ1 changes direction.
This was confirmed as logically consistent with the strategy, not a bug.
Add a Magic Number and Position Verification:
A magic number (12345) was introduced to ensure the EA only manages its own positions. AHasOpenPosition()function was added to check for existing positions before placing new orders, preventing duplicates.Improve Logging:
- Log ticket numbers on successful order placement.
- Log rejection reasons explicitly (e.g., "SL too far from entry").
- Optionally, log maintenance of an existing pending signal.
Use Current Market Price Instead of Bar Close:
For order placement, useSymbolInfoDouble(Symbol(), SYMBOL_ASK)for BUY andSYMBOL_BIDfor SELL, rather than the previous bar's close price. This ensures the entry price reflects actual execution conditions.
6. Philosophy
This session surfaced a recurring tension in algorithmic trading: the difference between a signal and a decision. A signal is an observation about market structure; a decision requires additional constraints — risk, timing, capital, and context. The original EA conflated the two, treating every signal as an automatic decision. The refinement introduced a deliberative layer: the signal remains, but the decision to act is now gated by risk validation.
Equally important was the realization that persistence is not a flaw. In a system designed around structural indicators like ZigZag, a pending signal that survives multiple bars is not stale — it is patient. It waits for the market to offer a favorable entry, and only then acts. This patience is a form of discipline encoded in logic, and it stands in contrast to the impulsive re-evaluation that often plagues discretionary traders.
Finally, the ghost order investigation reinforced a principle: observability is part of correctness. A system that behaves correctly but cannot be observed is indistinguishable from one that behaves incorrectly. Logging is not a secondary concern; it is the lens through which the system becomes trustworthy.
7. Future Work
- Optional Time Limit for Pending Signals: Introduce a maximum bar count after which a pending signal expires, to prevent indefinite waiting in ranging markets.
- Enhanced Pending Signal Logging: Print a status line on each bar while a pending signal is active, so the log reflects the ongoing state.
- Backtesting and Forward Testing: Validate the revised EA under historical data and demo conditions to confirm that the new risk filter improves overall performance without excessively reducing trade frequency.
- Parameter Optimization: Explore whether
StopLossOffsetandTakeProfitshould be dynamically adjusted based on volatility (e.g., ATR) rather than fixed values. - Review of ZigZag Parameters: Assess whether the depth/deviation/backstep settings for both ZigZag indicators remain optimal across different market regimes.
8. Closing Note
This session marked a quiet but significant evolution in the EA's design. What began as a request to add a simple validation check became a broader inquiry into the nature of signal persistence, the distinction between observation and action, and the role of observability in building trust with automated systems. The code now does more than follow ZigZag — it reasons about risk before committing capital. The pending signal that lingered from 13:30 to 14:40 was not a malfunction; it was the system waiting, correctly, for the market to meet its conditions. That patience, once understood, became a feature rather than a fault. The refinement is not merely technical — it is a step toward a more disciplined, transparent, and deliberate trading system.
