| Nome do ficheiro | Mensagem do último cometimento | Data do último cometimento |
|---|---|---|
BuildFeatureWindow() replaces eight hand-rolled copies of the same loop
and feeds the window OLDEST BAR FIRST. Every copy fed it newest-first,
because MQL5 timeseries indices run backwards and `r + b` with b ascending
walks into the past.
Harmless for PAI and CONV - a dense layer learns a weight per position
either way, a conv learns time-mirrored kernels. Not harmless for the
recurrent stacks:
- LSTM_SeqStepForward reads `inputs + t*Iw`, so step t is block t.
- It writes output[] only when t == steps-1: the visible output IS the
last hidden state.
- c_t = f*c_{t-1} + i*g decays toward the start of the sequence.
lstm_seq_flowcheck.cpp measured block 0's influence on the output at
1.2e-2 of block T-1's, at the shipped forget bias of 1.0.
So the bar being PREDICTED sat at the far end of the decay and the output
was handed to the OLDEST bar in the window - the exact inverse of what the
window is for. ~80x backwards on LSTM and HYBRID, on all three tiers
(OpenCL kernel, CPU DLL, pure-MQL5 inference), which is why it never
surfaced as a backend discrepancy.
This does not create edge - the MI diagnostics read at the noise floor
(p=0.4975) with a working positive control. It makes the one hypothesis
those diagnostics explicitly do NOT cover testable: they are marginal and
per-bar, and state they "cannot rule out one that only exists in
combination or across time". The sequence model is the instrument for
across-time structure and it has been crippled, so that hypothesis has
never been honestly tested.
Fingerprint gets an unconditional |WIN:2 - the vector keeps its shape and
its features, so a stale .nnw would load cleanly and run a model fitted to
one ordering against the other, silently. Re-keying every config is the
point, not collateral damage. FORCES A FULL RETRAIN.
Also: the now-relative bar caches are re-keyed on the two live paths.
EnsureBarCachesCapacity() was only ever called from training paths, but
once m_trainingComplete is set ScheduleTrainingIfNeeded() routes every bar
to RefreshConvergedSignal() and Train() is never re-entered - so nothing
cleared the feature cache again for the life of the process. A chart that
trained to convergence kept replaying the rows computed for the last
training era's bar grid: the live signal froze at its convergence-time
value, and OnlineLearnStep() backpropped those stale features against
freshly resolved labels. Backtests were never affected (an inference-only
process never allocates the arrays, so every read recomputes).
Compiles clean: 0 errors, 0 warnings.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
| .. | ||
| AIBase | ||
| ADIndicatorTuner.mqh | ||
| ExpertCustom.mqh | ||
| ExpertMoneyCustom.mqh | ||
| ExpertSignalAIBase.mqh | ||
| ExpertSignalCustom.mqh | ||
| README.md | ||
Expert/ Directory Documentation
Market-submission compliance (article 2555)
Every runtime check from
The Checks a Trading Robot Must Pass Before Publication in the Market
is implemented in System/TradeChecks.mqh (free functions, TC* prefix) and applied by the classes
in this folder. Where each rule lives:
| # | Rule | Implemented in |
|---|---|---|
| 1 | Catch/fix errors via the tester | Development practice; every rejection below logs a throttled reason |
| 2 | Insufficient funds | TCCheckMoneyForTrade / TCFitVolumeToFreeMargin, applied by CExpertMoneyCustom::ValidateLotForTrade |
| 3 | Invalid volumes | TCCheckVolumeValue / TCNormalizeVolume, same call site |
| 4 | Pending-order count limit | TCIsNewOrderAllowed, checked in CExpertSignalCustom::OpenParams and again in CExpertCustom::OpenLong/OpenShort |
| 5 | Per-symbol lot limit | TCSymbolVolumeAllowed / TCApplySymbolVolumeLimit |
| 6 | SYMBOL_TRADE_STOPS_LEVEL |
TCCheckStops / TCAdjustStops / TCCheckPendingPrice, applied when the setup is shaped and again immediately before the order is sent |
| 7 | SYMBOL_TRADE_FREEZE_LEVEL |
TCFreezeOkForPosition / TCFreezeOkForOrder, gating close, reverse, trailing, order modify and order delete in CExpertCustom |
| 8 | Insufficient quote history | TCHasEnoughHistory, in CExpertCustom::Refresh and CExpertSignalCustom::OpenParams |
| 9 | Array out of range | TCIndexOk, plus the existing index guards (iLowest/iHighest return values, Direction()'s bounded loops) |
| 10 | Zero divide | TCSafeDivide, plus explicit zero-denominator guards on every volume-step / loss division |
| 11 | Modification with no changes | TCPositionModifyIsMeaningful / TCOrderModifyIsMeaningful, in the TrailingStop* / TrailingOrder* overrides |
| 12 | No DLL imports | Build-time: WARRIOR_MARKET_BUILD compiles out the #import blocks in AI/NeuronDirectML.mqh |
| 13 | No external iCustom |
Build-time: #resource block in Warrior_EA.mq5 + WARRIOR_CI() in Variables/IndicatorResources.mqh |
| 14 | Invalid function parameters | TCSymbolIsTradeable, plus the existing ValidationSettings() range checks |
| 15 | Access violation | No runtime check exists by definition; the NULL-pointer and index guards above are what prevent it |
| 16 | CPU / memory consumption | TCWarnIfSlow on each OnTick pass (EXPERT_TICK_BUDGET_US) and TCWarnIfMemoryAbove on each timer pass (EXPERT_MEMORY_SOFT_LIMIT_MB) |
All rejections report through TCLog(), which throttles per condition so a state that persists for
many ticks writes one journal line per minute instead of thousands.
Class hierarchy
CExpert -> CExpertCustom (event dispatch, order lifecycle, article-2555 gates)
CExpertMoney -> CExpertMoneyCustom (volume correction, margin fitting)
CExpertSignal -> CExpertSignalCustom -> CExpertSignalAIBase -> CSignalPAI/CONV/LSTM/HYBRID
ExpertCustom.mqh
Base expert. Virtual handlers for OnTick / OnTimer / OnChartEvent, trading-object
setup, series refresh, and the freeze/stops-level gates applied immediately before every
send, modify and delete.
ExpertMoneyCustom.mqh
CheckAndCorrectVolumeValue— clamps volume to the broker's min/max/step and describes each correction.CheckAndAdjustMoneyForTrade— reduces lots to fit free margin rather than failing the order outright.ValidateLotForTrade— the single gate for rules 2/3/5/14, with throttled logging.
ExpertSignalCustom.mqh
Shared non-AI signal machinery: database-backed signal tracking, pattern weighting,
OpenParams() (which shapes SL/TP and applies the min-R:R rejection), and the filter
collection. SL_Mode/TP_Mode live here — note they define the AI training target
as well as the order, since the triple-barrier label is built from them.
There is no duplicate-trade detection. Three methods that implied otherwise were declared but never defined or called, and were removed in 2026-07. Do not assume the guard exists.
ExpertSignalAIBase.mqh
The AI signal base class. The declaration lives here; the method bodies are split by
responsibility into Expert/AIBase/ and included at the bottom of the file, after the
declaration. Include them nowhere else.
Expert/AIBase/ |
holds |
|---|---|
Training.mqh |
era loop, plateau ladder, checkpoint selection, auto-deploy |
Topology.mqh |
network bootstrap, derived shape, conv/LSTM/batch-norm stages |
Features.mqh |
indicator creation, per-bar input feature vector |
ChartUI.mqh |
arrows, arrow persistence, status panel, cleanup |
Lifecycle.mqh |
ctor/dtor, the vote API, tick + chart-event dispatch, config lock |
Persistence.mqh |
.stats / .cfg sidecars, CPU-inference validation |
OnlineLearning.mqh |
live continual learning, EMA shadow, OOS simulator |
Labels.mqh |
triple-barrier labels, async label-cache prebuild |
AutoTune.mqh |
indicator auto-tuner |
Inference.mqh |
softmax, prior calibration, class priors |
The topology is derived, not configured — width, taper, depth, conv filters and LSTM
hidden size all come from the data shape. See Topology.mqh and Variables/Inputs.mqh
for which inputs were removed and why.