mql5/Experts/Advisors/DualEA/PaperEA/NuclearOptimization.mqh

402 lines
15 KiB
MQL5
Raw Permalink Normal View History

2025-10-16 18:03:47 -04:00
//+------------------------------------------------------------------+
//| 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
};
//+------------------------------------------------------------------+
2026-02-24 12:47:37 -05:00
//| RING BUFFER - MQL5 Compatible String-Based Implementation |
//| FIXED: Using string array instead of SPolicyState (not defined) |
2025-10-16 18:03:47 -04:00
//+------------------------------------------------------------------+
class CRingBuffer {
private:
2026-02-24 12:47:37 -05:00
string m_buffer[1024]; // Store serialized data as strings
2025-10-16 18:03:47 -04:00
int m_capacity;
int m_head;
int m_tail;
int m_count;
public:
2026-02-24 12:47:37 -05:00
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
2025-10-16 18:03:47 -04:00
}
~CRingBuffer() {
2026-02-24 12:47:37 -05:00
// No ArrayFree needed for fixed array
2025-10-16 18:03:47 -04:00
}
2026-02-24 12:47:37 -05:00
bool Push(const string &item) {
2025-10-16 18:03:47 -04:00
if(m_count >= m_capacity) return false;
m_buffer[m_tail] = item;
m_tail = (m_tail + 1) % m_capacity;
m_count++;
return true;
}
2026-02-24 12:47:37 -05:00
bool Pop(string &item) {
2025-10-16 18:03:47 -04:00
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; }
2026-02-24 12:47:37 -05:00
void Clear() { m_head = 0; m_tail = 0; m_count = 0; }
2025-10-16 18:03:47 -04:00
};
//+------------------------------------------------------------------+
//| 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:
2026-02-24 12:47:37 -05:00
CRingBuffer m_policy_queue; // Non-template - stores serialized policy states
string m_current_state_serialized;
2025-10-16 18:03:47 -04:00
public:
2026-02-24 12:47:37 -05:00
CPolicyStateManager() : m_policy_queue(1024) {}
2025-10-16 18:03:47 -04:00
2026-02-24 12:47:37 -05:00
bool UpdateState(const string &serialized_state) {
m_current_state_serialized = serialized_state;
return m_policy_queue.Push(serialized_state);
2025-10-16 18:03:47 -04:00
}
2026-02-24 12:47:37 -05:00
string GetCurrentStateSerialized() const { return m_current_state_serialized; }
2025-10-16 18:03:47 -04:00
};