Commit graph Warrior_EA/System
Author SHA1 Message Date
AnimateDread
b035ea29e5 feat(ai): cross-asset currency strength - the first feature not derived from one price series
Every feature the network sees today is a function of the traded symbol's own OHLCV:
returns, ranges, oscillators, cloud distances, swing structure. Measured end to end that
whole family sits at the noise floor (research/test_classic.py, and the mutual-information
verdict before it). EURUSD moving is a statement about EUR and about USD, and which one
moved is invisible from EURUSD alone - but plainly visible if you also look at EURJPY,
GBPUSD and the rest.

System\CrossAsset.mqh builds a currency-strength panel from the FX pairs in Market Watch:
per bar, each currency's index is the average log return across every available pair
containing it, signed so "up" always means that currency strengthened. Six features - base
and quote strength at 1 and 20 bars, the DIVERGENCE between the pair and what its two
currencies separately did, and the cross-sectional dispersion of currency moves as a
regime term. The divergence is the thesis: it is the one value here that cannot be derived
from the traded series at all, being defined only relative to the rest of the market.

Built ONCE per training run against the traded symbol's bar grid, not per bar - a per-bar
cross-symbol lookup would be pairs x 178k iBarShift calls.

Correctness work, all of it driven by what MT5 actually guarantees rather than by what the
API surface suggests:

- Alignment is by TIMESTAMP, never by index. Bars do not open together across symbols, and
  in the tester each symbol gets its own generated tick sequence, so index k on GBPUSD and
  index k on USDJPY are not the same instant. Each traded bar takes the last reference bar
  at or BEFORE its timestamp - never after, which would be lookahead - and anything more
  than one bar period stale is treated as absent rather than carried forward across a
  holiday gap.
- SeriesReady() gates every pair on SymbolSelect + SymbolIsSynchronized + the PER-TIMEFRAME
  SERIES_SYNCHRONIZED. The symbol-wide and per-timeframe flags can disagree because the
  terminal builds series on separate threads, so checking only the first is not enough.
  Non-blocking by design: an unready pair is skipped and picked up on a later build.
- Failure is never fatal. Fewer than two usable pairs logs why and every Features() call
  0-fills, so a missing reference symbol costs the context block rather than the whole run.

Fingerprint: the flag goes in, the DISCOVERED REFERENCE SET does not. Which pairs exist in
Market Watch is a measured property of the terminal, exactly like the bar count the
existing comment warns about - keying the weights filename on it would orphan a trained
model the moment the user adds a symbol, silently, because a missing cache reads as a
normal first run.

Defaults ON, which re-keys existing databases on first run. That is intended: the input
vector genuinely changed shape.

Deliberately NOT built, having checked what the platform actually provides:
- swap/carry. SYMBOL_SWAP_LONG/SHORT have no history - "last values will be used for the
  whole test period" - so a backtest over 2020-2026 applies 2026 carry to 2020 bars.
- signed order flow. TICK_FLAG_BUY/SELL and volume_real are empty on Forex; any feature
  assuming trade direction would silently be all zeros.
- depth of market. Unavailable on retail FX symbols and never replayed in the tester.
- calendar actual-vs-forecast surprise. MqlCalendarValue.actual_value is the FINAL,
  post-revision figure and the calendar keeps no as-of-release snapshot, so a surprise
  feature for a 2019 bar is built from a number nobody had in 2019. Needs a live recorder,
  not a historical read.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 17:16:13 -04:00
AnimateDread
8710240cd5 fix(signals): revive a dead MA model, and demote Sanyaku from state to event
Two defects surfaced by research/test_classic.py, both verified fixed by re-running the
transcription against 178k bars of EURUSD H1.

CSignalMA model 1 could never fire. For any recursive average - and MA_TYPE_EMA is the
shipped default - MA(i) = a*Close(i) + (1-a)*MA(i+1), so

    DiffMA(i)      = a     * (Close(i) - MA(i+1))
    DiffCloseMA(i) = (1-a) * (Close(i) - MA(i+1))

are positive multiples of one quantity and always share a sign. Model 1 asks for a close
BELOW a RISING average, which is precisely the combination that identity forbids: 0.000%
of bars, either direction, any symbol. The MQL5 standard library this was ported from
defaults to MODE_SMA, where the two are merely correlated - the bug arrived with the EMA
default, not with the port. Reading the slope one bar back (DiffMAPrev) breaks the tie for
every MA type while keeping the model's stated meaning. Now fires on 7.92% of bars.

