//+------------------------------------------------------------------+ //| NuclearOptimization.mqh - 100-Level MQL5-Compatible Optimization | //| Copyright DualEA - Nuclear Grade Implementation | //| Version 3.0.0 | //+------------------------------------------------------------------+ #property copyright "DualEA - Nuclear Grade Implementation" #property version "3.0.0" #property strict //+------------------------------------------------------------------+ //| MEMORY-OPTIMIZED CONFIGURATION BLOCK | //+------------------------------------------------------------------+ struct SConfigBlock { string signature; // "DUAL" int version; // 3 int strategy_count; // 23 int risk_profile; // 0-100 (85 for AGGRESSIVE) double max_drawdown; // 0.15 default double kelly_fraction; // 0.25 default int correlation_window; // 252 int volatility_window; // 21 bool enable_ml; // true bool enable_news_filter; // true bool enable_regime_switch; // true }; //+------------------------------------------------------------------+ //| RING BUFFER - MQL5 Compatible String-Based Implementation | //| FIXED: Using string array instead of SPolicyState (not defined) | //+------------------------------------------------------------------+ class CRingBuffer { private: string m_buffer[1024]; // Store serialized data as strings int m_capacity; int m_head; int m_tail; int m_count; public: CRingBuffer(int capacity = 1024) : m_capacity(capacity), m_head(0), m_tail(0), m_count(0) { if(capacity > 1024) m_capacity = 1024; // Cap at 1024 } ~CRingBuffer() { // No ArrayFree needed for fixed array } bool Push(const string &item) { if(m_count >= m_capacity) return false; m_buffer[m_tail] = item; m_tail = (m_tail + 1) % m_capacity; m_count++; return true; } bool Pop(string &item) { if(m_count <= 0) return false; item = m_buffer[m_head]; m_head = (m_head + 1) % m_capacity; m_count--; return true; } int Count() const { return m_count; } bool IsFull() const { return m_count >= m_capacity; } bool IsEmpty() const { return m_count <= 0; } void Clear() { m_head = 0; m_tail = 0; m_count = 0; } }; //+------------------------------------------------------------------+ //| OPTIMIZED CORRELATION ENGINE - 23-Strategy Matrix | //+------------------------------------------------------------------+ class COptimizedCorrelationEngine { private: double m_correlation_cache[23][23]; double m_price_matrix[23][252]; // 23 strategies × 252-day window int m_window_size; int m_num_strategies; datetime m_last_update; public: COptimizedCorrelationEngine() { m_window_size = 252; m_num_strategies = 23; m_last_update = 0; ArrayInitialize(m_correlation_cache, 0.0); ArrayInitialize(m_price_matrix, 0.0); } // Optimized Pearson correlation with cache - compute inline from source matrix // First dimension must be dynamic in MQL5 function parameters void CalculateCorrelations(const double &prices[][252]) { for(int i = 0; i < m_num_strategies; i++) { for(int j = i; j < m_num_strategies; j++) { double sum_x = 0, sum_y = 0, sum_xy = 0; double sum_x2 = 0, sum_y2 = 0; int n = m_window_size; for(int k = 0; k < n; k++) { double x = prices[i][k]; double y = prices[j][k]; sum_x += x; sum_y += y; sum_xy += x * y; sum_x2 += x * x; sum_y2 += y * y; } double numerator = n * sum_xy - sum_x * sum_y; double denominator = MathSqrt((n * sum_x2 - sum_x * sum_x) * (n * sum_y2 - sum_y * sum_y)); double corr = (denominator != 0.0) ? numerator / denominator : 0.0; m_correlation_cache[i][j] = corr; m_correlation_cache[j][i] = corr; } } m_last_update = TimeCurrent(); } // Removed row-slice PearsonCorrelation; inlined in CalculateCorrelations double PearsonCorrelation(const double &x[], const double &y[], int n) { return 0.0; } double GetCorrelation(int strategy_i, int strategy_j) { if(strategy_i >= 0 && strategy_i < 23 && strategy_j >= 0 && strategy_j < 23) return m_correlation_cache[strategy_i][strategy_j]; return 0.0; } }; //+------------------------------------------------------------------+ //| ADVANCED RISK METRICS - VaR & Expected Shortfall | //+------------------------------------------------------------------+ struct SRiskMetrics { double var_95; // 5% Value at Risk double expected_shortfall; // Conditional VaR (CVaR) double max_drawdown; // Maximum drawdown double sharpe_ratio; // Risk-adjusted return double calmar_ratio; // Return/MaxDD ratio double sortino_ratio; // Downside deviation ratio datetime timestamp; }; class CRiskMetricsCalculator { private: double m_returns[]; int m_window; public: CRiskMetricsCalculator(int window = 100) : m_window(window) { ArrayResize(m_returns, m_window); ArrayInitialize(m_returns, 0.0); } SRiskMetrics CalculateMetrics(const double &equity_curve[]) { SRiskMetrics metrics; int n = ArraySize(equity_curve); // Calculate returns CalculateReturns(equity_curve); // Sort returns for VaR calculation double sorted_returns[]; ArrayCopy(sorted_returns, m_returns); ArraySort(sorted_returns); // Value at Risk (95th percentile) int var_index = (int)(n * 0.05); metrics.var_95 = MathAbs(sorted_returns[var_index]); // Expected Shortfall (CVaR) - average of worst 5% double es_sum = 0; for(int i = 0; i < var_index; i++) { es_sum += MathAbs(sorted_returns[i]); } metrics.expected_shortfall = es_sum / var_index; // Maximum Drawdown metrics.max_drawdown = CalculateMaxDrawdown(equity_curve); // Sharpe Ratio double mean_return = 0, std_return = 0; CalculateMeanStd(m_returns, mean_return, std_return); metrics.sharpe_ratio = (std_return > 0) ? (mean_return / std_return) * MathSqrt(252) : 0; // Calmar Ratio double annual_return = mean_return * 252; metrics.calmar_ratio = (metrics.max_drawdown > 0) ? annual_return / metrics.max_drawdown : 0; // Sortino Ratio (downside deviation only) metrics.sortino_ratio = CalculateSortinoRatio(m_returns); metrics.timestamp = TimeCurrent(); return metrics; } private: void CalculateReturns(const double &equity[]) { int n = MathMin(ArraySize(equity), m_window); ArrayResize(m_returns, n - 1); for(int i = 1; i < n; i++) { m_returns[i-1] = (equity[i] - equity[i-1]) / equity[i-1]; } } double CalculateMaxDrawdown(const double &equity[]) { int n = ArraySize(equity); double max_dd = 0; double peak = equity[0]; for(int i = 1; i < n; i++) { if(equity[i] > peak) { peak = equity[i]; } else { double dd = (peak - equity[i]) / peak; if(dd > max_dd) max_dd = dd; } } return max_dd; } void CalculateMeanStd(const double &data[], double &mean, double &std) { int n = ArraySize(data); mean = 0; for(int i = 0; i < n; i++) mean += data[i]; mean /= n; double variance = 0; for(int i = 0; i < n; i++) { double diff = data[i] - mean; variance += diff * diff; } std = MathSqrt(variance / n); } double CalculateSortinoRatio(const double &returns[]) { int n = ArraySize(returns); double mean = 0, downside_sum = 0; int downside_count = 0; for(int i = 0; i < n; i++) { mean += returns[i]; if(returns[i] < 0) { downside_sum += returns[i] * returns[i]; downside_count++; } } mean /= n; if(downside_count == 0) return 0; double downside_dev = MathSqrt(downside_sum / downside_count); return (downside_dev > 0) ? (mean / downside_dev) * MathSqrt(252) : 0; } }; //+------------------------------------------------------------------+ //| KELLY CRITERION POSITION SIZER | //+------------------------------------------------------------------+ class CKellyPositionSizer { private: double m_kelly_fraction; // Safety factor (0.25 = quarter Kelly) double m_max_position_size; // Maximum position size cap double m_min_position_size; // Minimum position size floor public: CKellyPositionSizer(double kelly_fraction = 0.25, double max_size = 0.10, double min_size = 0.01) { m_kelly_fraction = kelly_fraction; m_max_position_size = max_size; m_min_position_size = min_size; } double CalculatePositionSize(double win_rate, double avg_win, double avg_loss, double current_equity) { // Full Kelly formula: f = (p*W - (1-p)*L) / (W*L) // Where: p = win_rate, W = avg_win, L = avg_loss if(avg_win <= 0 || avg_loss <= 0) return m_min_position_size; double p = win_rate; double q = 1.0 - win_rate; // Kelly percentage double kelly = (p * avg_win - q * avg_loss) / (avg_win * avg_loss); // Apply safety fraction kelly *= m_kelly_fraction; // Clamp to safe range kelly = MathMax(0.0, MathMin(kelly, m_max_position_size)); if(kelly < m_min_position_size) return 0.0; // Don't trade if Kelly too small return current_equity * kelly; } double CalculateOptimalF(const double &returns[], double current_equity) { // Optimal F method (Ralph Vince) int n = ArraySize(returns); if(n == 0) return m_min_position_size; double max_f = 0; double max_twrr = -999999; // Search for optimal f between 0 and 1 for(double f = 0.01; f <= 0.50; f += 0.01) { double twrr = 1.0; // Terminal Wealth Relative Return for(int i = 0; i < n; i++) { twrr *= (1.0 + f * returns[i]); } if(twrr > max_twrr) { max_twrr = twrr; max_f = f; } } // Apply safety fraction max_f *= m_kelly_fraction; max_f = MathMax(m_min_position_size, MathMin(max_f, m_max_position_size)); return current_equity * max_f; } }; //+------------------------------------------------------------------+ //| CONFIGURATION MANAGER - JSON-Based | //+------------------------------------------------------------------+ class CConfigurationManager { private: SConfigBlock m_config; string m_config_file; public: CConfigurationManager(string config_path = "DualEA\\config\\nuclear_config.json") { m_config_file = config_path; LoadDefaultConfig(); } void LoadDefaultConfig() { m_config.signature = "DUAL"; m_config.version = 3; m_config.strategy_count = 23; m_config.risk_profile = 85; // AGGRESSIVE m_config.max_drawdown = 0.15; m_config.kelly_fraction = 0.25; m_config.correlation_window = 252; m_config.volatility_window = 21; m_config.enable_ml = true; m_config.enable_news_filter = true; m_config.enable_regime_switch = true; } bool SaveConfig() { int handle = FileOpen(m_config_file, FILE_WRITE|FILE_TXT); if(handle == INVALID_HANDLE) return false; FileWriteString(handle, "{\n"); FileWriteString(handle, " \"signature\": \"" + m_config.signature + "\",\n"); FileWriteString(handle, " \"version\": " + IntegerToString(m_config.version) + ",\n"); FileWriteString(handle, " \"strategy_count\": " + IntegerToString(m_config.strategy_count) + ",\n"); FileWriteString(handle, " \"risk_profile\": " + IntegerToString(m_config.risk_profile) + ",\n"); FileWriteString(handle, " \"max_drawdown\": " + DoubleToString(m_config.max_drawdown, 2) + ",\n"); FileWriteString(handle, " \"kelly_fraction\": " + DoubleToString(m_config.kelly_fraction, 2) + ",\n"); FileWriteString(handle, " \"correlation_window\": " + IntegerToString(m_config.correlation_window) + ",\n"); FileWriteString(handle, " \"volatility_window\": " + IntegerToString(m_config.volatility_window) + ",\n"); FileWriteString(handle, " \"enable_ml\": " + (m_config.enable_ml ? "true" : "false") + ",\n"); FileWriteString(handle, " \"enable_news_filter\": " + (m_config.enable_news_filter ? "true" : "false") + ",\n"); FileWriteString(handle, " \"enable_regime_switch\": " + (m_config.enable_regime_switch ? "true" : "false") + "\n"); FileWriteString(handle, "}\n"); FileClose(handle); return true; } SConfigBlock GetConfig() const { return m_config; } void SetRiskProfile(int profile) { m_config.risk_profile = profile; } void SetKellyFraction(double fraction) { m_config.kelly_fraction = fraction; } void SetMaxDrawdown(double dd) { m_config.max_drawdown = dd; } }; //+------------------------------------------------------------------+ //| POLICY STATE MANAGEMENT | //+------------------------------------------------------------------+ struct SPolicyState { double weights[23]; double bias; double learning_rate; int epoch; string model_hash; datetime timestamp; }; class CPolicyStateManager { private: CRingBuffer m_policy_queue; // Non-template - stores serialized policy states string m_current_state_serialized; public: CPolicyStateManager() : m_policy_queue(1024) {} bool UpdateState(const string &serialized_state) { m_current_state_serialized = serialized_state; return m_policy_queue.Push(serialized_state); } string GetCurrentStateSerialized() const { return m_current_state_serialized; } };