Corrects d70efc0, shipped an hour earlier, on the operator's report that historical
spread is not accessible from this terminal.
THE SOURCE WAS WRONG. d70efc0 read MqlRates.spread out of the bar history via
CopySpread, reasoning that a historical book should be charged the historical
spread. The reasoning is appealing and the data does not support it: that field is
only populated for bars the broker's own feed recorded, and anything backfilled,
imported or synthesised carries a constant or the spread at download time. A cost
that is silently constant is WORSE than no cost at all, because it looks measured -
it would have passed every review while charging a made-up number.
SPREAD IS NOW SAMPLED LIVE, Ask - Bid, ONCE PER BAR. Per bar and not per tick
deliberately: per-tick sampling weights busy hours, and busy hours are the
tight-spread ones, so the mean would be biased low - understating exactly the cost
this gate exists to charge. The running mean PERSISTS across restarts in a terminal
GlobalVariable, so it accumulates a real distribution over however long the fleet
has been up instead of resetting to a single tick on every deploy; past
WARRIOR_COST_SAMPLE_CAP samples it becomes an EMA so a genuine regime change can
still move it.
COMMISSION IS NOT A SYMBOL PROPERTY IN THIS BUILD, and this was put to the compiler
rather than assumed. A probe file compiled against this terminal returns:
error 256: undeclared identifier 'SYMBOL_COMMISSION'
error 256: undeclared identifier 'SYMBOL_TRADE_FEE'
error 256: undeclared identifier 'SYMBOL_COMMISSION_TYPE'
while SYMBOL_ASK / SYMBOL_BID / SYMBOL_SWAP_LONG / SYMBOL_TRADE_TICK_VALUE in the
same file compile clean, so the probe itself was sound. The Symbol Specification
DIALOG shows a commission for many brokers; MQL5 is not given it. The only
programmatic ground truth is DEAL_COMMISSION on an executed deal
(Database\TradeJournalManager.mqh already reads it), which is useless before the
book has traded.
So it is an INPUT - Cost_CommissionPerLotPerSide, account currency per lot per
side, the way brokers quote it. Doubled for the round turn and converted to price
through tickSize/tickValue. ZERO IS A REAL ANSWER (spread-only accounts exist) and
means the gate charges spread alone; it is not a way to disable the test. It ships
at 0.0, so until an operator sets it the gate is charging spread only and says so.
THE PER-ROW ARRAY IS NOT REDUNDANT at a constant spread: cost is expressed in the
BAR'S OWN ATR, so a quiet bar is genuinely dearer to trade than a volatile one and
the number still varies row to row.
THE LIMITATION, STATED RATHER THAN HIDDEN: this charges a HISTORICAL book the
CURRENT spread regime. No data available to this terminal can remove that
assumption, so it is written into the module header and is the first thing an
operator should challenge.
CFeatureBuilder::SpreadPointsAt keeps its body and loses its claim: its comment
said it existed for the deploy gate, which stopped being true with this commit. It
still backs the spread FEATURE, where a constant column merely fails the keep-screen
- a safe failure, which as a cost it is not.
Not retrain-forcing.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This repo now holds only EA (MQL5) sources. The Python research scripts and the
third-party MQL5/PDF reference material live in a sibling workspace folder,
..\Warrior_Research\, with their own git repo (initial commit ec2214a there).
Nothing in the EA depends on either folder at build or run time, and the research
scripts address ..\Market Data\ and the MetaTrader Common\Files directory by
absolute path, so the relocation breaks no path. EA comments that cite scripts by
name (research/edge.py, research/altdata/export.py, research/test_spread.py, ...)
stay accurate - only the parent folder moved.
.gitignore drops the two rules that only existed for the moved trees
(references/*.pdf, research/edge_rows.npy); they were carried over to the new repo.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CFirstPassageLadder (RungFor/StoreBar/FirstTouch/OutcomeR/WinShare),
CTripleBarrier+CLabelOverlap (ApplyMinStopWidening/ComputeLevels/SnapToLadder,
the label-overlap effective-sample-size correction), CMetaFamilies (the
classic-pattern taxonomy + table-naming rule), SGeometryScan::Reset() (guards
against 7452bd1's partial-reset shape recurring) and System/BinomialStats.mqh
(every deploy-gate/edge-floor formula this codebase shares). Each is a small
.mq5 Expert Advisor under Tests\ printing PASS/FAIL per assertion via
Print(), sharing Tests\TestHarness.mqh. All 5 self-compile-verified 0
errors/0 warnings. FirstPassageLadder.mqh/TripleBarrier.mqh expect
BARRIER_LADDER_COUNT/BARRIER_LADDER/BARRIER_HORIZON_LADDER_COUNT predefined
by their includer (normally ExpertSignalAIBase.mqh); the test EAs define
copies matching production values rather than including the whole AIBase
chain. SGeometryScan is reproduced verbatim from ExpertSignalAIBase.mqh for
the same reason, flagged in-file as needing to stay byte-identical.
Also adds Tests\convert_sample_data.py, which runs research/sqxbars.py's
decoder against a COPY of SP500_the5ers_H1.dat (never the SQX install
itself) so the operator has real sample data to point a manual tester run
at. Decodes structurally (52,542 H1 bars, monotonic, 0 high<low violations)
without calibrating a price scale - sqxbars.load()/sqx.calibrate_decimals()
both require a validated reference series to do that safely, which this
self-contained script does not have. Tests\sample_data\ (the raw copy +
decoded .npz) is gitignored, same policy as the existing Market Data/ rule.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
40 MB of third-party copyrighted books sit in references/ so the research
scripts can read them. Untracked is not the same as safe: one broad
`git add -A` puts them in history permanently and on a public remote.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A 2.1 GB tick .dat was committed in c7e9777 by a broad 'git add -A' and removed again in
6bb3386 - but a delete does not remove the blob from history, so the 2096 MB object is
still reachable and still gets pushed. That is what made syncing hang.
Ignoring the paths only prevents a recurrence; clearing the existing blob needs a history
rewrite, which is the user's call since it rewrites pushed commits.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Introduce per-bar feature cache to avoid redundant recomputation of input vectors during training.
- Rename EnsureLabelCacheCapacity to EnsureBarCachesCapacity to reflect management of both label and feature caches.
- Fix oversampling logic to maintain balanced representation among minority classes, replacing independent 5x caps that caused relative bias.