forked from animatedread/Warrior_EA
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>
102 lines
6.3 KiB
MQL5
102 lines
6.3 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| 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;
|
|
//--- 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;
|
|
//--- 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;
|
|
virtual void OosTally(int &buyPredicted, int &sellPredicted, int &buyPredictedHits, int &sellPredictedHits) = 0;
|
|
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;
|
|
//--- Throttled, side-effect-free forward of the CURRENT decision bar. See the signal's own
|
|
//--- declaration comment (AIBase\Inference.mqh).
|
|
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
|
|
//+------------------------------------------------------------------+
|