146 lines
5.2 KiB
Plaintext
146 lines
5.2 KiB
Plaintext
#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
|