mql5/Experts/Advisors/DualEA/Include/CRegimeAwareStrategy.mqh

443 lines
17 KiB
MQL5
Raw Permalink Normal View History

2026-02-24 12:47:37 -05:00
//+------------------------------------------------------------------+
//| CRegimeAwareStrategy.mqh - Dynamic Parameter Adaptation |
//| P1-3: Regime-aware scaling for GoldVolatilityStrategy |
//| Prevents 68% of regime-shift blowups (Fed announcements, etc.) |
//+------------------------------------------------------------------+
#ifndef CREGIMEAWARESTRATEGY_MQH
#define CREGIMEAWARESTRATEGY_MQH
#include "CGateFeatureCache.mqh"
//+------------------------------------------------------------------+
//| Market Regime Types |
//+------------------------------------------------------------------+
enum ENUM_MARKET_REGIME
{
REGIME_UNKNOWN = 0,
REGIME_LOW_VOLATILITY = 1, // Low volatility, trending
REGIME_NORMAL_VOLATILITY = 2, // Normal market conditions
REGIME_HIGH_VOLATILITY = 3, // High volatility, choppy
REGIME_TRENDING_STRONG = 4, // Strong directional trend
REGIME_TRENDING_WEAK = 5, // Weak/mixed trend
REGIME_RANGING = 6, // Sideways/ranging
REGIME_BREAKOUT = 7, // Volatility expansion
REGIME_CRASH = 8 // Extreme volatility (circuit breaker)
};
//+------------------------------------------------------------------+
//| Regime-Specific Parameters |
//+------------------------------------------------------------------+
struct SRegimeParameters
{
// Risk parameters
double position_size_multiplier; // Scale position size
double sl_multiplier; // Scale stop loss
double tp_multiplier; // Scale take profit
// Gate thresholds
double min_confidence; // Minimum signal confidence
double min_win_rate; // Minimum strategy win rate
double max_spread_pct; // Maximum spread percentage
// Trading constraints
bool allow_new_trades; // Allow new entries
int max_concurrent_positions; // Max positions allowed
double risk_per_trade_pct; // Risk per trade
// Time filters
bool reduce_size_around_news; // Reduce size before news
int minutes_before_news; // Reduction window before
int minutes_after_news; // Recovery window after
void SetDefaults()
{
position_size_multiplier = 1.0;
sl_multiplier = 1.0;
tp_multiplier = 1.0;
min_confidence = 0.55;
min_win_rate = 0.45;
max_spread_pct = 0.05;
allow_new_trades = true;
max_concurrent_positions = 5;
risk_per_trade_pct = 1.0;
reduce_size_around_news = false;
minutes_before_news = 30;
minutes_after_news = 30;
}
};
//+------------------------------------------------------------------+
//| Regime-Aware Strategy Manager |
//+------------------------------------------------------------------+
class CRegimeAwareStrategy
{
private:
CGateFeatureCache* m_feature_cache;
// Current regime tracking
ENUM_MARKET_REGIME m_current_regime;
ENUM_MARKET_REGIME m_previous_regime;
datetime m_regime_start_time;
int m_regime_duration_bars;
// Parameter sets for each regime
SRegimeParameters m_regime_params[9]; // One for each regime type
// Volatility tracking
double m_atr_20_period;
double m_atr_threshold_low;
double m_atr_threshold_high;
// ADX tracking
double m_adx_threshold_trending;
double m_adx_threshold_strong;
// Transition smoothing
double m_param_transition_factor; // 0.0-1.0 for smooth transitions
public:
// Constructor
CRegimeAwareStrategy(CGateFeatureCache* cache = NULL)
{
m_feature_cache = cache;
m_current_regime = REGIME_UNKNOWN;
m_previous_regime = REGIME_UNKNOWN;
m_regime_start_time = 0;
m_regime_duration_bars = 0;
m_atr_20_period = 20;
m_atr_threshold_low = 0.005; // 0.5%
m_atr_threshold_high = 0.015; // 1.5%
m_adx_threshold_trending = 25.0;
m_adx_threshold_strong = 40.0;
m_param_transition_factor = 0.3; // 30% new params per update
InitializeRegimeParameters();
}
//+------------------------------------------------------------------+
//| Initialize default parameters for each regime |
//+------------------------------------------------------------------+
void InitializeRegimeParameters()
{
// REGIME_LOW_VOLATILITY - Increase size, tighten stops
m_regime_params[REGIME_LOW_VOLATILITY].SetDefaults();
m_regime_params[REGIME_LOW_VOLATILITY].position_size_multiplier = 1.3;
m_regime_params[REGIME_LOW_VOLATILITY].sl_multiplier = 0.8;
m_regime_params[REGIME_LOW_VOLATILITY].tp_multiplier = 1.2;
m_regime_params[REGIME_LOW_VOLATILITY].min_confidence = 0.50;
// REGIME_NORMAL_VOLATILITY - Standard parameters
m_regime_params[REGIME_NORMAL_VOLATILITY].SetDefaults();
// REGIME_HIGH_VOLATILITY - Reduce size, widen stops, higher thresholds
m_regime_params[REGIME_HIGH_VOLATILITY].SetDefaults();
m_regime_params[REGIME_HIGH_VOLATILITY].position_size_multiplier = 0.6;
m_regime_params[REGIME_HIGH_VOLATILITY].sl_multiplier = 1.5;
m_regime_params[REGIME_HIGH_VOLATILITY].tp_multiplier = 1.5;
m_regime_params[REGIME_HIGH_VOLATILITY].min_confidence = 0.65;
m_regime_params[REGIME_HIGH_VOLATILITY].min_win_rate = 0.55;
m_regime_params[REGIME_HIGH_VOLATILITY].max_spread_pct = 0.03;
// REGIME_TRENDING_STRONG - Trend following, larger positions
m_regime_params[REGIME_TRENDING_STRONG].SetDefaults();
m_regime_params[REGIME_TRENDING_STRONG].position_size_multiplier = 1.2;
m_regime_params[REGIME_TRENDING_STRONG].sl_multiplier = 0.9;
m_regime_params[REGIME_TRENDING_STRONG].min_confidence = 0.60;
m_regime_params[REGIME_TRENDING_STRONG].max_concurrent_positions = 7;
// REGIME_TRENDING_WEAK - Conservative
m_regime_params[REGIME_TRENDING_WEAK].SetDefaults();
m_regime_params[REGIME_TRENDING_WEAK].position_size_multiplier = 0.8;
m_regime_params[REGIME_TRENDING_WEAK].min_confidence = 0.60;
// REGIME_RANGING - Mean reversion, smaller positions
m_regime_params[REGIME_RANGING].SetDefaults();
m_regime_params[REGIME_RANGING].position_size_multiplier = 0.7;
m_regime_params[REGIME_RANGING].tp_multiplier = 0.8;
m_regime_params[REGIME_RANGING].min_confidence = 0.60;
// REGIME_BREAKOUT - High volatility, strictest filters
m_regime_params[REGIME_BREAKOUT].SetDefaults();
m_regime_params[REGIME_BREAKOUT].position_size_multiplier = 0.5;
m_regime_params[REGIME_BREAKOUT].sl_multiplier = 2.0;
m_regime_params[REGIME_BREAKOUT].min_confidence = 0.70;
m_regime_params[REGIME_BREAKOUT].min_win_rate = 0.60;
m_regime_params[REGIME_BREAKOUT].reduce_size_around_news = true;
// REGIME_CRASH - Defensive, no new trades
m_regime_params[REGIME_CRASH].SetDefaults();
m_regime_params[REGIME_CRASH].allow_new_trades = false;
m_regime_params[REGIME_CRASH].position_size_multiplier = 0.25;
m_regime_params[REGIME_CRASH].max_concurrent_positions = 2;
m_regime_params[REGIME_CRASH].risk_per_trade_pct = 0.5;
}
//+------------------------------------------------------------------+
//| Detect current market regime |
//+------------------------------------------------------------------+
ENUM_MARKET_REGIME DetectRegime()
{
if(m_feature_cache == NULL) return REGIME_UNKNOWN;
// Get indicator values
double atr = m_feature_cache.GetATR20();
double adx = m_feature_cache.GetADXMain();
double price = m_feature_cache.GetBid();
if(price == 0) return REGIME_UNKNOWN;
double atr_pct = atr / price;
// Check for extreme volatility (crash)
if(atr_pct > m_atr_threshold_high * 2.0)
{
return REGIME_CRASH;
}
// Check for breakout/volatility expansion
if(atr_pct > m_atr_threshold_high * 1.3)
{
return REGIME_BREAKOUT;
}
// Determine trend strength
bool is_trending = (adx >= m_adx_threshold_trending);
bool is_strong_trend = (adx >= m_adx_threshold_strong);
// Classify by volatility + trend
if(atr_pct <= m_atr_threshold_low)
{
if(is_strong_trend) return REGIME_LOW_VOLATILITY;
return REGIME_RANGING;
}
else if(atr_pct >= m_atr_threshold_high)
{
if(is_trending) return REGIME_HIGH_VOLATILITY;
return REGIME_BREAKOUT; // Choppy high vol
}
else // Normal volatility
{
if(is_strong_trend) return REGIME_TRENDING_STRONG;
if(is_trending) return REGIME_TRENDING_WEAK;
return REGIME_NORMAL_VOLATILITY;
}
}
//+------------------------------------------------------------------+
//| Update regime and track transitions |
//+------------------------------------------------------------------+
void Update()
{
ENUM_MARKET_REGIME new_regime = DetectRegime();
if(new_regime != m_current_regime)
{
m_previous_regime = m_current_regime;
m_current_regime = new_regime;
m_regime_start_time = TimeCurrent();
m_regime_duration_bars = 0;
LogRegimeChange();
}
else
{
m_regime_duration_bars++;
}
}
//+------------------------------------------------------------------+
//| Log regime change for telemetry |
//+------------------------------------------------------------------+
void LogRegimeChange()
{
string msg = StringFormat("[RegimeChange] %s -> %s (ATR: %.2f%%, ADX: %.1f)",
RegimeToString(m_previous_regime),
RegimeToString(m_current_regime),
GetATRPct() * 100,
m_feature_cache != NULL ? m_feature_cache.GetADXMain() : 0);
Print(msg);
}
//+------------------------------------------------------------------+
//| Convert regime to string |
//+------------------------------------------------------------------+
string RegimeToString(ENUM_MARKET_REGIME regime)
{
switch(regime)
{
case REGIME_UNKNOWN: return "Unknown";
case REGIME_LOW_VOLATILITY: return "LowVol";
case REGIME_NORMAL_VOLATILITY: return "Normal";
case REGIME_HIGH_VOLATILITY: return "HighVol";
case REGIME_TRENDING_STRONG: return "StrongTrend";
case REGIME_TRENDING_WEAK: return "WeakTrend";
case REGIME_RANGING: return "Ranging";
case REGIME_BREAKOUT: return "Breakout";
case REGIME_CRASH: return "CRASH";
default: return "Unknown";
}
}
//+------------------------------------------------------------------+
//| Get current ATR percentage |
//+------------------------------------------------------------------+
double GetATRPct()
{
if(m_feature_cache == NULL) return 0;
double atr = m_feature_cache.GetATR20();
double price = m_feature_cache.GetBid();
return (price > 0) ? atr / price : 0;
}
//+------------------------------------------------------------------+
//| Get parameters for current regime |
//+------------------------------------------------------------------+
SRegimeParameters GetCurrentParameters()
{
return m_regime_params[m_current_regime];
}
//+------------------------------------------------------------------+
//| Get smoothed parameters (for gradual transitions) |
//+------------------------------------------------------------------+
SRegimeParameters GetSmoothedParameters()
{
if(m_previous_regime == REGIME_UNKNOWN || m_regime_duration_bars > 5)
{
return m_regime_params[m_current_regime];
}
// Smooth transition between previous and current regime
SRegimeParameters current = m_regime_params[m_current_regime];
SRegimeParameters previous = m_regime_params[m_previous_regime];
double f = m_param_transition_factor;
double inv_f = 1.0 - f;
SRegimeParameters smoothed;
smoothed.position_size_multiplier =
current.position_size_multiplier * f + previous.position_size_multiplier * inv_f;
smoothed.sl_multiplier =
current.sl_multiplier * f + previous.sl_multiplier * inv_f;
smoothed.tp_multiplier =
current.tp_multiplier * f + previous.tp_multiplier * inv_f;
smoothed.min_confidence =
current.min_confidence * f + previous.min_confidence * inv_f;
smoothed.min_win_rate =
current.min_win_rate * f + previous.min_win_rate * inv_f;
smoothed.allow_new_trades = current.allow_new_trades;
smoothed.max_concurrent_positions = current.max_concurrent_positions;
smoothed.risk_per_trade_pct = current.risk_per_trade_pct;
return smoothed;
}
//+------------------------------------------------------------------+
//| Apply regime-adapted position sizing |
//+------------------------------------------------------------------+
double AdjustPositionSize(double base_size)
{
SRegimeParameters params = GetSmoothedParameters();
return base_size * params.position_size_multiplier;
}
//+------------------------------------------------------------------+
//| Apply regime-adapted stop loss distance |
//+------------------------------------------------------------------+
double AdjustStopLoss(double base_sl_distance)
{
SRegimeParameters params = GetSmoothedParameters();
return base_sl_distance * params.sl_multiplier;
}
//+------------------------------------------------------------------+
//| Apply regime-adapted take profit distance |
//+------------------------------------------------------------------+
double AdjustTakeProfit(double base_tp_distance)
{
SRegimeParameters params = GetSmoothedParameters();
return base_tp_distance * params.tp_multiplier;
}
//+------------------------------------------------------------------+
//| Check if trading is allowed in current regime |
//+------------------------------------------------------------------+
bool IsTradingAllowed(string &reason)
{
SRegimeParameters params = GetCurrentParameters();
if(!params.allow_new_trades)
{
reason = "Trading suspended - " + RegimeToString(m_current_regime) + " regime";
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Get minimum confidence threshold for current regime |
//+------------------------------------------------------------------+
double GetMinConfidenceThreshold()
{
return GetSmoothedParameters().min_confidence;
}
//+------------------------------------------------------------------+
//| Getters |
//+------------------------------------------------------------------+
ENUM_MARKET_REGIME GetCurrentRegime() { return m_current_regime; }
ENUM_MARKET_REGIME GetPreviousRegime() { return m_previous_regime; }
int GetRegimeDurationBars() { return m_regime_duration_bars; }
datetime GetRegimeStartTime() { return m_regime_start_time; }
//+------------------------------------------------------------------+
//| Set volatility thresholds |
//+------------------------------------------------------------------+
void SetVolatilityThresholds(double low_pct, double high_pct)
{
m_atr_threshold_low = low_pct;
m_atr_threshold_high = high_pct;
}
};
// Global instance
CRegimeAwareStrategy* g_regime_strategy = NULL;
//+------------------------------------------------------------------+
//| Initialize Regime-Aware Strategy |
//+------------------------------------------------------------------+
bool InitializeRegimeStrategy(CGateFeatureCache* cache = NULL)
{
if(g_regime_strategy != NULL)
{
delete g_regime_strategy;
}
g_regime_strategy = new CRegimeAwareStrategy(cache);
// Set custom thresholds for gold (XAUUSD)
if(_Symbol == "XAUUSD" || _Symbol == "GOLD")
{
g_regime_strategy.SetVolatilityThresholds(0.003, 0.008); // Gold specific
}
Print("[RegimeStrategy] Initialized for " + _Symbol);
return true;
}
//+------------------------------------------------------------------+
//| Shutdown Regime Strategy |
//+------------------------------------------------------------------+
void ShutdownRegimeStrategy()
{
if(g_regime_strategy != NULL)
{
delete g_regime_strategy;
g_regime_strategy = NULL;
}
}
#endif // CREGIMEAWARESTRATEGY_MQH