refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Warrior_EA |
|
|
|
|
|
//| AnimateDread |
|
|
|
|
|
//| |
|
refactor(features): FeatureBuilder is a real collaborator, not a raw-include partial
Expert/AIBase/Features.mqh (2017 lines, 38 methods) split by exclusivity grep
(whole-repo, not just Expert/): 30 methods -> Expert/Features/FeatureBuilder.mqh
(CFeatureBuilder + CFeaturesView/CAIBaseFeaturesView), 8 stay behind as a much
smaller raw partial.
CFeatureBuilder is STATEFUL, same shape as Excursion/OnlineLearning: owns the
10 feature-only indicator handles (m_Volumes/m_MA/m_RSI/m_MACDFeature/
m_Ichimoku/5 AD* CiCustom indicators - grep-verified touched nowhere else in
the repo, only their bare declarations) plus the depth-probe/handle-repair/
spread-series/detectability-latch scalars (exclusive, Lifecycle.mqh ctor-init
only elsewhere). m_Open/m_Close/m_High/m_Low/m_Time/m_ATR/m_ADZigZag stay
signal-owned - Labels.mqh/AutoTune.mqh/Training.mqh read them directly - and
are reached read-only through the view (FeatureOpenAt/FeatureHighAt/
FeatureLowAt/ChartBarClose/ChartBarTime/OnlineAtrMain, all reused where a
forward already existed).
Deliberately did NOT move InitOpen/InitClose/InitHigh/InitLow/InitTime/
InitADZigZag/ResizeBuffers/RefreshData: they manage the 7 shared indicators'
Create/BufferResize/Refresh lifecycle, which would need a pure-relay wrapper
per operation per indicator for zero coupling benefit - same judgment as
Topology's boot sequence. They stay in Expert/AIBase/Features.mqh and reach
CFeatureBuilder's 10 owned indicators through 20 new Feature*BufferResize()/
Feature*Refresh() forwards (signal calling into its own owned collaborator
directly, no view needed in that direction).
Whole-repo grep (not just Expert/) caught a real external miss the campaign's
own doctrine warns about: Signals/SignalMETA.mqh read m_spreadSeries/
m_spreadSeriesBars directly as an inherited protected field (a subclass, not
an AIBase/*.mqh partial) - fixed with two new FeatureSpreadSeriesBars()/
FeatureSpreadSeriesAt() forwards.
Verified: if(/for(/while( counts identical between the original file and the
new split (269/20/1); return-count delta (+12) fully accounted for by the 12
new trivial one-line forwards added (10 indicator BufferResize + 2 spread-
series getters); quoted-string-literal diff empty except two doc-comment
paraphrases. Self-compiled 0 errors, 0 warnings.
2026-08-24 00:00:31 -04:00
|
|
|
//| Indicator lifecycle for the price/time/ATR/ZigZag series that |
|
|
|
|
|
//| stay signal-owned - genuinely shared with Labels.mqh/AutoTune.mqh/|
|
|
|
|
|
//| Training.mqh, which read them directly, so their Create/ |
|
|
|
|
|
//| BufferResize/Refresh lifecycle would need a pure-relay wrapper per|
|
|
|
|
|
//| operation per indicator to move with no coupling benefit (same |
|
|
|
|
|
//| judgment as Topology.mqh's InitNeuralNetwork boot sequence). The |
|
|
|
|
|
//| per-bar input feature vector, the 10 feature-only indicator |
|
|
|
|
|
//| handles and everything else that used to live here is now in |
|
|
|
|
|
//| Expert\Features\FeatureBuilder.mqh (CFeatureBuilder, m_featureBuilder). |
|
|
|
|
|
//| ResizeBuffers()/RefreshData() size/refresh CFeatureBuilder's owned|
|
|
|
|
|
//| indicators too, through the Feature*BufferResize()/Feature*Refresh() |
|
|
|
|
|
//| forwards it publishes for exactly that purpose. |
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
#ifndef WARRIOR_AIBASE_FEATURES_MQH
|
|
|
|
|
#define WARRIOR_AIBASE_FEATURES_MQH
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::ResizeBuffers(int barIndex)
|
|
|
|
|
{
|
ditch(features): remove the eight dead feature groups from the input matrix
RSI, MACD, Ichimoku and the five AD/Wyckoff indicators (CumulativeDelta,
ShorteningOfThrust, WyckoffEventStream, WyckoffFailedStructure,
WyckoffSignificantBarInversion). All eight inputs shipped false and each carries a
closed verdict: the three oscillators are the same patterns that measured at chance
as entries, and the Wyckoff family returned zero out-of-sample on five independent
instruments - which is what closed the context score.
RETRAIN-NEUTRAL, and this one is worth stating precisely because the change looks
larger than it is. Every removed group contributed `flag ? N : 0` to the input
width, and every flag was false, so the width was ALREADY zero for all eight: no
.nnw's input layer changes. On the fingerprints, UseRSI and the five AD flags were
hashed unconditionally and become literal 0 legacy slots (the convention the
m_focalGamma slot above them already uses); UseMACD/UseIchimoku were appended only
when enabled, so their segments simply never appear - byte-identical to every
fingerprint ever produced, since neither ever shipped on.
CADIndicatorTuner IS DELIBERATELY NOT SHRUNK. Its flat parameter array is persisted
inside every .nnw, and Unflatten() rejects a size mismatch by falling back to
constructor defaults - so dropping the dead fields would silently revert the tuned
MA period of every model on disk while keeping its trained weights. That is the
feature/weight mismatch this project has already paid for twice, and it is not
worth 200 lines. AD_TUNE_PARAM_COUNT stays 42, the dead slots are still written and
read, and AutoTune's ParamOwner gate now matches only owner 5 (MA) so nothing
searches them. The class comment says all of this at the declaration.
Also renamed ReInitADIndicators -> ReInitTunableIndicators: it rebuilds exactly one
indicator now, and a name saying "AD" for the MA handle is the kind of stale label
that gets believed later. Its release-AFTER-recreate ordering is untouched - that
is a documented fix, not bookkeeping.
Compile-verified in the stage copy: 0 errors, 0 warnings, against the same 0/0
baseline.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 09:21:03 -04:00
|
|
|
//--- barIndex for all four now. The Ichimoku feature was the only consumer reaching further back
|
|
|
|
|
//--- than the rest (its Chikou term read m_Close at idx + ichiKijun); it was removed 2026-08-24,
|
|
|
|
|
//--- so the close series no longer needs the extra depth.
|
|
|
|
|
if(!m_Open.BufferResize(barIndex) || !m_Close.BufferResize(barIndex) || !m_High.BufferResize(barIndex) || !m_Low.BufferResize(barIndex))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
return false;
|
|
|
|
|
if(m_useVolumes)
|
|
|
|
|
{
|
refactor(features): FeatureBuilder is a real collaborator, not a raw-include partial
Expert/AIBase/Features.mqh (2017 lines, 38 methods) split by exclusivity grep
(whole-repo, not just Expert/): 30 methods -> Expert/Features/FeatureBuilder.mqh
(CFeatureBuilder + CFeaturesView/CAIBaseFeaturesView), 8 stay behind as a much
smaller raw partial.
CFeatureBuilder is STATEFUL, same shape as Excursion/OnlineLearning: owns the
10 feature-only indicator handles (m_Volumes/m_MA/m_RSI/m_MACDFeature/
m_Ichimoku/5 AD* CiCustom indicators - grep-verified touched nowhere else in
the repo, only their bare declarations) plus the depth-probe/handle-repair/
spread-series/detectability-latch scalars (exclusive, Lifecycle.mqh ctor-init
only elsewhere). m_Open/m_Close/m_High/m_Low/m_Time/m_ATR/m_ADZigZag stay
signal-owned - Labels.mqh/AutoTune.mqh/Training.mqh read them directly - and
are reached read-only through the view (FeatureOpenAt/FeatureHighAt/
FeatureLowAt/ChartBarClose/ChartBarTime/OnlineAtrMain, all reused where a
forward already existed).
Deliberately did NOT move InitOpen/InitClose/InitHigh/InitLow/InitTime/
InitADZigZag/ResizeBuffers/RefreshData: they manage the 7 shared indicators'
Create/BufferResize/Refresh lifecycle, which would need a pure-relay wrapper
per operation per indicator for zero coupling benefit - same judgment as
Topology's boot sequence. They stay in Expert/AIBase/Features.mqh and reach
CFeatureBuilder's 10 owned indicators through 20 new Feature*BufferResize()/
Feature*Refresh() forwards (signal calling into its own owned collaborator
directly, no view needed in that direction).
Whole-repo grep (not just Expert/) caught a real external miss the campaign's
own doctrine warns about: Signals/SignalMETA.mqh read m_spreadSeries/
m_spreadSeriesBars directly as an inherited protected field (a subclass, not
an AIBase/*.mqh partial) - fixed with two new FeatureSpreadSeriesBars()/
FeatureSpreadSeriesAt() forwards.
Verified: if(/for(/while( counts identical between the original file and the
new split (269/20/1); return-count delta (+12) fully accounted for by the 12
new trivial one-line forwards added (10 indicator BufferResize + 2 spread-
series getters); quoted-string-literal diff empty except two doc-comment
paraphrases. Self-compiled 0 errors, 0 warnings.
2026-08-24 00:00:31 -04:00
|
|
|
if(!FeatureVolumesBufferResize(barIndex))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Unconditional - see InitTime()'s call site in InitIndicators() for why m_Time must always be live.
|
|
|
|
|
if(!m_Time.BufferResize(barIndex))
|
|
|
|
|
return false;
|
|
|
|
|
if(m_useMA)
|
|
|
|
|
{
|
2026-08-22 00:25:52 -04:00
|
|
|
//--- NOT barIndex + 1, though the MA block does read GetData(idx) AND GetData(idx + 1) for
|
|
|
|
|
//--- its bar-over-bar change. The read at the OLDEST bar is SUPPOSED to fail: there is no
|
|
|
|
|
//--- older bar to difference against.
|
refactor(features): FeatureBuilder is a real collaborator, not a raw-include partial
Expert/AIBase/Features.mqh (2017 lines, 38 methods) split by exclusivity grep
(whole-repo, not just Expert/): 30 methods -> Expert/Features/FeatureBuilder.mqh
(CFeatureBuilder + CFeaturesView/CAIBaseFeaturesView), 8 stay behind as a much
smaller raw partial.
CFeatureBuilder is STATEFUL, same shape as Excursion/OnlineLearning: owns the
10 feature-only indicator handles (m_Volumes/m_MA/m_RSI/m_MACDFeature/
m_Ichimoku/5 AD* CiCustom indicators - grep-verified touched nowhere else in
the repo, only their bare declarations) plus the depth-probe/handle-repair/
spread-series/detectability-latch scalars (exclusive, Lifecycle.mqh ctor-init
only elsewhere). m_Open/m_Close/m_High/m_Low/m_Time/m_ATR/m_ADZigZag stay
signal-owned - Labels.mqh/AutoTune.mqh/Training.mqh read them directly - and
are reached read-only through the view (FeatureOpenAt/FeatureHighAt/
FeatureLowAt/ChartBarClose/ChartBarTime/OnlineAtrMain, all reused where a
forward already existed).
Deliberately did NOT move InitOpen/InitClose/InitHigh/InitLow/InitTime/
InitADZigZag/ResizeBuffers/RefreshData: they manage the 7 shared indicators'
Create/BufferResize/Refresh lifecycle, which would need a pure-relay wrapper
per operation per indicator for zero coupling benefit - same judgment as
Topology's boot sequence. They stay in Expert/AIBase/Features.mqh and reach
CFeatureBuilder's 10 owned indicators through 20 new Feature*BufferResize()/
Feature*Refresh() forwards (signal calling into its own owned collaborator
directly, no view needed in that direction).
Whole-repo grep (not just Expert/) caught a real external miss the campaign's
own doctrine warns about: Signals/SignalMETA.mqh read m_spreadSeries/
m_spreadSeriesBars directly as an inherited protected field (a subclass, not
an AIBase/*.mqh partial) - fixed with two new FeatureSpreadSeriesBars()/
FeatureSpreadSeriesAt() forwards.
Verified: if(/for(/while( counts identical between the original file and the
new split (269/20/1); return-count delta (+12) fully accounted for by the 12
new trivial one-line forwards added (10 indicator BufferResize + 2 spread-
series getters); quoted-string-literal diff empty except two doc-comment
paraphrases. Self-compiled 0 errors, 0 warnings.
2026-08-24 00:00:31 -04:00
|
|
|
if(!FeatureMaBufferResize(barIndex))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// Unconditional (not gated by m_useATR): the ATR-normalization in BufferTempData() reads
|
|
|
|
|
// m_ATR.Main() regardless of whether ATR is enabled as an explicit extra input feature -
|
|
|
|
|
// m_useATR only controls that feature-count opt-in (see InitIndicators()'s "already init in the
|
|
|
|
|
// base class" comment), not whether ATR data itself needs to be kept live.
|
|
|
|
|
if(!m_ATR.BufferResize(barIndex))
|
|
|
|
|
return false;
|
2026-08-24 18:26:25 -04:00
|
|
|
// Unconditional, same reasoning as m_ATR above - m_zigZag drives the swing-context features AND
|
feat(ai): triple-barrier labels replace exact-pivot ZigZag targets
The 31:1 class imbalance was self-inflicted by the TARGET, not a property
of the market. Labelling only the exact bar where a ZigZag pivot confirms
gave Buy 1164 / Sell 1164 / Neutral 35841, and every correction mechanism
this codebase accumulated sits downstream of that one choice: the
logit-adjusted loss and its range cap, the prior EMA, the +-3.0 output-bias
seed, balanced-accuracy-then-precision selection with its coverage floor,
the recall floor and its catch-22, the alternation gate, NMS, and the four
oversampling designs that collapsed before them.
The reference this engine is built on (references/neuronetworksbook.pdf
ch. 3.1/3.3) also uses ZigZag, but targets the DIRECTION TO THE NEXT
EXTREMUM on every bar - ~50/50 by construction, with no imbalance to
correct at all. It never had this problem because it never asked "is this
the pivot bar".
Labels are now the triple barrier (Lopez de Prado ch. 3), using the EA's
OWN SL_Mode/TP_Mode: does a trade opened at this bar's close reach its
target before its stop, within a horizon. Buy = long resolves, Sell =
short resolves, Neutral = neither. Consequences:
- dir-precision in the era line stops being a proxy and becomes the win
rate of the strategy under its own exit rules.
- Expected balance ~25/25/50 at the shipped 1:3 (gambler's ruin), i.e.
~2:1 instead of 31:1. Measured and logged at the end of the prebuild.
- Spread is charged on both legs, so it is a NET win rate.
- Intrabar ambiguity resolves to the STOP. OHLC cannot order two touches
inside one bar and the optimistic reading is how a backtested edge
becomes a live loss.
ZigZag stays as input features (EnableSwingContext) and now also supplies
the vertical barrier: the horizon is the median confirmed leg length,
snapped to a coarse ladder. Derived, not configured, and deliberately kept
out of the filename fingerprint - a filename keyed on a measured quantity
orphans a trained model the moment the measurement moves.
Removed, because the premise died with the old target:
- the alternation gate. Correct for pivot labels (a ZigZag cannot emit two
same-type pivots in a row, so a repeat was provably a false fire), and
wrong for barrier labels, which answer each bar independently. It also
took its worst consequence with it: a one-sided model previously got ONE
trade per backtest, a hard blocker on marketplace validation.
- SignalClusterWindow now defaults off - it de-duplicated repeats that are
now real trades. Kept as an opt-in display control.
- LABEL_WINDOW_BARS, the pivot-widening pass, ConfirmedZigZagLabel.
- the era-0 output-bias seed now needs a genuinely dominant class (0.70)
rather than 0.40; at ~50% Neutral a +-3.0 seed is a distortion, not a
correction.
Also fixed, both found while wiring the above:
1. RefreshConvergedSignal sized its buffers from a date delta
(Bars(sym, period, dtStudied, TimeCurrent())). dtStudied is a training
watermark; in the tester it is loaded from a live-chart save AHEAD of
the simulated date, so the interval inverted, Bars() returned ~0, and
the buffer came out at exactly m_historyBars - deep enough for the OHLC
window and far too shallow for the Donchian-50 / 20-bar-return / SMA
extension behind it. Inference silently computed DIFFERENT features
from the ones training learned on, live as well as in the tester. Now
sized from what the feature builder actually needs.
2. The barrier horizon is resolved on the deployed path too. A deployed
model never enters Train(), so it never reached the prebuild, and
OnlineLearnStep reads the horizon as its confirmation delay - left at
the fallback it would have backpropped bars whose barriers had not
resolved. Silent lookahead in the one place that writes to a live model.
SL_Mode/TP_Mode join the weights fingerprint: they define the labels now,
so a model trained at 1:3 must never be silently reused at 1:1. This
re-keys every pre-existing model by design - none were trained on this task.
Inference census extended with the vote gate. LongCondition/ShortCondition
open with a readiness check the refresh counters never see; in the tester it
reduces to "the seeded _optcache.nnw must have LOADED", and if it did not,
every vote is hard-zeroed while the model still answers Buy. The old three
counters would have read that as "the model says Neutral" - false, and a
completely different fix. This is the leading candidate for the
zero-direction backtest and the census can now name it in one run.
Both builds compile 0 errors / 0 warnings. Forces a full retrain.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 20:39:49 -04:00
|
|
|
// ComputeBarrierHorizonBars()'s measurement, not an opt-in feature, so it's never gated by an
|
|
|
|
|
// m_use* flag. (It was also the training-label source until the 2026-08-01 triple-barrier relabel.)
|
2026-08-24 18:26:25 -04:00
|
|
|
if(!m_zigZag.BufferResize(barIndex))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
return false;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::RefreshData()
|
|
|
|
|
{
|
2026-08-22 00:25:52 -04:00
|
|
|
//--- CSeries/CIndicator::Refresh() is void - there is no per-call success/failure signal to
|
|
|
|
|
//--- propagate here.
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
m_Open.Refresh(OBJ_ALL_PERIODS);
|
|
|
|
|
m_Close.Refresh(OBJ_ALL_PERIODS);
|
|
|
|
|
m_High.Refresh(OBJ_ALL_PERIODS);
|
|
|
|
|
m_Low.Refresh(OBJ_ALL_PERIODS);
|
|
|
|
|
if(m_useVolumes)
|
|
|
|
|
{
|
refactor(features): FeatureBuilder is a real collaborator, not a raw-include partial
Expert/AIBase/Features.mqh (2017 lines, 38 methods) split by exclusivity grep
(whole-repo, not just Expert/): 30 methods -> Expert/Features/FeatureBuilder.mqh
(CFeatureBuilder + CFeaturesView/CAIBaseFeaturesView), 8 stay behind as a much
smaller raw partial.
CFeatureBuilder is STATEFUL, same shape as Excursion/OnlineLearning: owns the
10 feature-only indicator handles (m_Volumes/m_MA/m_RSI/m_MACDFeature/
m_Ichimoku/5 AD* CiCustom indicators - grep-verified touched nowhere else in
the repo, only their bare declarations) plus the depth-probe/handle-repair/
spread-series/detectability-latch scalars (exclusive, Lifecycle.mqh ctor-init
only elsewhere). m_Open/m_Close/m_High/m_Low/m_Time/m_ATR/m_ADZigZag stay
signal-owned - Labels.mqh/AutoTune.mqh/Training.mqh read them directly - and
are reached read-only through the view (FeatureOpenAt/FeatureHighAt/
FeatureLowAt/ChartBarClose/ChartBarTime/OnlineAtrMain, all reused where a
forward already existed).
Deliberately did NOT move InitOpen/InitClose/InitHigh/InitLow/InitTime/
InitADZigZag/ResizeBuffers/RefreshData: they manage the 7 shared indicators'
Create/BufferResize/Refresh lifecycle, which would need a pure-relay wrapper
per operation per indicator for zero coupling benefit - same judgment as
Topology's boot sequence. They stay in Expert/AIBase/Features.mqh and reach
CFeatureBuilder's 10 owned indicators through 20 new Feature*BufferResize()/
Feature*Refresh() forwards (signal calling into its own owned collaborator
directly, no view needed in that direction).
Whole-repo grep (not just Expert/) caught a real external miss the campaign's
own doctrine warns about: Signals/SignalMETA.mqh read m_spreadSeries/
m_spreadSeriesBars directly as an inherited protected field (a subclass, not
an AIBase/*.mqh partial) - fixed with two new FeatureSpreadSeriesBars()/
FeatureSpreadSeriesAt() forwards.
Verified: if(/for(/while( counts identical between the original file and the
new split (269/20/1); return-count delta (+12) fully accounted for by the 12
new trivial one-line forwards added (10 indicator BufferResize + 2 spread-
series getters); quoted-string-literal diff empty except two doc-comment
paraphrases. Self-compiled 0 errors, 0 warnings.
2026-08-24 00:00:31 -04:00
|
|
|
FeatureVolumesRefresh();
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
}
|
|
|
|
|
// Unconditional - see InitTime()'s call site in InitIndicators() for why m_Time must always be live.
|
|
|
|
|
m_Time.Refresh(OBJ_ALL_PERIODS);
|
|
|
|
|
if(m_useMA)
|
|
|
|
|
{
|
refactor(features): FeatureBuilder is a real collaborator, not a raw-include partial
Expert/AIBase/Features.mqh (2017 lines, 38 methods) split by exclusivity grep
(whole-repo, not just Expert/): 30 methods -> Expert/Features/FeatureBuilder.mqh
(CFeatureBuilder + CFeaturesView/CAIBaseFeaturesView), 8 stay behind as a much
smaller raw partial.
CFeatureBuilder is STATEFUL, same shape as Excursion/OnlineLearning: owns the
10 feature-only indicator handles (m_Volumes/m_MA/m_RSI/m_MACDFeature/
m_Ichimoku/5 AD* CiCustom indicators - grep-verified touched nowhere else in
the repo, only their bare declarations) plus the depth-probe/handle-repair/
spread-series/detectability-latch scalars (exclusive, Lifecycle.mqh ctor-init
only elsewhere). m_Open/m_Close/m_High/m_Low/m_Time/m_ATR/m_ADZigZag stay
signal-owned - Labels.mqh/AutoTune.mqh/Training.mqh read them directly - and
are reached read-only through the view (FeatureOpenAt/FeatureHighAt/
FeatureLowAt/ChartBarClose/ChartBarTime/OnlineAtrMain, all reused where a
forward already existed).
Deliberately did NOT move InitOpen/InitClose/InitHigh/InitLow/InitTime/
InitADZigZag/ResizeBuffers/RefreshData: they manage the 7 shared indicators'
Create/BufferResize/Refresh lifecycle, which would need a pure-relay wrapper
per operation per indicator for zero coupling benefit - same judgment as
Topology's boot sequence. They stay in Expert/AIBase/Features.mqh and reach
CFeatureBuilder's 10 owned indicators through 20 new Feature*BufferResize()/
Feature*Refresh() forwards (signal calling into its own owned collaborator
directly, no view needed in that direction).
Whole-repo grep (not just Expert/) caught a real external miss the campaign's
own doctrine warns about: Signals/SignalMETA.mqh read m_spreadSeries/
m_spreadSeriesBars directly as an inherited protected field (a subclass, not
an AIBase/*.mqh partial) - fixed with two new FeatureSpreadSeriesBars()/
FeatureSpreadSeriesAt() forwards.
Verified: if(/for(/while( counts identical between the original file and the
new split (269/20/1); return-count delta (+12) fully accounted for by the 12
new trivial one-line forwards added (10 indicator BufferResize + 2 spread-
series getters); quoted-string-literal diff empty except two doc-comment
paraphrases. Self-compiled 0 errors, 0 warnings.
2026-08-24 00:00:31 -04:00
|
|
|
FeatureMaRefresh();
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
}
|
|
|
|
|
// Unconditional - see the matching BufferResize() comment above.
|
|
|
|
|
m_ATR.Refresh(OBJ_ALL_PERIODS);
|
2026-08-24 18:26:25 -04:00
|
|
|
m_zigZag.Refresh(OBJ_ALL_PERIODS);
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Initialize Open indicators. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::InitOpen(CIndicators * indicators)
|
|
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
|
|
|
|
if(!indicators.Add(GetPointer(m_Open)))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- initialize object
|
|
|
|
|
if(!m_Open.Create(m_symbol.Name(), m_period))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Initialize Close indicators. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::InitClose(CIndicators * indicators)
|
|
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
|
|
|
|
if(!indicators.Add(GetPointer(m_Close)))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- initialize object
|
|
|
|
|
if(!m_Close.Create(m_symbol.Name(), m_period))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Initialize High indicators. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::InitHigh(CIndicators * indicators)
|
|
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
|
|
|
|
if(!indicators.Add(GetPointer(m_High)))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- initialize object
|
|
|
|
|
if(!m_High.Create(m_symbol.Name(), m_period))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Initialize Low indicators. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::InitLow(CIndicators * indicators)
|
|
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
|
|
|
|
if(!indicators.Add(GetPointer(m_Low)))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- initialize object
|
|
|
|
|
if(!m_Low.Create(m_symbol.Name(), m_period))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Initialize Time indicators. |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
bool CExpertSignalAIBase::InitTime(CIndicators * indicators)
|
|
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
|
|
|
|
if(!indicators.Add(GetPointer(m_Time)))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- initialize object
|
|
|
|
|
if(!m_Time.Create(m_symbol.Name(), m_period))
|
|
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
feat(indicators): run the built-in iMA and MetaTrader's ZigZag; add a classic-vote shift
MA: CustomIndicators\ADMovingAverage is replaced by the built-in iMA (CiMA) on
both consumers - the classic vote and the NN MA input feature. This drops the
five advanced types ALMA/DEMA/ZLEMA/T3/Kalman, which have no iMA equivalent;
MA_TYPE_PRESETS is now ENUM_MA_METHOD's own codes and the tuner searches all
four. It also removes a documented failure mode: a custom indicator's depth is
bounded by TERMINAL_MAXBARS, and m_MA was the one whose feature block REJECTS
the bar on a short read - the "feature 25 fails on every bar" incident of
2026-08-17. A built-in is served at any depth.
MIGRATION. SMA moves from code 5 to 0, so persisted type codes change meaning.
SanitizeMaType() is the single validity rule; TunedPeriods records now carry a
version field and a v1 record remaps 5..8 -> 0..3, falling back to SMA for a
stored advanced type (unrecoverable - old 0..4 are indistinguishable from valid
new codes). Existing .nnw files re-key on their own, because MA_Type is hashed
into the topology fingerprint, so models retrain rather than silently running
on different MA values. EXPECT A FULL RETRAIN.
ZigZag: ADZigZag was a byte-identical rename of MetaQuotes' Examples\ZigZag -
verified by normalising identifiers and stripping comments, 233 significant
lines each with only renamed symbols differing. It now loads the stock one, so
nothing is bundled and MetaQuotes' fixes arrive without a rebuild here. Both
#resource entries are gone.
Classic_Shift: a new input, the BAR the four classic votes evaluate on (0 =
forming, 1 = last closed, default 1). One implementation on CExpertSignalCustom,
inherited by all four rather than repeated per module. Defaults to a sentinel
meaning "unset", so the AI signals and the aggregate keep the stock every_tick
rule and their feature/label alignment is untouched. The META corpus sweep still
takes precedence. CExpertBase::StartIndex turns out to be virtual, so this is a
real override, not the name-hiding the old comment claimed.
Not compiled - MetaEditor compile pending.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:09:58 -04:00
|
|
|
//| Initialize the ZigZag - the training-label source (see |
|
2026-08-24 18:26:25 -04:00
|
|
|
//| m_zigZag's declaration comment). Always run at its stock |
|
feat(indicators): run the built-in iMA and MetaTrader's ZigZag; add a classic-vote shift
MA: CustomIndicators\ADMovingAverage is replaced by the built-in iMA (CiMA) on
both consumers - the classic vote and the NN MA input feature. This drops the
five advanced types ALMA/DEMA/ZLEMA/T3/Kalman, which have no iMA equivalent;
MA_TYPE_PRESETS is now ENUM_MA_METHOD's own codes and the tuner searches all
four. It also removes a documented failure mode: a custom indicator's depth is
bounded by TERMINAL_MAXBARS, and m_MA was the one whose feature block REJECTS
the bar on a short read - the "feature 25 fails on every bar" incident of
2026-08-17. A built-in is served at any depth.
MIGRATION. SMA moves from code 5 to 0, so persisted type codes change meaning.
SanitizeMaType() is the single validity rule; TunedPeriods records now carry a
version field and a v1 record remaps 5..8 -> 0..3, falling back to SMA for a
stored advanced type (unrecoverable - old 0..4 are indistinguishable from valid
new codes). Existing .nnw files re-key on their own, because MA_Type is hashed
into the topology fingerprint, so models retrain rather than silently running
on different MA values. EXPECT A FULL RETRAIN.
ZigZag: ADZigZag was a byte-identical rename of MetaQuotes' Examples\ZigZag -
verified by normalising identifiers and stripping comments, 233 significant
lines each with only renamed symbols differing. It now loads the stock one, so
nothing is bundled and MetaQuotes' fixes arrive without a rebuild here. Both
#resource entries are gone.
Classic_Shift: a new input, the BAR the four classic votes evaluate on (0 =
forming, 1 = last closed, default 1). One implementation on CExpertSignalCustom,
inherited by all four rather than repeated per module. Defaults to a sentinel
meaning "unset", so the AI signals and the aggregate keep the stock every_tick
rule and their feature/label alignment is untouched. The META corpus sweep still
takes precedence. CExpertBase::StartIndex turns out to be virtual, so this is a
real override, not the name-hiding the old comment claimed.
Not compiled - MetaEditor compile pending.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:09:58 -04:00
|
|
|
//| defaults (Depth=12, Deviation=5, Backstep=3) - unlike the AD* |
|
|
|
|
|
//| feature indicators above, this has no tunable-param struct and is |
|
|
|
|
|
//| never touched by AutoTuneIndicators. |
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
//+------------------------------------------------------------------+
|
2026-08-24 18:26:25 -04:00
|
|
|
bool CExpertSignalAIBase::InitZigZag(CIndicators * indicators, bool addToCollection)
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
{
|
|
|
|
|
//--- check pointer
|
|
|
|
|
if(indicators == NULL)
|
|
|
|
|
return (false);
|
|
|
|
|
//--- add object to collection
|
2026-08-24 18:26:25 -04:00
|
|
|
if(addToCollection && !indicators.Add(GetPointer(m_zigZag)))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error adding object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
feat(indicators): run the built-in iMA and MetaTrader's ZigZag; add a classic-vote shift
MA: CustomIndicators\ADMovingAverage is replaced by the built-in iMA (CiMA) on
both consumers - the classic vote and the NN MA input feature. This drops the
five advanced types ALMA/DEMA/ZLEMA/T3/Kalman, which have no iMA equivalent;
MA_TYPE_PRESETS is now ENUM_MA_METHOD's own codes and the tuner searches all
four. It also removes a documented failure mode: a custom indicator's depth is
bounded by TERMINAL_MAXBARS, and m_MA was the one whose feature block REJECTS
the bar on a short read - the "feature 25 fails on every bar" incident of
2026-08-17. A built-in is served at any depth.
MIGRATION. SMA moves from code 5 to 0, so persisted type codes change meaning.
SanitizeMaType() is the single validity rule; TunedPeriods records now carry a
version field and a v1 record remaps 5..8 -> 0..3, falling back to SMA for a
stored advanced type (unrecoverable - old 0..4 are indistinguishable from valid
new codes). Existing .nnw files re-key on their own, because MA_Type is hashed
into the topology fingerprint, so models retrain rather than silently running
on different MA values. EXPECT A FULL RETRAIN.
ZigZag: ADZigZag was a byte-identical rename of MetaQuotes' Examples\ZigZag -
verified by normalising identifiers and stripping comments, 233 significant
lines each with only renamed symbols differing. It now loads the stock one, so
nothing is bundled and MetaQuotes' fixes arrive without a rebuild here. Both
#resource entries are gone.
Classic_Shift: a new input, the BAR the four classic votes evaluate on (0 =
forming, 1 = last closed, default 1). One implementation on CExpertSignalCustom,
inherited by all four rather than repeated per module. Defaults to a sentinel
meaning "unset", so the AI signals and the aggregate keep the stock every_tick
rule and their feature/label alignment is untouched. The META corpus sweep still
takes precedence. CExpertBase::StartIndex turns out to be virtual, so this is a
real override, not the name-hiding the old comment claimed.
Not compiled - MetaEditor compile pending.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:09:58 -04:00
|
|
|
//--- params[1..] mirror ZigZag.mq5's own input order exactly - stock defaults, intentionally not
|
|
|
|
|
//--- sourced from a tunable params struct (see this function's declaration comment)
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
MqlParam params[4];
|
|
|
|
|
params[0].type = TYPE_STRING;
|
feat(indicators): run the built-in iMA and MetaTrader's ZigZag; add a classic-vote shift
MA: CustomIndicators\ADMovingAverage is replaced by the built-in iMA (CiMA) on
both consumers - the classic vote and the NN MA input feature. This drops the
five advanced types ALMA/DEMA/ZLEMA/T3/Kalman, which have no iMA equivalent;
MA_TYPE_PRESETS is now ENUM_MA_METHOD's own codes and the tuner searches all
four. It also removes a documented failure mode: a custom indicator's depth is
bounded by TERMINAL_MAXBARS, and m_MA was the one whose feature block REJECTS
the bar on a short read - the "feature 25 fails on every bar" incident of
2026-08-17. A built-in is served at any depth.
MIGRATION. SMA moves from code 5 to 0, so persisted type codes change meaning.
SanitizeMaType() is the single validity rule; TunedPeriods records now carry a
version field and a v1 record remaps 5..8 -> 0..3, falling back to SMA for a
stored advanced type (unrecoverable - old 0..4 are indistinguishable from valid
new codes). Existing .nnw files re-key on their own, because MA_Type is hashed
into the topology fingerprint, so models retrain rather than silently running
on different MA values. EXPECT A FULL RETRAIN.
ZigZag: ADZigZag was a byte-identical rename of MetaQuotes' Examples\ZigZag -
verified by normalising identifiers and stripping comments, 233 significant
lines each with only renamed symbols differing. It now loads the stock one, so
nothing is bundled and MetaQuotes' fixes arrive without a rebuild here. Both
#resource entries are gone.
Classic_Shift: a new input, the BAR the four classic votes evaluate on (0 =
forming, 1 = last closed, default 1). One implementation on CExpertSignalCustom,
inherited by all four rather than repeated per module. Defaults to a sentinel
meaning "unset", so the AI signals and the aggregate keep the stock every_tick
rule and their feature/label alignment is untouched. The META corpus sweep still
takes precedence. CExpertBase::StartIndex turns out to be virtual, so this is a
real override, not the name-hiding the old comment claimed.
Not compiled - MetaEditor compile pending.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:09:58 -04:00
|
|
|
params[0].string_value = WARRIOR_STOCK_ZIGZAG;
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
params[1].type = TYPE_INT;
|
|
|
|
|
params[1].integer_value = 12; // InpDepth
|
|
|
|
|
params[2].type = TYPE_INT;
|
|
|
|
|
params[2].integer_value = 5; // InpDeviation
|
|
|
|
|
params[3].type = TYPE_INT;
|
|
|
|
|
params[3].integer_value = 3; // InpBackstep
|
2026-08-24 18:26:25 -04:00
|
|
|
if(!m_zigZag.Create(m_symbol.Name(), m_period, IND_CUSTOM, 4, params))
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
{
|
|
|
|
|
printf(__FUNCTION__ + ": error initializing object");
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
feat(indicators): run the built-in iMA and MetaTrader's ZigZag; add a classic-vote shift
MA: CustomIndicators\ADMovingAverage is replaced by the built-in iMA (CiMA) on
both consumers - the classic vote and the NN MA input feature. This drops the
five advanced types ALMA/DEMA/ZLEMA/T3/Kalman, which have no iMA equivalent;
MA_TYPE_PRESETS is now ENUM_MA_METHOD's own codes and the tuner searches all
four. It also removes a documented failure mode: a custom indicator's depth is
bounded by TERMINAL_MAXBARS, and m_MA was the one whose feature block REJECTS
the bar on a short read - the "feature 25 fails on every bar" incident of
2026-08-17. A built-in is served at any depth.
MIGRATION. SMA moves from code 5 to 0, so persisted type codes change meaning.
SanitizeMaType() is the single validity rule; TunedPeriods records now carry a
version field and a v1 record remaps 5..8 -> 0..3, falling back to SMA for a
stored advanced type (unrecoverable - old 0..4 are indistinguishable from valid
new codes). Existing .nnw files re-key on their own, because MA_Type is hashed
into the topology fingerprint, so models retrain rather than silently running
on different MA values. EXPECT A FULL RETRAIN.
ZigZag: ADZigZag was a byte-identical rename of MetaQuotes' Examples\ZigZag -
verified by normalising identifiers and stripping comments, 233 significant
lines each with only renamed symbols differing. It now loads the stock one, so
nothing is bundled and MetaQuotes' fixes arrive without a rebuild here. Both
#resource entries are gone.
Classic_Shift: a new input, the BAR the four classic votes evaluate on (0 =
forming, 1 = last closed, default 1). One implementation on CExpertSignalCustom,
inherited by all four rather than repeated per module. Defaults to a sentinel
meaning "unset", so the AI signals and the aggregate keep the stock every_tick
rule and their feature/label alignment is untouched. The META corpus sweep still
takes precedence. CExpertBase::StartIndex turns out to be virtual, so this is a
real override, not the name-hiding the old comment claimed.
Not compiled - MetaEditor compile pending.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 19:09:58 -04:00
|
|
|
// Must match ZigZag.mq5's #property indicator_buffers exactly (3: main ZigZag buffer + 2
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
// internal INDICATOR_CALCULATIONS buffers), even though only buffer 0 is ever read via
|
|
|
|
|
// GetData() - see the working AD Wyckoff indicators' InitAD*() for the same pattern.
|
2026-08-24 18:26:25 -04:00
|
|
|
m_zigZag.NumBuffers(3);
|
refactor: split CExpertSignalAIBase implementation by responsibility
ExpertSignalAIBase.mqh was 8216 lines: the class declaration followed by 87
method bodies covering training, labelling, feature extraction, persistence,
chart drawing, online learning, the GA auto-tuner and inference, all in one
file. Train() alone is 1492 lines; a change to arrow drawing meant scrolling
past the era loop.
Moved the bodies into Expert\AIBase\, included at the bottom of the original
after the class declaration:
Training.mqh 1607 era loop, plateau ladder, checkpoint select, deploy
Features.mqh 1093 indicator creation + per-bar input feature vector
ChartUI.mqh 634 arrows, arrow persistence, status panel, cleanup
Persistence.mqh 492 .stats/.cfg sidecars, CPU-inference validation, copy
OnlineLearning.mqh 461 live continual learning, EMA shadow, OOS simulator
Labels.mqh 309 ZigZag pivot labels, async label-cache prebuild
AutoTune.mqh 275 genetic tuner (population, crossover, halving)
Inference.mqh 235 softmax, prior calibration, class priors
ExpertSignalAIBase.mqh 8216 -> 3131 (declaration + topology build only)
This is a pure relocation - verified mechanically, not by eye: HEAD's file
reconstructed from the eight partials plus the surviving remainder is
byte-identical to HEAD, span for span (scratchpad verify_split.py). No
declaration moved, no signature changed, no code rewritten, so behaviour is
unchanged by construction.
Compiles 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:42:45 -04:00
|
|
|
//--- ok
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
#endif // WARRIOR_AIBASE_FEATURES_MQH
|