Warrior_EA/Signals/README.md

84 lines
4.8 KiB
Markdown

# Signals Subsystem (`Signals/`)
Every trade-signal class the EA can construct. Each is a `CExpertSignalCustom` (rule-based)
or a `CExpertSignalAIBase` (neural), and each is gated by its own `Enable*` input in
`Variables/Inputs.mqh` — so this directory is the roster, not the running configuration.
`Signals.mqh` is the only file the EA includes; it pulls in the rest.
## What is here
### Neural votes — `CExpertSignalAIBase`
| File | Class | Role |
|---|---|---|
| `SignalPAI.mqh` | `CSignalPAI` | Dense MLP direction vote. |
| `SignalCONV.mqh` | `CSignalCONV` | Convolutional front end. |
| `SignalLSTM.mqh` | `CSignalLSTM` | Recurrent, sequence over the input window. |
| `SignalHYBRID.mqh` | `CSignalHYBRID` | Conv front end feeding an LSTM. |
| `SignalMETA.mqh` | `CSignalMETA` | **Not a voter.** A GATE — see below. |
Two or more enabled makes an ensemble; exactly one is a solo model. The roster is
chosen with `Use_MLP` / `Use_CONV` / `Use_LSTM` / `Use_CONVLSTM`, not with per-class
inputs, and it is reported by `EnabledNNSummary()`.
### Filters — `CExpertSignalCustom`
| File | Class | Role |
|---|---|---|
| `SignalNewsFilter.mqh` | `CSignalNewsFilter` | Blocks around calendar events, by impact and lookback. |
| `SignalSessionFilter.mqh` | `CSignalSessionFilter` | London / New York / Tokyo session gating. |
| `SignalRiskGuard.mqh` | `CSignalRiskGuard` | Takes no parameters: thresholds, anchors and state file all live on `g_riskBudget`, evaluated per tick rather than per bar. |
### `CSignalMETA` is routed, not voted
`AddFilter` inspects `IsVotingSignal()`, which is false for a meta head, so META is
adopted as a **gate** rather than a voter: it vetoes vote-cleared entries whose predicted
win probability is below cost-adjusted break-even. It never votes a direction, never
blocks an exit, and fails open loudly. It still receives indicators, ticks, panel commands
and traits, because the administrative walks cover the whole tree — it is simply absent
from every consumer of the voting list, and it is added last so no other filter's
`m_ignore`/`m_invert` bit index moves.
Its candidate corpus comes from `CMetaCorpus::LoadLargestOnDisk` (a tester-built DB).
The on-chart ladder sweep is still implemented (`BuildCorpusBySweep`) but has no wired
sources — see below.
## What was removed, and why it is not coming back
Deleting these is the only way to stop re-deriving the same negative result, so the
reasons are recorded here rather than in a commit nobody re-reads.
- **`SignalMA` / `SignalRSI` / `SignalMACD` / `SignalIchimoku`** (2026-08-24). All 26
shipped vote patterns were transcribed with their constructor weights and tested as
entries on 178k-bar histories, four instruments × three barrier geometries. Nothing
separated from chance — not individually, not by vote threshold, not by 2/3/4-module
quorum, not as event plus confirmation. Residual E[R] was −0.01 to −0.08 R everywhere,
which is approximately the spread. The +4σ reading that once justified the set was two
bars of lookahead; closing it took MACD pattern 4 on EURUSD from +5.05pp to −0.02pp.
All four inputs had shipped `false` long before removal.
- Consequence: these were `CSignalMETA`'s only wired `AddCandidateSource` calls, so a
META chart is no longer self-contained. `AddCandidateSource()` survives as the
extension point; the DB fallback is the supported route.
- `META_ONE_HOT_SLOTS` stays at **26** regardless. A tester-built corpus on disk still
encodes those pattern ids, and narrowing the descriptor would invalidate every stored
corpus.
- **`OscillatorDivergence.mqh`** (2026-08-24). Shared extremum/divergence detector; RSI
and MACD were its only users.
- **`SignalITF` / `SignalMarketDepth`** (2026-08-01). A bitmask-configured time filter, and
a DOM module with no way to test it. See the removal notes in `Variables/Inputs.mqh`.
- **`SignalAC` / `SignalAO` / `SignalCCI` / `SignalDTDB` / `SignalEB` / `SignalIB` /
`SignalPB` / `SignalRVI` / `SignalSAR` / `SignalStoch` / `SignalWPR`** — earlier
wizard-derived votes, removed before the classic-pattern study.
## Conventions worth knowing before editing
- **Weights, patterns and thresholds are stock `CExpertSignal`**, not project additions:
`m_pattern_0..N`, `m_weight`, `m_patterns_usage`, `m_threshold_open`/`_close` and the
weighted-average `Direction()` all ship with MQL5. "Going back to stock" removes none of
them. What *is* ours is `CExpertSignalCustom`'s `Direction()` override, and every one of
its six divergences from the library is a documented fix — most importantly dividing by
the sum of CAPABLE weight rather than by the voter count, which the library's own divisor
turned into a mean of products of two win rates.
- **`Direction()` is a transaction.** It journals DB rows, draws arrows and consumes
one-shot vote state, which is why callers must not invoke it speculatively.