//+------------------------------------------------------------------+ //| 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 //+------------------------------------------------------------------+