Warrior_EA/Expert/Chart/IChartView.mqh

102 lines
6.3 KiB
MQL5
Raw Permalink Normal View History

refactor(chart): ChartUI is a real collaborator, not a raw-include partial (S2) Expert/AIBase/ChartUI.mqh was 869 lines of method bodies of CExpertSignalAIBase, #included after the class declaration - free to touch any of its ~500 members. First of the eleven AIBase/*.mqh partials to come out (fewest inbound edges - see the SOLID campaign session order), using the same view+adapter shape already proven for CTrainingDataView. CChartView (Expert/Chart/IChartView.mqh) is the abstract read/behaviour surface a chart-rendering collaborator needs - identity, bar/model access, the prediction cache, and the training/vote/meta scalars the panel and HUD line summarise. CAIBaseChartView is the adapter the signal owns and binds to itself (MQL5 gives a class exactly one base, so CExpertSignalAIBase cannot implement the view directly). CChartUI is the real collaborator: it owns the arrow-restore queue, the rescan queue/tally, the last-arrows-saved count and the purge-mismatch latch as its own fields (verified via grep to be touched nowhere else in Expert/), and reaches everything else - including StartChartSignalRescan, moved in from its old inline home in the header since it drives the exact same rescan state machine AdvanceChartSignalRescan drains - through the view. m_arrowSignalCache and m_signalClusterWindow stay on the signal: Training.mqh writes the cache directly every era and the training-data view already reads it, so moving it would mean rewriting Training.mqh's write sites too - out of scope here. CChartUI reaches it through four bounds-checked accessors instead of a raw member poke. All 10 public methods keep their exact signatures and become one-line forwards on the signal, so no other file's call sites change except Training.mqh's one era-end status refresh, which now reads RefreshStatusLabel() rather than reaching into CChartUI's now-private last-displayed-neuron cache directly. Verified structurally, not compiled (never compile - the operator does, in MetaEditor): brace balance checked on every touched/new file against HEAD, and the view/adapter/impl method lists cross-diffed to confirm all 59 accessors match 1:1 across the interface, the adapter declaration and the adapter body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 20:03:52 -04:00
//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//| A READ-ONLY VIEW of one model's identity, bars, model and |
//| training/vote state - everything the chart-rendering side needs. |
//+------------------------------------------------------------------+
#ifndef WARRIOR_CHART_ICHARTVIEW_MQH
#define WARRIOR_CHART_ICHARTVIEW_MQH
//+------------------------------------------------------------------+
//| WHAT A CHART-SIDE COLLABORATOR IS ALLOWED TO SEE. |
//| |
//| Arrows, the status panel and the HUD line all need the same |
//| handful of things: who this model is, what a bar's time/price |
//| are, what the deployed net currently says, and the training/vote |
//| numbers the panel text summarises. Before this, CChartUI's |
//| predecessor (Expert\AIBase\ChartUI.mqh) was a raw-include body of |
//| CExpertSignalAIBase and reached straight into ~500 members. |
//| |
//| 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 |
//| CAIBaseChartView. Same shape as Training\ITrainingData.mqh. |
//+------------------------------------------------------------------+
class CChartView
{
public:
~CChartView(void) { }
//--- IDENTITY / CONFIG.
virtual string Id(void) = 0;
virtual string FileName(void) = 0;
virtual string ArrowPrefix(void) = 0;
virtual ENUM_TIMEFRAMES Period(void) = 0;
virtual int Digits(void) = 0;
virtual string DisplayNameForChart(void) = 0;
virtual bool ModelLoadedFromDisk(void) = 0;
virtual bool TrainingComplete(void) = 0;
virtual bool BothDirectionsTradeable(void) = 0;
virtual int SignalClusterWindow(void) = 0;
//--- Stop requested, or the program is unloading - same wrap as CTrainingDataView::Stopping().
virtual bool Stopping(void) = 0;
//--- BARS / MODEL. m_Time/m_Close are protected stdlib series the adapter cannot expose directly.
virtual datetime BarTime(const int idx) = 0;
virtual double BarClose(const int idx) = 0;
virtual int HistoryBars(void) = 0;
virtual int OutputNeuronsCount(void) = 0;
virtual bool NetReady(void) = 0;
//--- Bars() on the chart's OWN period (deliberately PERIOD_CURRENT, not this model's Period() -
//--- same as the code this replaces), for sizing a manual rescan's lookback.
virtual int AvailableBars(void) = 0;
virtual bool ResizeBuffers(const int barIndex) = 0;
virtual bool RefreshData(void) = 0;
virtual int ServableBars(const int want, const string context) = 0;
virtual void EnsureShadowNet(void) = 0;
//--- ONE bar through the deployed (shadow-preferred) net: builds the feature window, forwards,
//--- and hands back both the raw argmax-basis signal and the prior-corrected one - the exact pair
//--- AdvanceChartSignalRescan needs, without handing the net itself to a chart-rendering object.
//--- False = the window could not be built (bar skipped, not scored).
virtual bool ScoreBarForRescan(const int idx, double &rawSignal, double &adjustedSignal) = 0;
virtual ENUM_SIGNAL ToSignal(const double value) = 0;
//--- PREDICTION CACHE (m_arrowSignalCache). Stays signal-owned - Training.mqh writes it directly
//--- every era and the training-data view already reads it for the baseline comparator - so this
//--- is a bounds-checked window onto shared state, not a copy.
virtual int PredictionCacheSize(void) = 0;
virtual double PredictionAt(const int idx) = 0;
virtual void SetPredictionAt(const int idx, const double value) = 0;
virtual void ResizePredictionCache(const int size, const double fillValue) = 0;
fix(chart): a deployed model rescans history to rebuild its vote arrows The sidecar added in 484a9d8 restores the vote arrows from the previous session - but there was no previous session to restore from, and a deployed ensemble could never produce one. The overlay that draws the vote layer replays each member's m_overlaySigSnap, published in exactly one place: RankTiersFromOos, at pass-3 completion. A converged model runs no further eras. So after a restart every member's snapshot was empty, would never fill, the sweep had nothing to replay and the chart stayed blank permanently - no route back by any path. The chart rescan is the route: it runs the DEPLOYED net forward over history and rebuilds the per-bar cache, which is the same quantity pass 3 produces, obtained without training. It already existed for the panel's Show-Signals button; it just never handed its result to the overlay, so on the default filtered view a rescan rebuilt only the RAW per-member layer - the one that is hidden - and appeared to do nothing. - PublishOverlaySnapshotFromCache() extracted from RankTiersFromOos, so the era end and a completed rescan publish through one implementation. - A completed rescan now calls it, which also arms the sweep. - PollTraining auto-arms one rescan for a model that is converged, has no snapshot, and is on the filtered view. One-shot: a model that legitimately calls Neutral everywhere must not rescan forever chasing a snapshot that is correctly empty. On the timer, not in OnInit - it is a full feedForward per bar over up to 5000 bars and drains in the same time-boxed slices as a manual rescan. Together with the sidecar this closes both halves: the rescan covers the first session and any chart whose file was lost or invalidated by a threshold change; the sidecar covers every session after one is saved. Compile-verified in _claude_stage: 0 errors, 0 warnings. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-25 13:11:36 -04:00
//--- Hand the cache the rescan just rebuilt to the overlay as this member's snapshot, and mark the
//--- member ready for a sweep. The rescan is the only way a DEPLOYED model can produce one - it
//--- runs no further eras, and the era end is the only other publisher.
virtual void PublishOverlaySnapshot(void) = 0;
refactor(chart): ChartUI is a real collaborator, not a raw-include partial (S2) Expert/AIBase/ChartUI.mqh was 869 lines of method bodies of CExpertSignalAIBase, #included after the class declaration - free to touch any of its ~500 members. First of the eleven AIBase/*.mqh partials to come out (fewest inbound edges - see the SOLID campaign session order), using the same view+adapter shape already proven for CTrainingDataView. CChartView (Expert/Chart/IChartView.mqh) is the abstract read/behaviour surface a chart-rendering collaborator needs - identity, bar/model access, the prediction cache, and the training/vote/meta scalars the panel and HUD line summarise. CAIBaseChartView is the adapter the signal owns and binds to itself (MQL5 gives a class exactly one base, so CExpertSignalAIBase cannot implement the view directly). CChartUI is the real collaborator: it owns the arrow-restore queue, the rescan queue/tally, the last-arrows-saved count and the purge-mismatch latch as its own fields (verified via grep to be touched nowhere else in Expert/), and reaches everything else - including StartChartSignalRescan, moved in from its old inline home in the header since it drives the exact same rescan state machine AdvanceChartSignalRescan drains - through the view. m_arrowSignalCache and m_signalClusterWindow stay on the signal: Training.mqh writes the cache directly every era and the training-data view already reads it, so moving it would mean rewriting Training.mqh's write sites too - out of scope here. CChartUI reaches it through four bounds-checked accessors instead of a raw member poke. All 10 public methods keep their exact signatures and become one-line forwards on the signal, so no other file's call sites change except Training.mqh's one era-end status refresh, which now reads RefreshStatusLabel() rather than reaching into CChartUI's now-private last-displayed-neuron cache directly. Verified structurally, not compiled (never compile - the operator does, in MetaEditor): brace balance checked on every touched/new file against HEAD, and the view/adapter/impl method lists cross-diffed to confirm all 59 accessors match 1:1 across the interface, the adapter declaration and the adapter body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 20:03:52 -04:00
//--- PANEL / HUD SCALARS. Read-only summaries of training, vote and meta-gate state.
virtual long EraCount(void) = 0;
virtual long CumIsTotal(void) = 0;
virtual long CumIsCorrect(void) = 0;
virtual long CumOosTotal(void) = 0;
virtual long CumOosCorrect(void) = 0;
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
virtual void OosTally(int &buyPredicted, int &sellPredicted, int &buyPredictedHits, int &sellPredictedHits) = 0;
refactor(chart): ChartUI is a real collaborator, not a raw-include partial (S2) Expert/AIBase/ChartUI.mqh was 869 lines of method bodies of CExpertSignalAIBase, #included after the class declaration - free to touch any of its ~500 members. First of the eleven AIBase/*.mqh partials to come out (fewest inbound edges - see the SOLID campaign session order), using the same view+adapter shape already proven for CTrainingDataView. CChartView (Expert/Chart/IChartView.mqh) is the abstract read/behaviour surface a chart-rendering collaborator needs - identity, bar/model access, the prediction cache, and the training/vote/meta scalars the panel and HUD line summarise. CAIBaseChartView is the adapter the signal owns and binds to itself (MQL5 gives a class exactly one base, so CExpertSignalAIBase cannot implement the view directly). CChartUI is the real collaborator: it owns the arrow-restore queue, the rescan queue/tally, the last-arrows-saved count and the purge-mismatch latch as its own fields (verified via grep to be touched nowhere else in Expert/), and reaches everything else - including StartChartSignalRescan, moved in from its old inline home in the header since it drives the exact same rescan state machine AdvanceChartSignalRescan drains - through the view. m_arrowSignalCache and m_signalClusterWindow stay on the signal: Training.mqh writes the cache directly every era and the training-data view already reads it, so moving it would mean rewriting Training.mqh's write sites too - out of scope here. CChartUI reaches it through four bounds-checked accessors instead of a raw member poke. All 10 public methods keep their exact signatures and become one-line forwards on the signal, so no other file's call sites change except Training.mqh's one era-end status refresh, which now reads RefreshStatusLabel() rather than reaching into CChartUI's now-private last-displayed-neuron cache directly. Verified structurally, not compiled (never compile - the operator does, in MetaEditor): brace balance checked on every touched/new file against HEAD, and the view/adapter/impl method lists cross-diffed to confirm all 59 accessors match 1:1 across the interface, the adapter declaration and the adapter body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 20:03:52 -04:00
virtual string PassLabel(void) = 0;
virtual int PassProgressPct(void) = 0;
virtual int OosSplitPct(void) = 0;
virtual int OosSamples(void) = 0;
virtual void ClassCounts(int &predBuy, int &predSell, int &predNeutral,
int &trueBuy, int &trueSell, int &trueNeutral) = 0;
virtual void OosRecallPct(int &buyRecallPct, int &sellRecallPct) = 0;
virtual void OosLivePrecision(int &buyPrecPct, int &buyFired, int &sellPrecPct, int &sellFired) = 0;
virtual double Forecast(void) = 0; // dForecast
virtual double ErrorPct(void) = 0; // dError
virtual double OosForecast(void) = 0; // dOosForecast
virtual double OosErrorPct(void) = 0; // dOosError
virtual double NetRecentAverageError(void) = 0;
feat(panel): one live vote line, no stale era count, no per-model HUD Two chart-display fixes reported after watching a converged 4-model ensemble: the ensemble panel's trailing "(era 69, 4 models, DEPLOYING)" was frozen at whatever era the ensemble happened to deploy on, and the separate top-right HUD (one line per model, raw B/S/N + weight + era + error) was clutter once the vote itself is what matters. Root cause of the freeze: g_ensembleVoteLine is written once per era, at pass-3 completion. A deployed/converged ensemble runs no further eras (ScheduleTrainingIfNeeded's trainingComplete branch skips Train() entirely), so that line could never update again - the era count and "DEPLOYING" marker were permanent set-dressing from the deploying era, not a live reading. - EnsembleScoreCombinedVote() drops the era/DEPLOYING tail once g_ensDeployApproved - nothing left there worth freezing. - UpdateVoteReadout() (the aggregate "VOTE ..." line, previously its own top-right chart object) now writes g_liveVoteLine instead of drawing anything. Both status-label builders - PublishEnsembleStatus for the ensemble panel, PublishStatus's choke point for the solo panel - append it as one line, refreshed every tick/timer exactly as the old HUD was, so the live vote replaces the frozen era tail in the same visual slot. - RefreshVoteReadout()'s per-member loop (DisplayHudLine, one ObjectLabel per model) is deleted outright rather than folded in - the operator asked for the aggregate only, "without telling me each individual network". Follow-on dead-code removal, since DisplayHudLine was the only caller: the DispProb/DispSignal/MetaGateArmedNow/MetaHasScore/ MetaLastP/MetaLastBe/MetaApproved/MetaVetoed leg of IChartView (and its AIBaseChartView/AIBaseChartViewImpl/ExpertSignalAIBase forwards) had no other reader. The underlying data survives untouched - m_metaTelemetry is still populated live by SignalMETA.mqh, m_dispSignal still feeds ProspectiveVote - only the chart-view forwarding that existed solely to reach the deleted HUD is gone. Compile: 0 errors, 0 warnings (stage). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 22:27:41 -04:00
//--- Throttled, side-effect-free forward of the CURRENT decision bar. See the signal's own
//--- declaration comment (AIBase\Inference.mqh).
refactor(chart): ChartUI is a real collaborator, not a raw-include partial (S2) Expert/AIBase/ChartUI.mqh was 869 lines of method bodies of CExpertSignalAIBase, #included after the class declaration - free to touch any of its ~500 members. First of the eleven AIBase/*.mqh partials to come out (fewest inbound edges - see the SOLID campaign session order), using the same view+adapter shape already proven for CTrainingDataView. CChartView (Expert/Chart/IChartView.mqh) is the abstract read/behaviour surface a chart-rendering collaborator needs - identity, bar/model access, the prediction cache, and the training/vote/meta scalars the panel and HUD line summarise. CAIBaseChartView is the adapter the signal owns and binds to itself (MQL5 gives a class exactly one base, so CExpertSignalAIBase cannot implement the view directly). CChartUI is the real collaborator: it owns the arrow-restore queue, the rescan queue/tally, the last-arrows-saved count and the purge-mismatch latch as its own fields (verified via grep to be touched nowhere else in Expert/), and reaches everything else - including StartChartSignalRescan, moved in from its old inline home in the header since it drives the exact same rescan state machine AdvanceChartSignalRescan drains - through the view. m_arrowSignalCache and m_signalClusterWindow stay on the signal: Training.mqh writes the cache directly every era and the training-data view already reads it, so moving it would mean rewriting Training.mqh's write sites too - out of scope here. CChartUI reaches it through four bounds-checked accessors instead of a raw member poke. All 10 public methods keep their exact signatures and become one-line forwards on the signal, so no other file's call sites change except Training.mqh's one era-end status refresh, which now reads RefreshStatusLabel() rather than reaching into CChartUI's now-private last-displayed-neuron cache directly. Verified structurally, not compiled (never compile - the operator does, in MetaEditor): brace balance checked on every touched/new file against HEAD, and the view/adapter/impl method lists cross-diffed to confirm all 59 accessors match 1:1 across the interface, the adapter declaration and the adapter body. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 20:03:52 -04:00
virtual bool DisplayInference(void) = 0;
virtual double LiveVoteContribution(const double signal) = 0;
virtual double VoteCapableWeight(void) = 0;
//--- STATUS.
virtual void PublishStatus(const string text, const bool force) = 0;
};
#endif // WARRIOR_CHART_ICHARTVIEW_MQH
//+------------------------------------------------------------------+