Warrior_EA/Expert/Training/ITrainingData.mqh
AnimateDread 8f2164698b feat(target): delete the barrier/geometry stack - the label is the verdict
Step 3 of the swing-pivot plan, whole-hog. The swing label is now the ONE
target and the era verdict is precision + recall per class against the
label's own base rate - no win rate, no break-even, no expectancy, no
geometry anywhere in training.

DELETED
- Expert/Excursion/ (4), Expert/BarrierHorizon/ (4), GeometrySweep,
  FirstPassageLadder, Labeling/TripleBarrier.mqh (CLabelOverlap survives
  in Labeling/LabelOverlap.mqh), 3 test EAs.
- TripleBarrierLabel + walk, fractal label, geometry derivation/scan/
  adoption, exit-policy replay, excursion MI targets, the drift verdict
  (DIRECTION_INTELLIGENT), the recall floor, balanced-accuracy telemetry,
  the barrier defines, the .cfg geometry adopt (slots kept as zeros for
  the positional layout), the derived-geometry live-order override.
- TRAINING_TARGET input/enum: direction models are always swing; META2
  re-keys the meta head onto label agreement (descriptor loses its two
  geometry slots).

REWORKED
- Labels.mqh (1795 -> ~370 lines): AdvanceSwingLabelState with
  FINALITY-GATED CACHING - an unresolved bar (pivot pair uncommitted) is
  never cached, so it can never freeze as a false Neutral; training,
  calibration, OOS scoring and online learning all skip unresolved bars.
- SDeployVerdict: significance-only; SOosTally chance = larger
  directional class share; pooled gate poolability = timeframe (record v2).
- Purge/embargo/declustering gaps: the measured mean label resolution
  lag (LabelResolutionBars), not a barrier horizon.
- Pool purge key + backfill DB rows: marked at the bar the label
  resolved on (m_labelResolveAge), not a fabricated barrier touch.
- Online learning frontier: finality, not a horizon delay.
- m_bestBalancedOos -> m_bestSelectionScore, m_erasSinceBestBalanced ->
  m_erasSinceBest, ensemble vote outcome arrays -> label arrays.

STEP 4 folded in: Entry_Multiplier / SL_Mode / TP_Mode / tradingdirection
are inputs again - trade management is the tester GA's search space.

Fingerprints: every direction model re-keys (TGT:SWG1 now unconditional,
CUT token gone); META1 -> META2. Full retrain, as planned.

Compile-verified in _claude_stage: Warrior_EA + both surviving test EAs,
0 errors, 0 warnings each.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 20:42:31 -04:00

66 lines
4.3 KiB
MQL5

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//| A READ-ONLY VIEW of one model's training data. |
//+------------------------------------------------------------------+
#ifndef WARRIOR_TRAINING_ITRAININGDATA_MQH
#define WARRIOR_TRAINING_ITRAININGDATA_MQH
//+------------------------------------------------------------------+
//| WHAT A TRAINING-SIDE COLLABORATOR IS ALLOWED TO SEE. |
//| |
//| Everything that analyses a model's data - baselines, geometry |
//| scans, redundancy reports - needs the same handful of things: a |
//| feature row, a label, an outcome, an excursion, and the shape |
//| they all share. Before this, each one reached straight into |
//| CExpertSignalAIBase's members, which is why a 951-line diagnostic |
//| could not be moved, tested or replaced without moving the signal |
//| class with it. |
//| |
//| Every accessor is BOUNDS-CHECKED and returns false rather than |
//| reading past a cache. The caller asks "is there a label at r?" |
//| and never "how long is the label array?", so a short cache is a |
//| missing row here instead of an out-of-range read at each of the |
//| thirty-odd call sites that used to do the test themselves. |
//| |
//| MQL5 has interfaces, but a class may implement one only if it |
//| inherits nothing else, and CExpertSignalAIBase is already a |
//| CExpertSignalCustom. So this is an abstract class and the signal |
//| exposes itself through a small ADAPTER that does inherit it - see |
//| CAIBaseTrainingData. Collaborators depend on this and never on |
//| the signal. |
//+------------------------------------------------------------------+
class CTrainingDataView
{
public:
~CTrainingDataView(void) { }
//--- SHAPE: the geometry every row shares.
virtual int HistoryBars(void) = 0; // bars per feature window
virtual int FeaturesPerBar(void) = 0; // columns per bar
virtual int LabelResolutionBars(void) = 0; // mean label resolution lag; also the declustering gap
virtual int PurgeBars(void) = 0; // purge width between fitted and held-out spans
virtual int CalibrationHiIndex(const int totalIter, const int oosCutoff) = 0;
//--- ROWS: false means "this bar has nothing to say", never a partial answer.
virtual bool HasLabel(const int bar) = 0;
virtual bool IsBuyLabel(const int bar) = 0;
virtual bool IsSellLabel(const int bar) = 0;
virtual bool RowFeatures(const int bar, const int width, double &x[]) = 0;
//--- THE MODEL'S OWN CALL on a bar, as the chart drew it: which way and how strongly.
//--- False = it said nothing (never scored, or scored Neutral). Direction rather than a raw
//--- double on purpose - turning one into the other needs the head's output width, which is the
//--- model's business and not a reader's.
virtual bool DirectionalCall(const int bar, bool &isBuy, double &magnitude) = 0;
//--- IDENTITY, for log lines and for the once-per-chart guards.
virtual string Id(void) = 0;
virtual bool IsEnsembleMember(void) = 0;
virtual int EnsembleIndex(void) = 0;
//--- The net's own gate on this chart, for the row every baseline is read against. False when
//--- the gate has not scored yet, which is NOT the same as a gate that scored zero.
virtual bool GateReference(double &precPct, int &calls, double &chancePct) = 0;
//--- POLICY the collaborator must not re-derive: overlapping labels are worth less than their
//--- count, and only the model knows its own overlap - see EffectiveSampleSize.
virtual double EffectiveSampleSize(const double rawN) = 0;
virtual bool Stopping(void) = 0;
};
#endif // WARRIOR_TRAINING_ITRAININGDATA_MQH
//+------------------------------------------------------------------+