refactor(persistence): ModelPersistence is a real collaborator, not a raw-include partial (S3)
Expert/AIBase/Persistence.mqh (598 lines, 8 methods) -> Expert/Persistence/:
IPersistenceView.mqh (abstract, 68 read+write accessors) + AIBasePersistenceView.mqh/
AIBasePersistenceViewImpl.mqh (the adapter) + ModelPersistence.mqh (CModelPersistence,
the real collaborator - signal owns m_modelPersistence and binds it to m_persistenceView,
same shape as ChartUI's S2).
Grep-verified before starting: every field these 8 methods touch is ALSO touched
elsewhere in the class (Training/Lifecycle/OnlineLearning/Topology/FeatureScreen/
Labels.mqh) or already exposed via ChartView. Zero exclusive state, unlike ChartUI's
arrow-restore/rescan queues - CModelPersistence is stateless, holding only the
borrowed view pointer, operating entirely through 68 Persist*/PersistSet*() accessors
on the signal.
ValidateCpuInference's Net-pointer/throwaway-clone core is ONE consolidated view call
(PersistRunCpuInferenceSelfCheck) rather than field-by-field - irreducible pointer/
object work, not signal state, same doctrine as ChartScoreBarForRescan.
LoadNetWithRetry keeps its original CheckPointer(Net)-free Net.Load() call unchanged
(no guard added - would change failure behaviour on what must be a pure relocation).
This code writes the actual on-disk .cfg/.stats binary layouts every deployed model
depends on (explicit "DO NOT REORDER" comment in the original), so beyond compiling
clean (0 errors, 0 warnings) this was verified with a positional field-order diff:
every FileWrite*/FileRead* call's target field, extracted and normalized from both
the original and the new file, matches 1:1 in the same order (43/43 on the write
side covering SaveModelStats+SaveTopologyConfiguration, 17/17 on LoadModelStats'
read side; LoadAndCompareTopologyConfiguration's local-variable read block was
copied verbatim, untouched, so nothing to diff there). The magic-version
conditionals (WST2-6, haveDerivedStages/haveBarrierGeometry/etc.) moved unchanged.
All 8 methods keep their exact original signatures as one-line forwards - zero
external call sites changed.
2026-08-23 21:45:09 -04:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Warrior_EA |
|
|
|
|
|
//| AnimateDread |
|
|
|
|
|
//| |
|
|
|
|
|
//| CAIBasePersistenceView - declarations only, bodies in |
|
|
|
|
|
//| AIBasePersistenceViewImpl.mqh (needs the full signal declared). |
|
|
|
|
|
//| Same shape as Chart\AIBaseChartView.mqh. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#ifndef WARRIOR_PERSISTENCE_AIBASEPERSISTENCEVIEW_MQH
|
|
|
|
|
#define WARRIOR_PERSISTENCE_AIBASEPERSISTENCEVIEW_MQH
|
|
|
|
|
#include "IPersistenceView.mqh"
|
|
|
|
|
class CExpertSignalAIBase;
|
|
|
|
|
class CAIBasePersistenceView : public CPersistenceView
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
CExpertSignalAIBase *m_owner;
|
|
|
|
|
public:
|
|
|
|
|
CAIBasePersistenceView(void) : m_owner(NULL) { }
|
|
|
|
|
void Bind(CExpertSignalAIBase *owner) { m_owner = owner; }
|
|
|
|
|
|
|
|
|
|
virtual string Id(void) override;
|
|
|
|
|
virtual string FileName(void) override;
|
|
|
|
|
virtual int NeuronsCount(void) override;
|
|
|
|
|
virtual long CumIsCorrect(void) override;
|
|
|
|
|
virtual long CumIsTotal(void) override;
|
|
|
|
|
virtual long CumOosCorrect(void) override;
|
|
|
|
|
virtual long CumOosTotal(void) override;
|
|
|
|
|
|
|
|
|
|
virtual bool NetLoaded(void) override;
|
|
|
|
|
virtual bool UsesConvStage(void) override;
|
|
|
|
|
virtual uint NetFirstConvWindow(void) override;
|
|
|
|
|
virtual int ConvReceptiveFieldBars(void) override;
|
|
|
|
|
virtual ENUM_ACTIVATION OutputLayerActivation(void) override;
|
|
|
|
|
virtual bool NetEnforceOutputActivation(const ENUM_ACTIVATION intended, ENUM_ACTIVATION &stale) override;
|
|
|
|
|
virtual void SetTopologySuperseded(const bool v) override;
|
|
|
|
|
|
|
|
|
|
virtual double PriorBuy(void) override;
|
|
|
|
|
virtual void SetPriorBuy(const double v) override;
|
|
|
|
|
virtual double PriorSell(void) override;
|
|
|
|
|
virtual void SetPriorSell(const double v) override;
|
|
|
|
|
virtual double PriorNeutral(void) override;
|
|
|
|
|
virtual void SetPriorNeutral(const double v) override;
|
|
|
|
|
virtual double ConfidenceCalScale(void) override;
|
|
|
|
|
virtual void SetConfidenceCalScale(const double v) override;
|
|
|
|
|
virtual bool MqlInferenceValidated(void) override;
|
|
|
|
|
virtual void SetMqlInferenceValidated(const bool v) override;
|
|
|
|
|
virtual datetime OnlineLearnedUpToTime(void) override;
|
|
|
|
|
virtual void SetOnlineLearnedUpToTime(const datetime v) override;
|
|
|
|
|
virtual double OnlineRollingAcc(void) override;
|
|
|
|
|
virtual void SetOnlineRollingAcc(const double v) override;
|
|
|
|
|
virtual long OnlineSamples(void) override;
|
|
|
|
|
virtual void SetOnlineSamples(const long v) override;
|
|
|
|
|
virtual int LastBuyFiredPrecPct(void) override;
|
|
|
|
|
virtual void SetLastBuyFiredPrecPct(const int v) override;
|
|
|
|
|
virtual int LastSellFiredPrecPct(void) override;
|
|
|
|
|
virtual void SetLastSellFiredPrecPct(const int v) override;
|
|
|
|
|
virtual int LastBuyRecallPct(void) override;
|
|
|
|
|
virtual void SetLastBuyRecallPct(const int v) override;
|
|
|
|
|
virtual int LastSellRecallPct(void) override;
|
|
|
|
|
virtual void SetLastSellRecallPct(const int v) override;
|
|
|
|
|
virtual int LastBuyFired(void) override;
|
|
|
|
|
virtual void SetLastBuyFired(const int v) override;
|
|
|
|
|
virtual int LastSellFired(void) override;
|
|
|
|
|
virtual void SetLastSellFired(const int v) override;
|
|
|
|
|
virtual void SetCumIsCorrect(const long v) override;
|
|
|
|
|
virtual void SetCumIsTotal(const long v) override;
|
|
|
|
|
virtual void SetCumOosCorrect(const long v) override;
|
|
|
|
|
virtual void SetCumOosTotal(const long v) override;
|
fix(vote): persist the tier ladder - a converged model was mute after every restart
THIS IS NOT A DISPLAY BUG. A deployed model could not vote, or trade, at
any point after a terminal restart, and never would have.
LiveVoteContribution() returns 0 for every call until m_tiersSelfRanked
is set - deliberately, and correctly: before RankTiersFromOos() runs,
m_pattern_0..3 hold the constructor's stock 25/50/75/100, which since the
2026-08-18 currency change is the WRONG UNIT rather than a weak opinion,
and one unranked member would drag the whole ensemble over any threshold.
But that ladder is produced ONLY by a completed pass 3, and it was never
persisted - the code comment at LiveVoteContribution says so outright.
A converged model runs no further passes. So on every restart it lost its
entire vote permanently:
LiveVoteContribution -> 0 => no live vote ("0 vote/4 flat")
ReconstructionWeight -> 0 => overlay divisor 0 ("0 had a snapshot")
=> no arrows
=> no fired bars, so g_ensCumOosTotal stays 0
=> "measuring..." forever
Every symptom reported over the last three exchanges is that one cause.
The log is unambiguous: six H4 charts resumed at era 70/71, all 24
rescans completed with ~2700 Buy / ~2200 Sell per model, and the overlay
then swept 4999 bars finding "0 had a snapshot". The calls were there;
nothing was permitted to count them.
WST7 now stores the four tier weights, the module trust weight and the
self-ranked flag beside the model. Restored only when the stored flag
says the ladder was MEASURED - a .stats written before a model's first
pass 3 holds the stock ladder, and adopting that as if measured is the
exact error the flag exists to prevent.
A .stats predating WST7 has no ladder, so existing converged models stay
silent until their next scoring pass mints one. That case now prints a
warning naming all three of its symptoms, because each one independently
looks like a different bug.
Compile-verified in _claude_stage: 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 14:26:33 -04:00
|
|
|
virtual int TierWeight(const int tier) override;
|
|
|
|
|
virtual void SetTierWeight(const int tier, const int v) override;
|
|
|
|
|
virtual double ModuleTrustWeight(void) override;
|
|
|
|
|
virtual void SetModuleTrustWeight(const double v) override;
|
|
|
|
|
virtual bool TiersSelfRanked(void) override;
|
|
|
|
|
virtual void SetTiersSelfRanked(const bool v) override;
|
2026-08-26 16:53:16 -04:00
|
|
|
virtual double CertifiedPrecPct(void) override;
|
|
|
|
|
virtual double CertifiedChancePct(void) override;
|
|
|
|
|
virtual void SetCertifiedEdge(const double precPct, const double chancePct) override;
|
refactor(persistence): ModelPersistence is a real collaborator, not a raw-include partial (S3)
Expert/AIBase/Persistence.mqh (598 lines, 8 methods) -> Expert/Persistence/:
IPersistenceView.mqh (abstract, 68 read+write accessors) + AIBasePersistenceView.mqh/
AIBasePersistenceViewImpl.mqh (the adapter) + ModelPersistence.mqh (CModelPersistence,
the real collaborator - signal owns m_modelPersistence and binds it to m_persistenceView,
same shape as ChartUI's S2).
Grep-verified before starting: every field these 8 methods touch is ALSO touched
elsewhere in the class (Training/Lifecycle/OnlineLearning/Topology/FeatureScreen/
Labels.mqh) or already exposed via ChartView. Zero exclusive state, unlike ChartUI's
arrow-restore/rescan queues - CModelPersistence is stateless, holding only the
borrowed view pointer, operating entirely through 68 Persist*/PersistSet*() accessors
on the signal.
ValidateCpuInference's Net-pointer/throwaway-clone core is ONE consolidated view call
(PersistRunCpuInferenceSelfCheck) rather than field-by-field - irreducible pointer/
object work, not signal state, same doctrine as ChartScoreBarForRescan.
LoadNetWithRetry keeps its original CheckPointer(Net)-free Net.Load() call unchanged
(no guard added - would change failure behaviour on what must be a pure relocation).
This code writes the actual on-disk .cfg/.stats binary layouts every deployed model
depends on (explicit "DO NOT REORDER" comment in the original), so beyond compiling
clean (0 errors, 0 warnings) this was verified with a positional field-order diff:
every FileWrite*/FileRead* call's target field, extracted and normalized from both
the original and the new file, matches 1:1 in the same order (43/43 on the write
side covering SaveModelStats+SaveTopologyConfiguration, 17/17 on LoadModelStats'
read side; LoadAndCompareTopologyConfiguration's local-variable read block was
copied verbatim, untouched, so nothing to diff there). The magic-version
conditionals (WST2-6, haveDerivedStages/haveBarrierGeometry/etc.) moved unchanged.
All 8 methods keep their exact original signatures as one-line forwards - zero
external call sites changed.
2026-08-23 21:45:09 -04:00
|
|
|
|
|
|
|
|
virtual bool RunCpuInferenceSelfCheck(double &maxDiff) override;
|
|
|
|
|
|
|
|
|
|
virtual void SetDirConfThreshold(const double v) override;
|
|
|
|
|
virtual double BestDirConfThreshold(void) override;
|
|
|
|
|
virtual void SetBestDirConfThreshold(const double v) override;
|
|
|
|
|
virtual string CrossAssetPairsPinned(void) override;
|
|
|
|
|
virtual void SetCrossAssetPairsPinned(const string v) override;
|
|
|
|
|
virtual void SetCrossAssetCfgSaved(const bool v) override;
|
|
|
|
|
virtual string AltDataNamesPinned(void) override;
|
|
|
|
|
virtual void SetAltDataNamesPinned(const string v) override;
|
|
|
|
|
virtual void ApplyAltDataPinnedNames(const string v) override;
|
|
|
|
|
|
|
|
|
|
virtual bool LoadNetOnce(double &indicatorParams[]) override;
|
|
|
|
|
};
|
|
|
|
|
#endif // WARRIOR_PERSISTENCE_AIBASEPERSISTENCEVIEW_MQH
|
|
|
|
|
//+------------------------------------------------------------------+
|