Warrior_EA/Expert/Topology/ITopologyView.mqh

70 lines
4 KiB
MQL5
Raw Permalink Normal View History

refactor(topology): split shape derivation into CTopology, leave the boot sequence in place Expert/AIBase/Topology.mqh (1191 lines) held two genuinely different jobs: the fingerprint/derived-shape/BuildFreshTopology math, and InitNeuralNetwork/ InitFeatureIndicators - the network boot sequence (config-lock, tester-cache seeding, load/save the .cfg, net-load backend fallback, chart/persistence/ online-learning orchestration). Extracted the first job to Expert/Topology/ as CTopology + CTopologyView/ CAIBaseTopologyView (20 methods: BuildModelFingerprint, the Estimated*/Compute* budget math, the Conv*/Lstm* shape helpers, Add*Stage, BuildFreshTopology). STATELESS, like ModelPersistence - grep-verified zero exclusive fields, every member these methods touch is shared elsewhere in the signal. Reused ~15 existing Data*/Chart*/Persist*/Exc* getters per the established convention; added ~20 new getter overloads next to their existing setters (UseVolumes(), MinDirectionalRecall(), etc. - same pattern as SignalClusterWindow) and ~16 new Topology*() wrappers for fields with no prior accessor. The Net-pointer swap in BuildFreshTopology is one consolidated view call (TopologyReplaceNetFromTopology), same doctrine as Persistence's RunCpuInferenceSelfCheck - irreducible pointer work, not signal state. Deliberately did NOT extract InitNeuralNetwork/InitFeatureIndicators: they orchestrate nearly every other collaborator (chart, persistence, online- learning, cross-asset, config-lock) rather than deriving a shape, so moving them would just relocate a hub, not reduce coupling - same judgment call as Inference.mqh (assessed, not extracted). They stay in the AIBase/Topology.mqh partial, byte-identical to before (diffed against git HEAD to confirm), and now call the extracted math through the same public forwards every other caller already used. Verified: string- and numeric-literal diff of the old file's 20 method bodies against the new CTopology methods (0 differences), InitNeuralNetwork/ InitFeatureIndicators byte-identical, self-compiled 0 errors/0 warnings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:23:00 -04:00
//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//| The read/write surface CTopology needs from the signal. Same |
//| shape as Persistence\IPersistenceView.mqh - abstract, pure `= 0`,|
//| no signal include. Everything here is either a fingerprint input,|
//| a size the shape derivation reads, or the two irreducible |
//| pointer operations (the Net swap, the online-learning reset) |
//| that are not signal STATE and so are consolidated into one call |
//| each rather than exposed field-by-field. |
//+------------------------------------------------------------------+
class CTopologyView
{
public:
virtual ~CTopologyView(void) { }
//--- IDENTITY + SIZE (reused via the signal's existing Data*()/Chart*() getters)
virtual string Id(void) = 0;
virtual string SymbolName(void) = 0;
virtual ENUM_TIMEFRAMES Timeframe(void) = 0;
virtual int OptimizationAlgo(void) = 0;
virtual int OutputNeuronsCount(void) = 0;
virtual int NeuronsCount(void) = 0;
virtual int HistoryBars(void) = 0;
virtual int InitialNeuronsCount(void) = 0;
virtual int HiddenLayersCount(void) = 0;
virtual int ConvFilterCount(void) = 0;
virtual int LstmHiddenSize(void) = 0;
virtual int MinTrainYear(void) = 0;
virtual int FractalPeriods(void) = 0;
virtual int OosSplitPct(void) = 0;
virtual int SwingConfirmationBars(void) = 0;
fix(topology): size the network against observations, not bars The capacity budget is stated in weights per INDEPENDENT observation and divides by the mean label lifespan to get there. It never once did: EstimatedInSampleBars() deflates via m_labelOverlap, but it is only ever called from InitNeuralNetwork, where the label cache does not exist yet (that same function sets m_labelCachePrebuilt = false a few lines below), so MeanLifespan() returned its "nothing measured" default of 1.0 at every call. Every fresh model was sized as though its labels did not overlap - over-budgeting the first dense layer by a factor of L, which is several rungs of a power-of-two ladder. The "expect overfitting, reduce the feature set or pool instruments" warning is the branch that should fire on H1 and structurally could not. Fixed at the source rather than by reordering the boot sequence (the prebuild is chunked across Train() calls and cannot complete inside init): MeasureSwingGeometry() walks the ZigZag ONCE at init and answers both questions from it - the median leg gives the window, and the leg series gives the mean label lifespan analytically. SwingPivotDirectionLabel resolves bar i when the SECOND pivot after it commits, so a bar d bars before pivot P waits d + (the leg leaving P); summed over every bar of every leg that is exactly the mean the label walk accumulates. That also closes the coherence gap the swing target opened: the window was measured with a private +/-12-bar fractal while the label aimed at ZigZag(12,5,3) pivots, so it was sized against a leg distribution the label never used. One pivot source now, the label's. Also: - ResetWeights() re-derives the shape. It rebuilt from the members a history-starved init had pinned and re-saved them - so the "let history download, then reset from the panel" advice in both fallback warnings did nothing at all. - The CAPACITY line prints the measured lifespan beside the one the topology was sized for, and warns when they differ by more than a ladder rung. That is the check that makes the estimator falsifiable. - Topology reads the view's symbol, not _Symbol (latent for pooling). - Unmeasured geometry defaults to HISTORY_BARS_FALLBACK, never 1.0: under-sizing is recoverable, over-sizing silently is not. Compile: 0 errors, 0 warnings (stage). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 21:21:05 -04:00
//--- The LABEL'S pivot source, read at init to measure the swing geometry the window and the
//--- capacity budget are both derived from - see CTopology::MeasureSwingGeometry().
virtual int ZigZagHandle(void) = 0;
refactor(topology): split shape derivation into CTopology, leave the boot sequence in place Expert/AIBase/Topology.mqh (1191 lines) held two genuinely different jobs: the fingerprint/derived-shape/BuildFreshTopology math, and InitNeuralNetwork/ InitFeatureIndicators - the network boot sequence (config-lock, tester-cache seeding, load/save the .cfg, net-load backend fallback, chart/persistence/ online-learning orchestration). Extracted the first job to Expert/Topology/ as CTopology + CTopologyView/ CAIBaseTopologyView (20 methods: BuildModelFingerprint, the Estimated*/Compute* budget math, the Conv*/Lstm* shape helpers, Add*Stage, BuildFreshTopology). STATELESS, like ModelPersistence - grep-verified zero exclusive fields, every member these methods touch is shared elsewhere in the signal. Reused ~15 existing Data*/Chart*/Persist*/Exc* getters per the established convention; added ~20 new getter overloads next to their existing setters (UseVolumes(), MinDirectionalRecall(), etc. - same pattern as SignalClusterWindow) and ~16 new Topology*() wrappers for fields with no prior accessor. The Net-pointer swap in BuildFreshTopology is one consolidated view call (TopologyReplaceNetFromTopology), same doctrine as Persistence's RunCpuInferenceSelfCheck - irreducible pointer work, not signal state. Deliberately did NOT extract InitNeuralNetwork/InitFeatureIndicators: they orchestrate nearly every other collaborator (chart, persistence, online- learning, cross-asset, config-lock) rather than deriving a shape, so moving them would just relocate a hub, not reduce coupling - same judgment call as Inference.mqh (assessed, not extracted). They stay in the AIBase/Topology.mqh partial, byte-identical to before (diffed against git HEAD to confirm), and now call the extracted math through the same public forwards every other caller already used. Verified: string- and numeric-literal diff of the old file's 20 method bodies against the new CTopology methods (0 differences), InitNeuralNetwork/ InitFeatureIndicators byte-identical, self-compiled 0 errors/0 warnings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:23:00 -04:00
//--- FINGERPRINT INPUT FLAGS (BuildModelFingerprint) - every one already has a signal-side setter;
//--- these are the matching getters.
virtual bool UseVolumes(void) = 0;
virtual bool UseTime(void) = 0;
virtual bool UseATR(void) = 0;
virtual bool UseSwingContext(void) = 0;
virtual bool UseNews(void) = 0;
virtual int NewsFeatureWindowMinutes(void) = 0;
virtual bool UseMA(void) = 0;
virtual bool UseCrossAsset(void) = 0;
virtual bool UseSpreadFeature(void) = 0;
//--- The DERIVED alt-data flag (InitFeatureIndicators sets it once width is known) - NOT the
//--- operator opt-in switch (UseAltData(bool) already means that elsewhere).
virtual bool UseAltData(void) = 0;
virtual bool IsEnsembleMember(void) = 0;
//--- Extra independent observations available from Training\TrainingPool.mqh, already discounted
//--- for cross-instrument correlation - see CTopology::EstimatedInSampleBars()'s use of it. 0 when
//--- pooling is off or no compatible peer file exists yet.
virtual double PooledIndependentBars(void) = 0;
refactor(topology): split shape derivation into CTopology, leave the boot sequence in place Expert/AIBase/Topology.mqh (1191 lines) held two genuinely different jobs: the fingerprint/derived-shape/BuildFreshTopology math, and InitNeuralNetwork/ InitFeatureIndicators - the network boot sequence (config-lock, tester-cache seeding, load/save the .cfg, net-load backend fallback, chart/persistence/ online-learning orchestration). Extracted the first job to Expert/Topology/ as CTopology + CTopologyView/ CAIBaseTopologyView (20 methods: BuildModelFingerprint, the Estimated*/Compute* budget math, the Conv*/Lstm* shape helpers, Add*Stage, BuildFreshTopology). STATELESS, like ModelPersistence - grep-verified zero exclusive fields, every member these methods touch is shared elsewhere in the signal. Reused ~15 existing Data*/Chart*/Persist*/Exc* getters per the established convention; added ~20 new getter overloads next to their existing setters (UseVolumes(), MinDirectionalRecall(), etc. - same pattern as SignalClusterWindow) and ~16 new Topology*() wrappers for fields with no prior accessor. The Net-pointer swap in BuildFreshTopology is one consolidated view call (TopologyReplaceNetFromTopology), same doctrine as Persistence's RunCpuInferenceSelfCheck - irreducible pointer work, not signal state. Deliberately did NOT extract InitNeuralNetwork/InitFeatureIndicators: they orchestrate nearly every other collaborator (chart, persistence, online- learning, cross-asset, config-lock) rather than deriving a shape, so moving them would just relocate a hub, not reduce coupling - same judgment call as Inference.mqh (assessed, not extracted). They stay in the AIBase/Topology.mqh partial, byte-identical to before (diffed against git HEAD to confirm), and now call the extracted math through the same public forwards every other caller already used. Verified: string- and numeric-literal diff of the old file's 20 method bodies against the new CTopology methods (0 differences), InitNeuralNetwork/ InitFeatureIndicators byte-identical, self-compiled 0 errors/0 warnings. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:23:00 -04:00
//--- SHAPE SEAMS - subclass-overridden virtuals on the signal (CSignalCONV/LSTM/HYBRID/META).
virtual bool UsesConvStage(void) = 0;
virtual bool UsesLstmStage(void) = 0;
virtual bool HasConvBeforeLstm(void) = 0;
virtual bool AddCustomLayers(CArrayObj *topology) = 0;
virtual ENUM_ACTIVATION HiddenLayerActivation(void) = 0;
virtual ENUM_ACTIVATION OutputLayerActivation(void) = 0;
virtual int NetInputWidth(void) = 0;
//--- IRREDUCIBLE POINTER WORK, consolidated - same doctrine as Persistence's
//--- RunCpuInferenceSelfCheck/ChartScoreBarForRescan: not signal state, a whole-object operation.
virtual bool ReplaceNetFromTopology(CArrayObj *topology) = 0;
//--- A fresh topology invalidates the shadow net and the online-learning history - see
//--- COnlineLearning::ResetForFreshTopology()'s comment.
virtual void ResetOnlineLearningForFreshTopology(void) = 0;
};
//+------------------------------------------------------------------+