mql5/Experts/Advisors/DualEA/docs/Execution-Pipeline.md

387 lines
12 KiB
Markdown
Raw Permalink Normal View History

2025-10-03 01:38:19 -04:00
# Execution Pipeline — DualEA System
**Complete trade execution flow from signal to position**
---
## Pipeline Overview
```
OnTick/OnTimer
2026-02-05 01:22:42 -05:00
[1. Early Safety & Filters] ← circuit breaker, memory guard, news filter (PaperEA); risk/spread/session/news/etc (LiveEA)
2025-10-03 01:38:19 -04:00
↓ PASS
2026-02-05 01:22:42 -05:00
[2. Strategy Selection] ← selector scoring (PaperEA) or external orchestration (LiveEA)
2025-10-03 01:38:19 -04:00
↓ SELECTED
2026-02-05 01:22:42 -05:00
[3. Signal Generation] ← PaperEA: indicator signal generator registry; LiveEA: strategy bridge is available but not called from OnTick
↓ SIGNAL
[4. 8-Stage Gates] ← GateManager (PaperEA) / LiveEA early + risk4 gates
2025-10-03 01:38:19 -04:00
↓ PASS
2026-02-05 01:22:42 -05:00
[5. Policy & Insights Gating] ← LiveEA: per-slice policy + insights gating + exploration; PaperEA: minimal policy load + min_conf gate
↓ PASS
[6. Trade Execution] ← TradeManager.ExecuteOrder() (both EAs)
2025-10-03 01:38:19 -04:00
↓ SUCCESS
2026-02-05 01:22:42 -05:00
[7. Post-Execution] ← KB logging, features export, telemetry, learning
2025-10-03 01:38:19 -04:00
```
---
## Stage 1: Signal Generation
**Entry Points:**
- `OnTick()`: Real-time tick processing
2026-02-05 01:22:42 -05:00
- `OnTimer()`: Used today for maintenance and reload polling (PaperEA); LiveEA uses a timer for insights auto-reload polling
2025-10-03 01:38:19 -04:00
2026-02-05 01:22:42 -05:00
**PaperEA_v2 Signal Generation (actual):**
- Strategy selection chooses from a **23-strategy list** (e.g., `ADXStrategy`, `RSIStrategy`, `MACDStrategy`, `IchimokuStrategy`, etc.).
- Signal generation is executed through `Include/StrategySignalGenerators.mqh` via `GenerateSignalFromStrategy()`.
- Output is a `TradingSignal` (from `Include/GateManager.mqh`) with `price`, `sl`, `tp`, `volume`, and `confidence` seeded.
2025-10-03 01:38:19 -04:00
2026-02-05 01:22:42 -05:00
**LiveEA Signal Generation (actual):**
- `LiveEA.mq5` provides the gating and execution pipeline but **does not call the strategy bridge from `OnTick()`**.
- Strategy generation exists as `LiveEA_StrategyBridge.mqh` (21 default `IStrategy` implementations) and can be used by an external orchestrator or future wiring.
2025-10-03 01:38:19 -04:00
**Signal Structure:**
- `strategy_name`, `direction` (1=Buy, -1=Sell)
- `confidence` (0.0-1.0), `entry_price`, `stop_loss`, `take_profit`, `lot_size`
- `reason` (human-readable), `timestamp`
- Strategy-specific indicator values
---
## Stage 2: Early Phase Validation
Quick rejection before expensive gate processing.
**Checks:**
2026-02-05 01:22:42 -05:00
1. **Circuit breakers / risk limits**
2. **News blackout** (Common Files CSV `DualEA\news_blackouts.csv`)
3. **Session/trading hours caps** (where enabled)
4. **Spread and margin checks** (LiveEA)
2025-10-03 01:38:19 -04:00
2026-02-05 01:22:42 -05:00
**NoConstraintsMode**:
- PaperEA default is `true` and bypasses many constraints, but **circuit breaker + memory guard remain enforced**.
- LiveEA default is `false`; when `true`, many gates become **shadow/diagnostic only** (it logs but does not block on early gates).
2025-10-03 01:38:19 -04:00
---
## Stage 3: 8-Stage Gate Processing
Progressive filtering through configurable gates.
2026-02-05 01:22:42 -05:00
**Important reality check:** In `Include/GateManager.mqh`, several gates are currently implemented as simplified/deterministic checks (for repeatable Strategy Tester runs), not a full production-grade market simulation.
2025-10-03 01:38:19 -04:00
### Gate 1: Signal Rinse
- **Purpose**: Basic validation
- **Checks**: `confidence ≥ G1_MinConfidence`, `strength ≥ G1_MinStrength`
### Gate 2: Market Soap
- **Purpose**: Market context
- **Checks**: ATR within `[G2_MinVolatility, G2_MaxVolatility]`, portfolio correlation ≤ `G2_MaxCorrelation`, regime tradeable
### Gate 3: Strategy Scrub
- **Purpose**: Strategy-specific validation
- **Checks**: History bars ≥ `G3_MinHistoryBars`, strategy.ValidateSignal()
### Gate 4: Risk Wash
- **Purpose**: Risk validation
- **Checks**: Risk/trade ≤ `G4_MaxRiskPct`, portfolio risk ≤ `G4_MaxPortfolioRisk`, RR ≥ `G4_MinRiskReward`
### Gate 5: Performance Wax
- **Purpose**: Backtest performance
- **Checks**: Backtest WR ≥ `G5_MinBacktestWinRate`, trades ≥ `G5_MinBacktestTrades`, R ≥ `G5_MinBacktestRMultiple`
### Gate 6: ML Polish
- **Purpose**: ML confidence
- **Checks**: ML confidence ≥ `G6_MinMLConfidence`, ML available if `G6_RequireMLAvailable`
### Gate 7: Live Clean
- **Purpose**: Live market conditions
- **Checks**: Spread, market open, liquidity
### Gate 8: Final Verify
- **Purpose**: Pre-execution validation
- **Checks**: Broker constraints (min/max lots), duplicate signals
**Learning Integration**: Each gate decision recorded via `LearningBridge` for threshold optimization.
---
## Stage 4: Strategy Selection
2026-02-05 01:22:42 -05:00
### StrategySelector Scoring (PaperEA)
2025-10-03 01:38:19 -04:00
```cpp
score = (winRate × W1) + (normRMultiple × W2) + (normSharpe × W3) + (normTrades × W4)
if(SelectorUseRecency) score ×= recencyDecay^daysSinceLastTrade
```
2026-02-05 01:22:42 -05:00
**Weights (actual PaperEA inputs):** `SelW_PF`, `SelW_Exp`, `SelW_WR`, `SelW_DD` with optional recency overlay.
2025-10-03 01:38:19 -04:00
### Insights Gating
Load insights.json slice for `strategy|symbol|timeframe`:
- **No slice found**: Enter exploration mode if enabled
- **Slice exists**: Check `winRate ≥ InsightsMinWinRate`, `totalTrades ≥ InsightsMinTotalTrades`, `avgR ≥ InsightsMinAvgR`
### Exploration Mode
**Triggered when**: No insights slice exists
2026-02-05 01:22:42 -05:00
**Caps (current defaults in code):**
- Daily: `ExploreMaxPerSlicePerDay` (default 100)
- Weekly: `ExploreMaxPerSlice` (default 100)
2025-10-03 01:38:19 -04:00
**Counters**: Persist in `explore_counts.csv` and `explore_counts_day.csv`
**NoConstraintsMode**: Bypasses insights gating and exploration caps entirely.
---
## Stage 5: Policy Application
### Policy Loading
2026-02-05 01:22:42 -05:00
**LiveEA (actual):**
- Loads `DualEA\policy.json` from **Common Files**.
- Parses per-slice fields including `p_win`, and optional scaling keys `sl_scale`, `tp_scale`, `trail_scale`.
- Applies a slice lookup order:
- Exact `strategy+symbol+timeframe`
- Aggregate `strategy+symbol` with `timeframe=-1`
- Aggregate `strategy` with `symbol="*"` and `timeframe=-1`
**PaperEA_v2 (actual):**
- Loads `DualEA\policy.json` from Common Files and treats the policy as “loaded” if it can find the string `min_confidence`.
- `g_policy_min_conf` defaults to `0.5`.
- Per-slice parsing/scaling is **not currently wired** in PaperEA’s `Policy_Load()`.
- HTTP polling exists (see `PolicyServerUrl`, `PolicyHttpPollPercent`) but still only checks for `min_confidence`.
2025-10-03 01:38:19 -04:00
### Policy Gating Logic
```
if policy.slices == 0:
if FallbackWhenNoPolicy && (FallbackDemoOnly→demo OR !FallbackDemoOnly):
→ FALLBACK: neutral scaling, bypass insights/exploration
else:
→ BLOCK
if slice missing:
if FallbackWhenSliceMissing && (demo check as above):
→ FALLBACK: neutral scaling
else:
→ BLOCK
if slice.probability < policy.min_confidence:
→ BLOCK
else:
→ PASS: Apply scaling
```
### Policy Scaling
2026-02-05 01:22:42 -05:00
**LiveEA (actual):**
- Adjusts SL/TP distance from entry using `sl_scale` / `tp_scale`.
- Adjusts trailing distance using `trail_scale`.
**PaperEA_v2 (current):**
- Policy gating is applied as a **minimum confidence check** (and the scaling path is currently neutral/placeholder in `ApplyPolicyGating()`).
2025-10-03 01:38:19 -04:00
---
## Stage 6: Risk Management
### Position Sizing
**Base Sizing**:
```
pipRisk = |entry - SL| / Point / 10
riskAmount = Balance × (G4_MaxRiskPct / 100)
lots = riskAmount / (pipRisk × tickValue)
lots = NormalizeLots(lots) // Broker constraints
```
**Correlation Adjustment** (LiveEA with PositionManager):
```
avgCorr = CorrelationManager.GetAverageCorrelation(symbol)
dampening = 1.0 - (avgCorr × 0.5)
adjustedLots = lots × dampening
adjustedLots = max(adjustedLots, max(lots × PM_CorrMinMult, PM_CorrMinLots))
```
### Circuit Breakers
- **Daily Loss**: Block if daily PnL < `-MaxDailyLossPct`
- **Drawdown**: Block if drawdown from peak > `MaxDrawdownPct`
- **Consecutive Losses**: Block after `MaxConsecutiveLosses` losses
- **Cooldown**: After breaker trips, wait `CircuitCooldownSec` seconds
---
## Stage 7: Trade Execution
### TradeManager.Execute()
2026-02-05 01:22:42 -05:00
**PaperEA_v2 (actual):** Places **real MT5 orders on demo accounts** via `CTradeManager::ExecuteOrder()`.
2025-10-03 01:38:19 -04:00
2026-02-05 01:22:42 -05:00
**LiveEA (actual):** Places **real MT5 orders** via `CTradeManager::ExecuteOrder()`.
2025-10-03 01:38:19 -04:00
- Market orders: Immediate execution
- Pending orders: BuyStop, SellStop, BuyLimit, SellLimit
- SL/TP normalization to broker tick size
- Volume normalization (min/max/step)
**Trailing Stops**: Initialized if `TrailEnabled=true`
- Fixed-points: `TrailActivationPoints`, `TrailDistancePoints`, `TrailStepPoints`
- ATR-based: `TrailATRMultiplier × ATR` for distance
---
## Stage 8: Post-Execution
### Knowledge Base Logging
**knowledge_base.csv**:
```
timestamp,symbol,type,entry_price,stop_loss,take_profit,close_price,profit,strategy_id
```
**knowledge_base_events.csv**:
```
timestamp,strategy,retcode,deal,order
```
### Features Export
**features.csv** (long format):
```
timestamp,symbol,timeframe,strategy,direction,confidence,...,indicator_1,indicator_2,...
```
- 50+ features per trade
2026-02-05 01:22:42 -05:00
- Automatic ~100MB rotation (rename to `*.bak`); no compression is performed in MQL5
2025-10-03 01:38:19 -04:00
### Telemetry & Logging
**Telemetry Events**:
- `gate_decision`: Pass/block with reason, latency
- `trade_execution`: Order placement, retcode
- `policy_load`, `insights_rebuild`, `threshold_adjust`
- `risk4_*`: Risk gate events (spread, margin, drawdown)
- `pm_*`: PositionManager events (correlation sizing, scale-ins)
- `p5_*`: Selector events (refresh, rescore, tune)
**UnifiedTradeLogger**: Daily JSON logs with full lifecycle
```json
{
"timestamp": "2025-01-15T10:30:00Z",
"strategy": "ADXStrategy",
"symbol": "EURUSD",
"timeframe": 60,
"direction": 1,
"entry": 1.0850,
"sl": 1.0800,
"tp": 1.0950,
"lots": 0.10,
"gates": ["signal_rinse:pass", "market_soap:pass", ...],
"policy": {"confidence": 0.75, "sl_mult": 1.0, "tp_mult": 1.2},
"outcome": "closed",
"profit": 15.50,
"r_multiple": 1.2
}
```
### Learning System Update
**LearningBridge**: Records `CSignalDecision` with:
- All 8 gate decisions (pass/fail, reason, latency)
- Final outcome (executed, blocked, reason)
- Trade result (if executed): profit, R-multiple, duration
**GateLearningSystem**: Updates gate thresholds
- Hybrid learning: immediate (5% rate) + batch (every 20 trades)
- Target success rate per gate configurable
- Adjusts thresholds to optimize pass rate vs trade quality
---
## Live Trading Flow (LiveEA)
2026-02-05 01:22:42 -05:00
**Differences from PaperEA_v2 (as wired today):**
1. **Insights auto-reload loop**: LiveEA requests rebuild by creating `DualEA\insights.reload` and waits for `DualEA\insights.ready`.
2. **Per-slice policy scaling**: LiveEA parses per-slice policy entries and applies SL/TP/trailing scaling.
3. **Risk gates**: LiveEA includes spread/session/margin/consecutive-loss gating in the EA itself.
2025-10-03 01:38:19 -04:00
**Safety Features**:
- Shadow mode possible (log decisions, don't execute)
- Policy fallback with demo-only restriction
- Multiple circuit breakers
- One-execution-per-slice-per-minute de-dup (Phase 6 - planned)
---
## Error Handling
### Broker Errors
**Retcode Handling**:
- `TRADE_RETCODE_DONE`: Success → proceed to post-execution
- `TRADE_RETCODE_REQUOTE`: Retry with new price (max 3 attempts)
- `TRADE_RETCODE_REJECT`: Log + telemetry, don't retry
- `TRADE_RETCODE_NO_MONEY`: Trip circuit breaker, halt trading
- Other errors: Log, telemetry, optional cooldown
### File I/O Errors
**KB Write Failures**:
- Retry with exponential backoff (3 attempts)
- Create directory if missing
- Log to Journal on persistent failure
- Continue execution (non-fatal)
**Policy/Insights Load Failures**:
- Use last-known-good cached version
- Log warning + telemetry event
- Fallback to neutral scaling if allowed
- Reload attempt on next timer cycle
### Learning System Failures
- Non-fatal: Log errors, continue trading
- Disable learning if consecutive failures > 5
- Telemetry event for monitoring
---
## Performance Characteristics
### Latency Targets
- **Signal → Gate entry**: <5ms
- **8-stage gates**: <50ms total (target <10ms per gate)
- **Policy/insights lookup**: <2ms (in-memory cache)
- **KB write**: <10ms (non-blocking preferred)
- **Telemetry emit**: <1ms
- **Total pipeline**: <100ms (OnTick → OrderSend)
### Memory Footprint
- **Strategies (21)**: ~500KB
- **Gate Manager**: ~100KB
- **Policy cache**: ~50KB
- **Insights cache**: ~200KB
- **Telemetry buffer**: ~500KB
- **Total**: ~1.5MB per EA instance
### File I/O
- **KB writes**: Append-only, buffered every 10 trades
- **Features export**: Buffered every 50 trades
- **Telemetry flush**: Every 5 minutes or 1000 events
- **Policy/insights reload**: On timer (every 60 minutes) or .reload trigger
---
**See Also:**
- [Configuration-Reference.md](Configuration-Reference.md) - All input parameters
- [Observability-Guide.md](Observability-Guide.md) - Telemetry and monitoring
- [Policy-Exploration-Guide.md](Policy-Exploration-Guide.md) - Policy fallback and exploration details