#ifndef REGIME_CONSENSUS_MQH #define REGIME_CONSENSUS_MQH #include "AgentBase.mqh" class RegimeConsensus : public IAgent { private: RunningStats adxStats, hurstStats; RunningStats diffRegimeStats; RunningCorrelation hurstCorr; // correlazione hurstZ con ritorno RunningCorrelation adxCorr; // correlazione adxZ con ritorno double lastHurstZ, lastADXZ; // raw z-scores per Learn() double SafeDenom(double v, double fallback) const { double eps = DATA_EPS(fallback); return (MathAbs(v) > eps) ? v : fallback; } double ZScoreFallback() const { return 1.0; } // z-score ha per definizione σ=1 public: RegimeConsensus(string n="Consensus", double w=1.0) : IAgent(n, w), adxStats(0.05, 30, 200), hurstStats(0.05, 30, 200), diffRegimeStats(0.05, 20, 200), hurstCorr(0.1, 5), adxCorr(0.1, 5), lastHurstZ(0), lastADXZ(0) {} double Analyze(const MarketData &data) override { lastZScore = 0; return 0; } void Interact(IAgent *&allAgents[], int count) override { double hurstZ = 0, adxZ = 0; double rawHurstZ = 0, rawADXZ = 0; for(int i=0; i 0) nActive += 1.0; if(adxStats.Count() > 0) nActive += 1.0; nActive = MathMax(1.0, nActive); SHARED_regimeConsensus = MathTanh((hurstZ + adxZ) / nActive * SHARED_regimeAgreement); // Rilevamento pattern con soglie data-driven long pattern = 0; string pName = "none"; double hThr = SafeDenom(hStd, ZScoreFallback()); double aThr = SafeDenom(aStd, ZScoreFallback()); // Fattore divergenza basato sull'agreement storico double agreeFactor = 1.0 + 1.0 / MathMax(1e-15, SHARED_regimeAgreement); double divThreshold = combinedScale * agreeFactor; // Soglia breakout: SE della differenza normalizzato per agreement // Per due fonti indipendenti, SE_diff = √(hStd² + aStd²) / √nActive // Agreement scala: più accordo → soglia più alta (breakout più significativo) double nActiveRegime = 2.0; double seDiff = combinedScale / MathSqrt(nActiveRegime); double breakLower = seDiff * (1.0 + SHARED_regimeAgreement); double breakUpper = divThreshold; if(hurstZ > hThr && adxZ > aThr) { pattern = 1; pName = "strong_trend"; } else if(hurstZ < -hThr && adxZ < -aThr) { pattern = 2; pName = "strong_range"; } else if(rawDiff > divThreshold && (hurstZ > 0 || adxZ > 0)) { pattern = 3; pName = "divergence"; } else if(rawDiff > breakLower && rawDiff < breakUpper && MathAbs(hurstZ + adxZ) > combinedScale) { pattern = 4; pName = "breakout_forming"; } else if(MathAbs(SHARED_regimeConsensus) > combinedScale / MathSqrt(nActiveRegime)) { pattern = 5; pName = "weak_bias"; } SHARED_regimeConsensus = CalibrateZ(SHARED_regimeConsensus); SHARED_regimeZ = SHARED_regimeConsensus; SHARED_trendStrength = MathAbs(SHARED_regimeConsensus); } void Learn(double predictedZ, double actualReturnZ) override { IAgent::Learn(predictedZ, actualReturnZ); hurstCorr.Update(lastHurstZ, actualReturnZ); adxCorr.Update(lastADXZ, actualReturnZ); } void Save(int fh) const override { IAgent::Save(fh); adxStats.Save(fh); hurstStats.Save(fh); diffRegimeStats.Save(fh); hurstCorr.Save(fh); adxCorr.Save(fh); } void Load(int fh) override { IAgent::Load(fh); adxStats.Load(fh); hurstStats.Load(fh); diffRegimeStats.Load(fh); hurstCorr.Load(fh); adxCorr.Load(fh); } void Reset() override { IAgent::Reset(); adxStats.Reset(); hurstStats.Reset(); diffRegimeStats.Reset(); hurstCorr.Reset(); adxCorr.Reset(); lastHurstZ = 0; lastADXZ = 0; } string SignalInfo() const override { return name + " z=" + StringFormat("%+.3f", SHARED_regimeConsensus) + " agree=" + StringFormat("%.2f", SHARED_regimeAgreement); } }; #endif