CSignalIchimoku model 11 fired on 27% of bars at weight 100. Sanyaku is three standing
STATES conjoined with no transition term, so it held across long stretches - and being
last in the if-chain at the top weight, the module's highest-conviction reading was also
its most common one, overwriting all eight event models below it on a quarter of all bars.
The old comment rejected an event form because "demanding all three flip on the same bar
would fire almost never" - true, but that is not the alternative. Kouten is the TURN: the
ALIGNMENT transitions, and only one role need change for it to. Testing !Sanyaku(idx+1)
fires once per aligned stretch. Now 2.17%, in line with Kumo breakout (2.4%) and the
strong TK cross (1.1%). DataReady() extended one bar deeper to cover the lookback.

Neither pattern showed edge before or after; this is about the models meaning what they
say and the vote not being dominated by a constant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 17:14:34 -04:00
AnimateDread
d7eea325fb refactor(ai): extract Layer.mqh and deduplicate AI config
- Moves CLayer neuron construction to AI/Impl/Layer.mqh to keep Network.mqh clean
- Unifies four previously duplicated architecture initialisation blocks (MLP/CONV/LSTM/HYBRID) into a single shared function
- Eliminates risk of behavioural drift where one architecture missed a setter, causing mismatched feature sets or targets
2026-08-01 11:27:28 -04:00
AnimateDread
36a2825087 chore(Network): remove unused optimization methods and tidy whitespace
Remove the unused SetOptimization/Optimization virtual getter/setter from
CNeuronBase and the static member `alpha` initialization. These were dead
code. Also fix trailing whitespace inconsistencies in comment blocks.
2026-08-01 11:26:59 -04:00
AnimateDread
41d6a63d92 fix: make sidecar writes atomic; extract shared AtomicFile helper
FileOpen(FILE_WRITE) truncates its target on open. CNet::Save already staged
the .nnw through a temp file + rename for that reason, but the three sidecars
written beside it did not:

  .stats  ExpertSignalAIBase.mqh:5918
  .arrows ExpertSignalAIBase.mqh:6224
  .cfg    ExpertSignalAIBase.mqh:7329

Two defects followed.

1. An interrupted write published a truncated sidecar. For .cfg that is the
   worst case: LoadAndCompareTopologyConfiguration() reads a short file as a
   mismatch, which discards the trained model and restarts from era 0.

2. Windows file sharing is a mutual contract - a writer opened with no
   FILE_SHARE_* blocks every concurrent open regardless of the reader's flags.
   All three read paths carry FILE_SHARE_READ|FILE_SHARE_WRITE specifically so
   a tester agent can read them while a live chart runs; an exclusive writer on
   the same path defeated that.

Extracted CNet::Save's proven pattern into System\AtomicFile.mqh
(AtomicWriteBegin/AtomicWriteEnd) and routed all four writers through it. This
also encodes the FileMove gotcha once instead of per call site: the destination
location comes from FILE_COMMON inside the 4th arg, NOT inherited from the
source, and getting it wrong moves the file to the wrong sandbox silently.

Also fixed while in these functions:

- SaveTopologyConfiguration had 13 copy-pasted 6-line error blocks that each
  returned WITHOUT FileClose(handle), leaking the handle on every write
  failure. Collapsed to one ok-chain that closes exactly once. The on-disk
  field order and types are unchanged (asserted during the rewrite) so existing
  .cfg files still load.

- SaveChartSignals documented that pruning runs only after a successful write
  ("a failed write above leaves both the file AND the chart untouched") but
  never checked any write result, so a partial write still deleted the chart
  objects. Results are checked now, making the existing comment true.

Compiles 0 errors, 0 warnings.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-29 00:31:29 -04:00
AnimateDread
3a37b9115e fix: correct inference-only new-bar detection and add stop validation
In inference-only backtests, dtStudied could be ahead of the test range, causing new-bar detection to freeze. Replaced with m_lastBarTime to keep detection aligned with runtime history. Added diagnostic logging when a non-neutral softmax output is neutralized by prior correction. Also added validation for order_price, sl, and tp in stop-checking functions to catch non-finite or negative values.
2026-07-27 11:51:45 -04:00
a228d1bde7 feat(trade): implement trade safety checks per Article 2555 and resource limits
Add freeze-level checks, no-change modification skipping, entry price routing, and per-tick/memory budget monitoring. Override trade actions (Open, Close, Reverse, TrailingStop, TrailingOrder) to validate at the final gate before sending orders.
2026-07-26 23:08:32 -04:00
AnimateDread
5247c34fe9 fix: add error logging for buffer failures and reject trades on invalid stop loss 2026-07-26 12:12:14 -04:00
AnimateDread
d0e89a6fc7 fix(SignalNewsFilter): scope calendar veto to the traded symbol's own currencies
CalendarValueHistory() was called with no country filter at all, so
ANY country's economic calendar event vetoed a trade regardless of
relevance - a JPY release blocked a EURUSD trade just as readily as a
USD one, making NF_MinImpact's fine-tuning far noisier than intended.

