Commit graph Warrior_EA/Database/TradeJournalManager.mqh
Author SHA1 Message Date
AnimateDread
17270ab308 feat(trade): two books per symbol, and delete the vote exit
Allow_Hedging (default ON, live only on a RETAIL_HEDGING account) gives the EA
an independent long book and short book on its symbol: at most one long and at
most one short, each opened on its own side's vote and each held to its own
barrier. On a netting account, or with the input off, the original
single-position path runs bit-for-bit unchanged and init says which one is live.

WHY THIS INSTEAD OF A VOTE EXIT. The deploy gate certifies
P(label agrees | vote fired) and the label runs to the barrier, so closing early
on a reversal makes the realised outcome stop being the labelled one - the
certified precision no longer describes what is traded. Opening the other side
acts on the new signal and leaves the old position's certification intact, and
costs no more than reversing: both pay the new side's spread, the difference is
only that the existing position runs on to a barrier already measured as
positive-expectancy. So Signal_ThresholdClose is DELETED rather than tuned,
along with its SIGNAL_CLOSE_PRESETS enum; the threshold is pinned to an
arithmetically unreachable 101 (the stock default of 100 is reachable by a
weighted mean of values capped at 100).

Note the two books can never both fill from one signal: CheckOpenLong and
CheckOpenShort test opposite signs of the same m_direction, so at most one clears
per tick. A hedge only forms when a LATER opposite vote fires - which is what
keeps it from being a guaranteed-loss wash pair.

The mechanism is a SelectPosition() override keyed on the active book's magic;
every inherited close/trail path then operates on that book untouched. The long
book keeps Expert_MagicNumber, so no existing position, journal row or
risk-budget state file is re-addressed. Short book is +1.

Four ownership filters had to widen from "== m_magic" to WarriorOwnsMagic(),
or the short book would have been invisible to the code that must reach it:
the scheduled close-all (positions and orders), the risk budget's emergency
flatten, and the journal's MAE/MFE walk. WarriorOwnsMagic() is deliberately NOT
gated on Allow_Hedging - turning the input off while a short-book position is
open would otherwise orphan it with nothing left to close it.

Risk sizing needed no change: CapRiskAmount already subtracts OpenRiskAtStops(),
which counts every position regardless of magic, so the second book is sized
inside what the first one left. Conservative for a hedged pair, which cannot
lose both stops - the safe direction.

Retrain-neutral: neither input is in BuildModelFingerprint() or
ComputeDbConfigFingerprint(). Compiled clean; NOT yet run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-26 09:20:35 -04:00
AnimateDread
8ed54e25fb refactor(db): split GenerateReport into fetch/aggregate/derive/write
CTradeJournalManager::GenerateReport() mixed four jobs in one
211-line method: DB fetch, per-hour/day/confidence aggregation,
suggestion-derivation, and CSV formatting. Split into
FetchClosedTrades/AggregateJournalStats/DeriveSuggestions/
WriteJournalReportCsv, each independently testable/replaceable;
GenerateReport is now a 12-line orchestrator. AggregateJournalStats
touches no class member so it stays a free function alongside the
existing JournalBucket* helpers (moved next to SJournalStats, ahead
of the class, since the new method signatures reference it);
Fetch/Derive/Write stay private methods since Derive needs the
already-private AddSuggestion. Pure relocation - every quoted string
literal and if/for/return count verified identical (net of the
intentional new step-boundary guards/returns) against the pre-edit
file.
2026-08-24 03:55:25 -04:00
AnimateDread
48c1dc5c23 refactor(journal): dedupe the 5 append-suggestion sites in GenerateReport
CTradeJournalManager::AddSuggestion() does the resize+assign+increment
once; the hour/dow/near-miss/sl-tight/confidence-tier suggestion sites
now each call it with their already-built StringFormat text. Pure
textual relocation, no arithmetic or ordering change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:43:31 -04:00
AnimateDread
f64e0f8b67 feat(ensemble): per-NN inputs replace the preset selector - the meta head becomes the vote's gate
User design (2026-08-19): 'remove the enum menu that selects neural networks... individual
inputs for every NN just like classic signals... the META NN should be integrated into the
voting decision pipeline when enabled... as a bonus meta labelling is applied to enabled NNs.'

- AI_CHOICE is GONE (tombstoned per the stale-.set doctrine). Use_MLP/Use_CONV/Use_LSTM/
  Use_CONVLSTM are ordinary bools like the classic votes; the ensemble arithmetic adapts to
  any subset because the consensus divisor is the enabled capable weight. Two or more
  enabled = ensemble (|ENS1 token + joint gate, exactly the old AI_HYBRID fingerprints, so
  existing weight files keep loading); one = the old solo preset; none = classic-only.
- Use_MetaLabeling un-couples META from the direction NNs (the old selector made them
  mutually exclusive). S3 ships: CSignalMETA::LiveMetaGate scores each vote-cleared entry
  (shared window at bar 1 + proposal descriptor: side, net vote, live geometry, spread/ATR;
  pattern one-hot ZEROED - ranking, not calibrated probability, documented in the body) and
  vetoes below the cost-adjusted break-even. Entries only; fail-open everywhere, loudly.
- COEXISTENCE HAZARDS closed: VoteCapableWeight()=0 and ProspectiveVote()=false for the
  meta target - solo-only until today, a trained META would otherwise sit in the consensus
  divisor as a permanent abstainer and shrink every vote by its module weight.
- CERTIFIED == TRADED: the ensemble era verdict replays the identical veto through the same
  g_warriorMetaGate pointer over its OOS fired bars (bar re-resolved from the row's own
  time; fail-open counted as fires and reported: 'metaGate: N approved, M vetoed, K
  unscored'). The overlay deliberately does NOT replay it (veto-filter-in-replay class,
  calendar-cliff precedent) - documented at the sweep site. Solo charts' own gate does not
  model the veto - the standing solo-gate caveat, documented at the input.
