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

146 lines
5.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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