Files
TR_Agent/MQL5/Experts/MultiAgentTest/Agents/RegimeConsensus.mqh
T

146 lines
5.2 KiB
Plaintext
Raw Normal View History

#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<count; i++) {
if(!allAgents[i].enabled) continue;
if(allAgents[i].name == "Hurst") { rawHurstZ = allAgents[i].lastRawSignal; hurstZ = allAgents[i].lastZScore; }
if(allAgents[i].name == "ADX") { rawADXZ = allAgents[i].lastRawSignal; adxZ = allAgents[i].lastZScore; }
}
lastHurstZ = hurstZ;
lastADXZ = adxZ;
hurstStats.Update(hurstZ);
adxStats.Update(adxZ);
double hStd = SafeDenom(hurstStats.Std(), ZScoreFallback());
double aStd = SafeDenom(adxStats.Std(), ZScoreFallback());
double combinedScale = MathSqrt(hStd * hStd + aStd * aStd);
double rawDiff = MathAbs(hurstZ - adxZ);
diffRegimeStats.Update(rawDiff);
// Agreement data-driven: quanto sono vicine relative alla loro volatilità tipica
double typicalDiff = SafeDenom(diffRegimeStats.Std(), combinedScale);
SHARED_regimeAgreement = 1.0 - MathMin(rawDiff / typicalDiff, 1.0);
// Consenso: media divisa per numero di fonti attive
double nActive = 0;
if(hurstStats.Count() > 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