Adds System/NewsRelevance.mqh (GetRelevantCountryCodes/
ImpactWeightedProximity), a shared utility that cross-references
CalendarCountries() against the symbol's base/quote currency to get
the actually-relevant ISO country codes, then uses
CalendarValueHistory()'s country_code-filtering overload. Shared so
the upcoming NN news-input feature reuses the same relevance logic
rather than duplicating it.

Compiled clean (MetaEditor, 0 errors/0 warnings).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 17:22:33 -04:00
AnimateDread
ef95e19d1d fix: correct metric label in training output and improve status panel comments 2026-07-17 21:53:09 -04:00
AnimateDread
fe4c93cf71 refactor: simplify on-chart status text and remove verbose metrics
The training status panel was too tall and wordy, displaying detailed recall, precision, and continual-learning OOS simulation metrics that are not needed for at-a-glance monitoring. These metrics are still tracked internally for convergence gating, but removed from the on-chart display to keep the panel compact. Also shortened label names (e.g., "[IS] Accuracy" -> "IS Acc") to save space without reducing clarity.
2026-07-17 21:49:30 -04:00
AnimateDread
6f3daf23a3 fix(System/StatusLabel): correct type mismatches in TextGetSize usage
TextGetSize returns uint values, so dummyW, dummyH, textW, and textH
changed to uint. Added explicit casts to int where used in comparisons
or arithmetic to prevent signed/unsigned mismatch warnings.
2026-07-17 21:37:52 -04:00
AnimateDread
a2ed4e3682 fix: word-wrap status labels via TextGetSize() to fix clipping and background overflow
Replace the static per-character width approximation with dynamic word-wrapping using
`TextGetSize()` to measure actual rendered pixel widths. This prevents status label text
from being clipped at the chart edge while its oversized background rectangle extended
beyond. Each line is now greedily wrapped to fit within the chart pane minus margins,
ensuring the measured string matches what is drawn. Also extracts font constant and adds
`WrapLineInto()` helper for reuse.
2026-07-17 21:36:44 -04:00
AnimateDread
bb9edfc119 fix(status-label): handle multi-line status text with per-line labels
OBJ_LABEL does not render embedded '\n' as line breaks, causing multi-line status text to appear as one truncated line. This commit splits the input text by newlines, creates a separate OBJ_LABEL and tightly-fit OBJ_RECTANGLE_LABEL background for each line, ensuring every line remains legible regardless of chart background.
2026-07-17 21:32:55 -04:00
AnimateDread
2c0cdf5e2b refactor(ai): replace Comment() with StatusLabel for training status display
Migrate all per-era classification counts, OOS confusion metrics, and training progress output from the legacy Comment() function to a dedicated StatusLabel object. This provides cleaner UI integration and avoids blocking the chart's normal info line during prolonged training cycles. A new include for StatusLabel.mqh has been added, and all related documentation comments updated accordingly.
2026-07-17 21:28:59 -04:00
AnimateDread
8157c42314 feat: Enhance README and documentation for Warrior_EA project
- Updated README.md with project overview, key features, directory structure, getting started guide, and modernization roadmap.
- Added AI_NETWORK.md detailing the neural network and AI/ML infrastructure, including architecture, components, usage patterns, and next steps.
- Introduced DATABASE.md for the Database module, outlining key components, design highlights, usage patterns, and future enhancements.
- Created README.md files for Enumerations, Expert, Money, Signals, Structures, System, Trailing, Variables directories, detailing their purpose, key components, and integration notes.
- Documented the Signals subsystem, emphasizing modularity, extensibility, and AI/ML readiness.
- Added comprehensive descriptions for individual signal modules in Signals/ directory.
- Established clear integration notes and recommendations for future improvements across all modules.
2026-04-20 19:28:34 -04:00
super.admin
0a527b0cf9 convert 2025-05-30 16:35:54 +02:00