Files
mql-trading-bots/2026-04-23 OrdersEA Smart Grid - Read-Only Code Review.md
garfield 0894d18db4 WIP: 6+ weeks of uncommitted EA development and preset tuning
Confluence EA (v1.16 → v1.20):
- Per-EA realized P&L tracking via history deals
- Weekly drawdown protection
- Warmup bars, pivot cache, state persistence
- Point-scaled pivot thresholds, ranging ATR factor
- Market filling mode helper per symbol

Grid EA (v3.1 → v4.1):
- Adaptive filters, adaptive entry, spread filter
- Session filter, breakeven, correlation caps, range drift
- Profit protection (stop-after-profit, cycle reports)
- Edge cleanup v5.0 — close wrong-side positions outside grid
- Master one-shot shutdown, grid state persistence

Presets:
- Fix GetOut=Y shutdown bug on 4 grid presets
- Relax ADXMax 18→40, widen RSI 20/80 across grid presets
- Standardize daily drawdown 3%→5%, add weekly 10%
- Increase grid lots 0.01→0.03
- Normalize confluence ATR thresholds per pair
- Add XAGUSD, EURCHF, EURGBP, AUDNZD presets

Docs & DevOps:
- April 23 audit files (preset mismatch, code review, checklist)
- n8n workflow and validation infrastructure updates
- AI agent analyses in notes/

Known issues carried forward:
- Shared drawdown budget contamination (both EAs)
- Confluence ranging-market threshold inversion
- Older grid presets missing v4.1 safety controls
2026-05-12 09:02:25 -04:00

5.3 KiB

2026-04-23 OrdersEA Smart Grid - Read-Only Code Review

Reviewed current OrdersEA_Smart_Grid.mq5 and grid-*.set files in the repo read-only. No code changes made.

Findings

High: several presets set GetOut=Y, which makes those charts effectively unable to run grids

GetOut only accepts N/L/S/A/X; Y is invalid per validation in OrdersEA_Smart_Grid.mq5 lines 1150-1159. But OnTick() treats anything other than N as GetOut mode, calls HandleGetOut(), deletes pending orders, sets gridPlaced=false, and returns before trading in lines 1212-1215. The affected repo presets are:

  • grid-usdjpy.set:32
  • grid-xauusd.set:32
  • grid-gbpusd.set:32
  • grid-gbpjpy.set:32

The comments say "enable for safety", but the code interprets that as shutdown mode. This is the first thing to fix before judging live behavior.

High: the grid monitoring logic cancels same-side pending limits after the first fill, despite the comment saying opposite-side limits

When a BUY position exists, it deletes remaining ORDER_TYPE_BUY_LIMIT; when a SELL exists, it deletes remaining ORDER_TYPE_SELL_LIMIT in OrdersEA_Smart_Grid.mq5 lines 1312-1335. That means it does not behave like a classic multi-level averaging grid after the first level fills. This may be intentional risk reduction, but it contradicts the comment and likely user expectation.

High: daily/weekly drawdown is only partially isolated per EA

The P&L numerator is filtered by symbol and magic, which is good, but the daily and weekly baselines still use whole-account ACCOUNT_EQUITY in OrdersEA_Smart_Grid.mq5 lines 340 and 353. If Confluence or another EA has floating P&L at rollover, OrdersEA's limit is based on a contaminated account-level baseline. The same isolation problem affects cycle profit logic.

High: cycle profit target and stop-after-profit can be triggered by other EAs' floating P&L

CheckProfitTarget() compares current whole-account equity to cycleStartEquity in OrdersEA_Smart_Grid.mq5 line 835, and InpStopAfterProfit uses whole-account equity in line 1341. Since cycleStartEquity is also captured from whole-account equity at grid placement in line 1417, Confluence can make Grid think a cycle is profitable, or vice versa.

Medium: breakeven is now broker-valid but not really breakeven/profit-locking

Current logic sets BUY SL to open - buffer and SELL SL to open + buffer in OrdersEA_Smart_Grid.mq5 line 791. That avoids the invalid-stops flood noted in the vault, but it parks the stop on the loss side of entry, not at true breakeven or better. If the intent is "after one TP, protect the remaining basket from loss," this implementation does not do that.

Medium: breakeven can still flood logs if a broker rejects modifications

ApplyBreakeven() retries every 5 seconds and logs every failed PositionModify() in OrdersEA_Smart_Grid.mq5 lines 799-803. There is no freeze-level/stops-level precheck and no failure backoff per ticket. The Apr 23 invalid-stop issue is fixed directionally, but the retry architecture can still produce another large log flood under a different rejection condition.

Medium: adaptive relaxation does not help symbols that have never traded

UpdateFilterRelaxation() returns immediately when lastTradePlacedTime == 0 in OrdersEA_Smart_Grid.mq5 lines 530-537. So a pair that has been blocked forever by filters never relaxes, even though the feature says "relax after N days with no trade." It only relaxes after at least one prior order placement.

Medium: old presets do not carry the newer safety inputs, so they rely on risky defaults

The older grid-eurusd/usdjpy/gbpusd/... files do not define InpUseSessionFilter, InpUseBreakeven, correlation caps, or spread caps, so MT5 will use source defaults. Source default is InpUseSessionFilter=false in OrdersEA_Smart_Grid.mq5 line 65, meaning most older pairs are not actually restricted to Asia hours. The new EURGBP/EURCHF/AUDNZD presets are much better aligned with v4.1.

What Looks Good

The core v4.1 architecture is much improved versus the earlier vault history:

  • Uses _Symbol plus MagicNum consistently for normal position/order handling.
  • Pending orders use ORDER_FILLING_RETURN, avoiding the IOC pending-order issue.
  • IsBreakout() no longer clobbers ATR-based grid bounds.
  • Pivots recalc reliably once per broker day after the first tick.
  • State is persisted through GlobalVariables.
  • Master shutdown is one-shot instead of every tick.
  • Range, spread, session, correlation, daily/weekly drawdown, cycle reports, and weekend close are all present.

Bottom Line

The biggest practical problem is not the .mq5 core, it is the mismatch between code semantics and presets: GetOut=Y is a shutdown setting in practice, not a safety enable. After that, the main code risks are equity contamination from other EAs, unclear same-side limit cancellation behavior, and breakeven not actually locking breakeven.

Suggested Next Steps

  1. Audit and normalize every live chart's loaded preset, especially GetOut, MagicNum, InpUseSessionFilter, and InpUseBreakeven.
  2. Decide whether OrdersEA should be a true multi-level averaging grid or a one-fill-per-side range system, then align the cancellation logic and comments.
  3. Make cycle P&L/profit-stop/drawdown baselines use OrdersEA-only P&L rather than whole-account equity.