Warrior_EA/Variables/ConfidenceBridge.mqh

64 lines
4.3 KiB
MQL5
Raw Permalink Normal View History

//+------------------------------------------------------------------+
//| Warrior_EA |
//| AnimateDread |
//| |
//+------------------------------------------------------------------+
// Money management classes (CExpertMoney) are invoked by the standard library's
// CExpert with a fixed (price, sl) signature - they have no pointer back to the
// signal filter that computed those levels. CExpertSignalCustom::OpenParams()
// refreshes these globals right before Money.CheckOpenLong/Short() is called for
// the same trade, so Money classes can read a same-tick confidence value without
// requiring an intrusive change to the wizard framework's call chain.
double g_AISignedConfidence = 0.0; // -1..1, sign = direction, magnitude = AI confidence; 0 if no AI filter
double g_DBConfidence = 0.0; // 0..1, historical time-based win rate of the active pattern set
// source takes CONFIDENCE_SOURCE's underlying int values (0=CONF_AI, 1=CONF_DB, 2=CONF_BLENDED).
// Declared as int rather than the enum type so this header has no dependency on the include
// order of Enumerations\InputEnums.mqh (this file is pulled in from class headers that are
// included before Inputs.mqh in Warrior_EA.mq5).
// reward:risk ratio of the specific trade OpenParams() just sized (b in the Kelly-criterion
// formula CMoneyIntelligent::AdjustRiskAmount() uses) - refreshed on the same same-tick
// contract as the two confidence globals above; always > 0 when populated, since OpenParams()
feat: remove Min_Risk_Reward_Ratio - a guess was overriding a measurement The barrier geometry is derived from the instrument's own excursion distribution (stop at q75 of adverse travel, target at q50 of favourable), and then a 1:2 floor was applied on top, raising the target to twice whatever the stop happened to be. On SP500 H1 that pushed the target to 6.66*ATR, reached on 3.3% of bars inside the horizon - so the label became "almost never a win" and every topology was trained to predict an event that essentially does not occur. A measured target has to stay measured. The ratio never bought what it was believed to buy. A reward:risk floor does not create expectancy; it trades hit rate against payoff at a break-even the geometry already fixes - which this project has separately MEASURED (payoff 0.92 -> 5.72 with expectancy flat). What it did buy was two outages: four consecutive Market validation rejections for "no trading operations" when it rejected 100% of setups, and the label corruption above. Removed: - the input and the RISK_REWARD_RATIO enum (deleted, not left dangling - a live enum with no input behind it is the shape of the stale-.set incident that trained ~250 eras on the wrong target) - the forced target raise in the label geometry - the rrOK eligibility gate in the barrier-geometry scan, so every unclamped pairing now competes on the measurement alone. Clamping stays disqualifying for its own unrelated reason. - the reward < minRR*risk veto in OpenParams Kept: g_TradeRewardRiskRatio still computed and still bridged to Kelly sizing in MoneyIntelligent - the ratio as a SIZING input was always the sound use. Risk stays bounded where it actually is - account risk % and CRiskBudget. The low-reachability warning survives but is re-aimed: with nothing inflating the target, a target the market rarely reaches can only mean the horizon is truncating the excursions the geometry is derived from. Both build variants compile 0 errors / 0 warnings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 14:51:59 -04:00
// no longer rejects on reward:risk at all (the filter was removed 2026-08-09), so g_TradeRewardRiskRatio
// reaches Money as a SIZING input rather than as the survivor of a veto.
double g_TradeRewardRiskRatio = 0.0;
// Live per-tick signed AI confidence (-1..1, sign = predicted direction, magnitude = confidence),
// refreshed every tick/timer from the active AI signal's SignedAIConfidence() in
// CExpertSignalAIBase::ScheduleTrainingIfNeeded() - independent of the OpenParams() same-tick
// contract above, because an ALREADY-OPEN position generates no OpenParams() calls yet the
// intelligent trailing (Trailing\TrailingIntelligent.mqh) still needs a current read while holding.
// This is written by the active AI signal once per tick; 0.0 means no AI filter is active/converged yet.
double g_LiveAISignedConfidence = 0.0;
fix: live trades now use the geometry the gate certifies; perf: BN kernels Three changes, one theme: the trade placed, the trade graded, and the trade computed are now the same trade. 1) GEOMETRY WIRE (correctness, the ranked #1 open issue). The measured barrier pair reached the LABELS only - OpenParams still placed orders at the enum geometry (2*ATR/6*ATR), so the deploy gate certified "reaches 1.62*ATR before 3.33*ATR above break-even" about trades the EA never placed. Published via g_DerivedSlAtrMult/g_DerivedTpAtrMult (ConfidenceBridge, same same-tick contract as the confidence globals, because OpenParams runs on the root signal which has no pointer to the AI filter). Two writers: DeriveBarrierGeometry at era 0, and the .cfg adoption a deployed model takes. Overrides both legs and both Intelligent modes - the certificate is exact or it is nothing. TP is ATR-anchored like the label, NOT risk-relative, so a floor-widened stop cannot reshape the certified target. 2) BATCH NORM RUNS DEVICE-SIDE ON OPENCL. Four kernels in Network.cl - forward, hidden gradient, gamma/beta accumulate, gamma/beta apply - each a line-for-line transcription of the host implementation (NormalizeHost / HiddenGradHost / StepGammaBeta) including every NaN guard, clamp, and the exact moment-write ordering. The host copies remain the runtime for the DLL and pure-MQL5 tiers and the reference the kernels must match. Because this box has no OpenCL platform, the safety story is layered: - shim validation: kernels compiled as C and driven against a fp64 host transcription over NaN-poisoned stats, NaN gamma, over-clamp inputs, the frozen path, both optimizers, 3 batches - ALL PASS, worst normalized diff 0.132 vs tolerance 1.0 - in-situ self-check: each kernel is compared against its host twin ON FIRST USE on the real device (SelfCheckBn*), covering what the shim cannot - arg indices and buffer bindings. Any disagreement resyncs from the good copy, latches all BN kernels off process-wide, and training continues host-side. A transcription bug costs a warning and some speed, never a poisoned .nnw. - sync discipline: BatchOptions is now a CBufferDouble with explicit authority tracking (m_bnDeviceAuthoritative). Checkpoints/saves pull read-only; restores/loads/resets push; a mid-batch handover drains the device gamma/beta accumulator into the host arrays so no sample is lost. 3) SMALL FIXES. Apply-kernel build failure now latches the dispatch path at init (one warning instead of warning + failed Execute). Build tag bumped to win-scoring-gpu-v1 - first tag change since expectancy-stop-v1 despite five binary-changing commits. Both build variants compile 0 errors, 0 warnings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-09 17:51:40 -04:00
// MEASURED barrier geometry, in ATR multiples, published by the AI signal for the LIVE order path.
// Written from exactly two places: DeriveBarrierGeometry() when the geometry is measured at era 0, and
// the .cfg adoption in Persistence.mqh when a trained model is loaded with its pinned pair. 0.0 = not
// derived (fresh start before era 0, or no AI filter) - OpenParams() then falls back to the SL_Mode/
// TP_Mode enum multiples exactly as before.
//
// This bridge exists because of a real incident, not tidiness: the deploy gate certifies "this model's
// trades reach the MEASURED target before the MEASURED stop at a win rate beating break-even" - and
// until 2026-08-09 the live EA then placed trades with the ENUM geometry (2*ATR stop, 6*ATR target on
// the shipped SP500 config) that the certificate says nothing about. The model was graded on one game
// and paid on another. Same one-way, same-tick contract as the confidence globals above; OpenParams()
// runs on the aggregate/root signal, which has no pointer to the AI filter that measured these.
double g_DerivedSlAtrMult = 0.0;
double g_DerivedTpAtrMult = 0.0;
//+------------------------------------------------------------------+
//| Combine AI/DB confidence into a single 0..1 magnitude |
//+------------------------------------------------------------------+
double CombinedConfidence(int source)
{
double aiMag = MathIsValidNumber(g_AISignedConfidence) ? MathAbs(g_AISignedConfidence) : 0.0;
double dbMag = MathIsValidNumber(g_DBConfidence) ? g_DBConfidence : 0.0;
aiMag = MathMax(0.0, MathMin(aiMag, 1.0));
dbMag = MathMax(0.0, MathMin(dbMag, 1.0));
switch(source)
{
case 1: // CONF_DB
return dbMag;
case 2: // CONF_BLENDED
return (aiMag + dbMag) / 2.0;
default: // CONF_AI
return aiMag;
}
}
//+------------------------------------------------------------------+