- DB continuity: the pattern/journal DB fingerprint's first slot was (int)AIType;
  DbLegacyAiSlot() maps every legacy-expressible config to its OLD value (new 2-3 member
  subsets get 100+bitmask, outside the legacy range) so no existing database re-keys.
  filterID becomes the enabled roster via one EnabledNNSummary().
- HUD: the meta line shows the gate (armed/(trn), last P vs BE, ok/veto tally); the
  armed/disarmed announcement fires on state change via one latch (MetaGateArmedNow), not
  only when an entry happens to be proposed.

NOT COMPILED - user compiles in MetaEditor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-19 13:01:02 -04:00
AnimateDread
77e8080cfe fix: four risk-layer holes a funded account would eventually find
1. The expectancy stop was stone dead at shipped defaults. Its only feed -
   RecordTradeResult inside CTradeJournalManager::Update() - ran solely under
   UseDatabaseRanking, which ships false, so the da54639 halt was armed
   (ExpectancyMinTrades=40) and never received a single closed trade. A risk
   rule must not be a side effect of an analytics toggle: the journal gains
   InitTrackingOnly(), Update() runs unconditionally from OnTick and skips
   only the DB insert when no DB was initialized.

2. Below-minimum lots were silently bumped UP to SYMBOL_VOLUME_MIN by
   TCNormalizeVolume - correct for a user-entered fixed lot, but in the
   risk-sizing path it turned a budget-capped 0.05 into 0.10 on min-0.10/
   step-0.01 symbols: double the intended risk, after CapRiskAmount already
   clamped, exactly the routine-stop-out-breaches-the-daily-limit scenario
   the budget exists to close. CMoneyRiskBase now refuses the trade when the
   risk-derived lot is below the broker minimum.

3. All trading was async fire-and-forget (SetAsyncMode(true)) with no
   OnTradeTransaction handler and no retry: server retcodes were never
   observed. Fail-safe for entries, not for closes - a silently rejected
   close rode the position until the next bar (or next day for the timed
   close window). Now synchronous, matching the risk-budget flatten's own
   already-synchronous CTrade; on an H1 EA the latency is irrelevant.

4. FIXED_LOT bypassed the budget entirely (no CapRiskAmount, no
   OpenRiskAtStops) - pre-halt it could commit more than the remaining daily
   allowance. A fixed lot cannot be scaled, so the rule is binary: its
   loss-to-stop fits the remaining allowance whole or the trade is refused;
   unpriceable risk (no SL) is refused while the budget is enabled.

Compile: 0 errors, 0 warnings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-11 18:14:26 -04:00
AnimateDread
da54639996 feat: expectancy stop - halt when the measured result says the strategy loses
The daily (4%) and total (8%) rules bound how FAST an account can lose. Nothing
noticed WHETHER it was losing. A negative-expectancy signal traded at 1% inside
that envelope breaches no rule and still arrives at zero - it just takes longer,
with every limit green the whole way down. That is the realistic way this EA
destroys an account, and no existing guard could see it.

THE ARITHMETIC THIS ENFORCES. Expected value per trade is p*TP - (1-p)*SL - cost.
With no directional edge p equals SL/(SL+TP), which is also the break-even rate,
so the payoff terms cancel exactly and EV = -cost. Expected P&L is -(trades) x
cost: strictly negative, proportional to activity. Measured here: directional
precision 23-24% against a 25% break-even, flat across every confidence tier,
with 58 points of spread on SP500. Sizing, stop placement and trailing move
variance around that mean; none of them changes its sign.

So every closed position now reports its result in R (net profit over money
actually at risk) and the running mean is tested against zero. Above the
configured minimum sample, if mean + sigma*SE < 0, new entries stop.

  - SIGNIFICANTLY below, not merely below. A run of losers is ordinary variance
    even for a profitable system; halting on the raw mean would be the same
    act-on-noise error the MI gates exist to prevent. Using the standard error
    means a wide spread simply demands more trades before the rule can fire.
  - NET of swap and commission (ResolveClose already sums all three). Deliberate
    and load-bearing: when the edge is zero, cost IS the expectancy, so a gross
    version would measure a strategy nobody can trade.
  - Reported in R so symbols, lot sizes and balances share one scale and one
    mean. Trades without a stop are not scored rather than assigned a guessed R.
  - LATCHED across restarts, like the daily halt and for the same reason: a
    latch a reattach clears is not a latch. Clearing it means deleting the risk
    state file, deliberately, after looking at why.

State is appended to the risk file length-guarded, so files written before this
still load and start their sample at zero rather than misreading.

Defaults 40 trades / 2 sigma; ExpectancyMinTrades = 0 disables it.

This does not make the strategy profitable and is not meant to. It stops paying
tuition on one the results say is losing, and does it on measurement rather than
on a drawdown limit finally being reached.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:20:00 -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
771c9b58ec feat: add weight scaling parameter to neuron initialization for improved training stability
- Added optional `weighScale` parameter (default -1.0) to `CNeuronBase::Init` and `CLayer::CreateElement`.
- Updated `CNeuronPool::Init` to use LeCun-uniform scaling (1/sqrt(window+1)) for its base initialization.
- Updated `CNet::CNet` to use He-scaled initialization (sqrt(2/neurons)) for dense layers.
- These changes enable more flexible and statistically sound weight initialization, matching the rationale used in OCL-based implementations, leading to better training stability and convergence.
2026-07-22 22:51:04 -04:00