//+------------------------------------------------------------------+ //| ERMT 8.0 - Institutional Grade | //| External Risk Management Tool v7.1 | //| Ultra-Low Latency & ML-Enhanced | //+------------------------------------------------------------------+ #property copyright "Institutional Risk Management System v8.0" #property version "7.1" #property strict #property description "Next-gen modular risk system with ML and HFT optimizations" //--- Include system modules #include #include #include #include "Modules/RiskManager_v71.mqh" #include "Modules/TradeManager_v71.mqh" #include "Modules/EntrySystem_v71.mqh" #include "Modules/TechnicalAnalysis_v71.mqh" #include "Modules/Dashboard_v71.mqh" #include "Modules/Utilities_v71.mqh" #include "Modules/MultiTradeReporter_v71.mqh" #include "Modules/MLPredictor.mqh" #include "Modules/OrderFlowAnalyzer.mqh" #include "Modules/ExecutionOptimizer.mqh" //+------------------------------------------------------------------+ //| PERFORMANCE OPTIMIZATIONS | //+------------------------------------------------------------------+ #define CACHE_SIZE 1024 // Tick cache size #define MAX_SYMBOLS 50 // Maximum monitored symbols #define CORRELATION_WINDOW 100 // Bars for correlation calc #define ML_LOOKBACK 500 // ML training window #define TICK_BUFFER_SIZE 10000 // High-frequency tick buffer //+------------------------------------------------------------------+ //| INPUT PARAMETERS - INSTITUTIONAL CONFIGURATION | //+------------------------------------------------------------------+ //--- System Configuration input group "=== SYSTEM CONFIGURATION ===" input bool SystemEnabled = true; // Master Switch input int TradingMagic = 12345; // EA Magic Number input bool ManageExternalTrades = true; // Manage External Trades input int MagicNumberFilter = 0; // External Magic Filter input ENUM_LOG_LEVEL LogLevel = LOG_ERROR; // Logging Level (Optimized) input bool UltraLowLatencyMode = true; // Ultra-Low Latency Mode input int TickProcessingInterval = 1; // Tick Processing Interval (ms) //--- Entry System Parameters input group "=== ENTRY SYSTEM ===" input ENUM_ENTRY_MODE EntryMode = ENTRY_ML_ENHANCED; // Entry System Type input bool EnableMultipleEntries = true; // Allow Pyramiding input int MaxPositions = 10; // Maximum Positions input double MinTimeBetweenTrades = 5; // Min Seconds Between Trades input bool UseMLPrediction = true; // Use ML Entry Prediction input double MLConfidenceThreshold = 0.75; // ML Confidence Threshold //--- Risk Management Parameters input group "=== ADVANCED RISK MANAGEMENT ===" input ENUM_POSITION_SIZING SizingMode = PS_KELLY_ML; // Position Sizing Mode input double BaseRiskPercent = 1.0; // Base Risk Per Trade % input double MaxPortfolioRisk = 6.0; // Max Portfolio Risk % input double DailyVaRLimit = 3.0; // Daily VaR Limit % input double CVaRMultiplier = 1.5; // CVaR Risk Multiplier input bool UsePortfolioOptimization = true; // Portfolio Optimization input double MaxCorrelationExposure = 0.7; // Max Correlation Exposure //--- Execution Parameters input group "=== EXECUTION OPTIMIZATION ===" input bool UseSmartRouting = true; // Smart Order Routing input ENUM_EXECUTION_ALGO ExecutionAlgo = EXEC_ADAPTIVE; // Execution Algorithm input double MaxSlippagePips = 2.0; // Max Acceptable Slippage input bool UseIcebergOrders = true; // Use Iceberg Orders input double IcebergShowPercent = 20.0; // Iceberg Display % input int ExecutionRetries = 3; // Execution Retry Attempts //--- ML Configuration input group "=== MACHINE LEARNING ===" input bool EnableMLAdaptation = true; // Enable ML Adaptation input int MLUpdateFrequency = 3600; // ML Update Frequency (sec) input double MLLearningRate = 0.01; // ML Learning Rate input int MLMinTrainingSize = 100; // Min Training Samples input bool UseDeepLearning = true; // Use Deep Neural Network //--- Order Flow Analysis input group "=== ORDER FLOW ANALYSIS ===" input bool EnableOrderFlow = true; // Enable Order Flow Analysis input int VolumeProfilePeriod = 20; // Volume Profile Period input double LiquidityThreshold = 1000000; // Liquidity Threshold ($) input bool DetectInstitutionalFlow = true; // Detect Large Orders input double BlockTradeThreshold = 100000; // Block Trade Threshold ($) //--- Performance Monitoring input group "=== PERFORMANCE MONITORING ===" input bool EnableRealtimeAnalytics = true; // Real-time Analytics input int PerformanceUpdateMs = 100; // Performance Update (ms) input bool TrackExecutionQuality = true; // Track Execution Quality input bool GenerateInstitutionalReports = true; // Institutional Reports input string FIXGatewayID = ""; // FIX Gateway ID //+------------------------------------------------------------------+ //| GLOBAL VARIABLES - OPTIMIZED STRUCTURES | //+------------------------------------------------------------------+ //--- Module instances CRiskManagerV71* RiskMgr; CTradeManagerV71* TradeMgr; CEntrySystemV71* EntrySys; CTechnicalAnalysisV71* TechAnalysis; CDashboardV71* Dashboard; CUtilitiesV71* Utils; CMultiTradeReporterV71* Reporter; CMLPredictor* MLEngine; COrderFlowAnalyzer* OrderFlow; CExecutionOptimizer* ExecOptimizer; //--- System state with atomic operations struct SystemStateV71 { bool is_active; int magic_number; double start_balance; double peak_balance; datetime session_start; int tick_count; long last_tick_time; double current_var; double current_cvar; double portfolio_beta; double sharpe_real_time; CorrelationMatrix correlation_matrix; }; SystemStateV71 g_SystemState; PerformanceMetricsV71 g_Performance; MarketConditionsV71 g_MarketConditions; //--- Trade tracking with lock-free structures ManagedTradeV71 g_ManagedTrades[]; int g_TotalTrades = 0; ulong g_TradeVersion = 0; // Version for lock-free updates //--- High-performance tick cache struct TickCache { MqlTick ticks[TICK_BUFFER_SIZE]; int write_index; int read_index; int count; ulong last_update; }; TickCache g_TickCache[]; int g_CacheCount = 0; //--- Symbol monitoring with pre-calculated values struct SymbolDataV71 { string symbol; double tick_value; double tick_size; double min_lot; double max_lot; double lot_step; double contract_size; int digits; double point; double spread_average; double volatility_1m; double volatility_5m; double liquidity_score; datetime last_update; bool is_active; }; SymbolDataV71 g_SymbolData[MAX_SYMBOLS]; int g_ActiveSymbols = 0; //--- ML prediction cache struct MLPredictionCache { string symbol; ENUM_ORDER_TYPE predicted_direction; double confidence; double expected_return; double predicted_volatility; datetime prediction_time; bool is_valid; }; MLPredictionCache g_MLCache[MAX_SYMBOLS]; //--- Execution quality metrics struct ExecutionMetrics { double avg_slippage; double positive_slippage_rate; double avg_fill_time_ms; int rejected_orders; double improvement_rate; double vwap_performance; }; ExecutionMetrics g_ExecMetrics; //+------------------------------------------------------------------+ //| EXPERT INITIALIZATION - ULTRA OPTIMIZED | //+------------------------------------------------------------------+ int OnInit() { //--- Start performance timer ulong init_start = GetMicrosecondCount(); //--- Initialize system state g_SystemState.is_active = SystemEnabled; g_SystemState.magic_number = TradingMagic; g_SystemState.start_balance = AccountInfoDouble(ACCOUNT_BALANCE); g_SystemState.peak_balance = g_SystemState.start_balance; g_SystemState.session_start = TimeCurrent(); g_SystemState.tick_count = 0; g_SystemState.last_tick_time = 0; //--- Create module instances with optimized memory allocation RiskMgr = new CRiskManagerV71(); TradeMgr = new CTradeManagerV71(); EntrySys = new CEntrySystemV71(); TechAnalysis = new CTechnicalAnalysisV71(); Dashboard = new CDashboardV71(); Utils = new CUtilitiesV71(); Reporter = new CMultiTradeReporterV71(); //--- Initialize ML and advanced modules if(UseMLPrediction || EnableMLAdaptation) { MLEngine = new CMLPredictor(); if(!MLEngine.Initialize(ML_LOOKBACK, MLMinTrainingSize, UseDeepLearning)) { Print("Failed to initialize ML Engine"); return(INIT_FAILED); } } if(EnableOrderFlow) { OrderFlow = new COrderFlowAnalyzer(); if(!OrderFlow.Initialize(VolumeProfilePeriod, LiquidityThreshold)) { Print("Failed to initialize Order Flow Analyzer"); return(INIT_FAILED); } } if(UseSmartRouting) { ExecOptimizer = new CExecutionOptimizer(); if(!ExecOptimizer.Initialize(ExecutionAlgo, MaxSlippagePips)) { Print("Failed to initialize Execution Optimizer"); return(INIT_FAILED); } } //--- Initialize all modules if(!InitializeModulesV71()) { Print("Failed to initialize core modules"); return(INIT_FAILED); } //--- Pre-calculate symbol data for all monitored symbols if(!InitializeSymbolData()) { Print("Failed to initialize symbol data cache"); return(INIT_FAILED); } //--- Initialize tick caches for active symbols if(UltraLowLatencyMode) { ArrayResize(g_TickCache, g_ActiveSymbols); for(int i = 0; i < g_ActiveSymbols; i++) { g_TickCache[i].write_index = 0; g_TickCache[i].read_index = 0; g_TickCache[i].count = 0; g_TickCache[i].last_update = 0; } } //--- Load existing positions with optimized scanning LoadExistingPositionsOptimized(); //--- Initialize correlation matrix if(UsePortfolioOptimization) { InitializeCorrelationMatrix(); } //--- Create dashboard with institutional metrics if(ShowDashboard) { Dashboard.CreateInstitutional(DashboardX, DashboardY); Dashboard.UpdateInstitutional(g_Performance, g_SystemState, g_ExecMetrics); } //--- Set high-frequency timer if enabled if(UltraLowLatencyMode) { EventSetMillisecondTimer(TickProcessingInterval); } else { EventSetTimer(1); // Standard 1-second timer } //--- Log initialization metrics ulong init_time = GetMicrosecondCount() - init_start; Utils.Log(LOG_INFO, StringFormat("ERMT 7.1 initialized in %.2f ms. Symbols: %d, ML: %s, OrderFlow: %s", init_time / 1000.0, g_ActiveSymbols, UseMLPrediction ? "ON" : "OFF", EnableOrderFlow ? "ON" : "OFF")); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| EXPERT DEINITIALIZATION | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Kill timers EventKillTimer(); //--- Save ML model if enabled if(MLEngine != NULL && EnableMLAdaptation) { MLEngine.SaveModel("ERMT71_ML_Model.bin"); } //--- Generate final institutional report if(Reporter != NULL && GenerateInstitutionalReports) { Reporter.GenerateInstitutionalReport(g_Performance, g_ManagedTrades, g_ExecMetrics); } //--- Cleanup modules delete MLEngine; delete OrderFlow; delete ExecOptimizer; delete Reporter; delete RiskMgr; delete TradeMgr; delete EntrySys; delete TechAnalysis; delete Dashboard; delete Utils; Print("ERMT 7.1 shutdown complete: ", GetUninitReasonText(reason)); } //+------------------------------------------------------------------+ //| EXPERT TICK FUNCTION - ULTRA LOW LATENCY | //+------------------------------------------------------------------+ void OnTick() { //--- Ultra-fast system check if(!g_SystemState.is_active || !SystemEnabled) return; //--- Get current microsecond timestamp ulong tick_start = GetMicrosecondCount(); //--- Update tick counter g_SystemState.tick_count++; //--- Process current symbol tick with minimal latency MqlTick tick; if(!SymbolInfoTick(_Symbol, tick)) return; //--- Cache tick if in ultra-low latency mode if(UltraLowLatencyMode) { CacheTickData(_Symbol, tick); } //--- Fast order flow analysis if(EnableOrderFlow && OrderFlow != NULL) { OrderFlow.ProcessTick(_Symbol, tick); //--- Check for institutional flow signals if(DetectInstitutionalFlow) { double flow_imbalance = OrderFlow.GetFlowImbalance(_Symbol); if(MathAbs(flow_imbalance) > 0.7) { g_MarketConditions.institutional_flow = flow_imbalance; } } } //--- Update ML predictions if needed if(UseMLPrediction && MLEngine != NULL) { UpdateMLPredictions(_Symbol); } //--- Quick position check using cached data int symbol_index = GetSymbolIndex(_Symbol); if(symbol_index >= 0) { QuickPositionUpdate(symbol_index); } //--- Process entry signals with ML enhancement if(EntryMode != ENTRY_DISABLED && EntrySys != NULL) { ProcessEntrySignalsOptimized(); } //--- Risk monitoring with VaR/CVaR if(RiskMgr != NULL) { MonitorPortfolioRiskRealtime(); } //--- Update execution metrics if(TrackExecutionQuality) { UpdateExecutionMetrics(); } //--- Record tick processing time g_SystemState.last_tick_time = GetMicrosecondCount() - tick_start; } //+------------------------------------------------------------------+ //| TIMER FUNCTION - HIGH FREQUENCY PROCESSING | //+------------------------------------------------------------------+ void OnTimer() { //--- Process all cached ticks if(UltraLowLatencyMode) { ProcessCachedTicks(); } //--- Update all positions UpdateAllPositionsOptimized(); //--- Portfolio rebalancing check if(UsePortfolioOptimization && g_SystemState.tick_count % 100 == 0) { OptimizePortfolioWeights(); } //--- ML model update if(EnableMLAdaptation && MLEngine != NULL) { if(TimeCurrent() - MLEngine.GetLastUpdateTime() > MLUpdateFrequency) { MLEngine.UpdateModel(g_ManagedTrades); } } //--- Update institutional dashboard if(ShowDashboard && Dashboard != NULL) { Dashboard.UpdateInstitutional(g_Performance, g_SystemState, g_ExecMetrics); } } //+------------------------------------------------------------------+ //| MILLISECOND TIMER - ULTRA LOW LATENCY | //+------------------------------------------------------------------+ void OnMillisecondTimer() { if(!UltraLowLatencyMode) return; //--- Process high-priority tasks ProcessHighPriorityTasks(); //--- Update real-time analytics if(EnableRealtimeAnalytics && g_SystemState.tick_count % (PerformanceUpdateMs / TickProcessingInterval) == 0) { UpdateRealtimeAnalytics(); } } //+------------------------------------------------------------------+ //| INITIALIZE MODULES V7.1 | //+------------------------------------------------------------------+ bool InitializeModulesV71() { //--- Risk Manager with advanced features RiskManagerConfigV71 risk_config; risk_config.sizing_mode = SizingMode; risk_config.risk_percent = BaseRiskPercent; risk_config.max_risk = MaxPortfolioRisk; risk_config.daily_var_limit = DailyVaRLimit; risk_config.cvar_multiplier = CVaRMultiplier; risk_config.use_portfolio_optimization = UsePortfolioOptimization; risk_config.max_correlation = MaxCorrelationExposure; if(!RiskMgr.Initialize(risk_config)) return false; //--- Trade Manager with execution optimization TradeManagerConfigV71 trade_config; trade_config.magic_number = TradingMagic; trade_config.use_smart_routing = UseSmartRouting; trade_config.execution_algo = ExecutionAlgo; trade_config.max_slippage = MaxSlippagePips; trade_config.use_iceberg = UseIcebergOrders; trade_config.iceberg_percent = IcebergShowPercent; trade_config.retry_attempts = ExecutionRetries; if(!TradeMgr.Initialize(trade_config)) return false; //--- Entry System with ML EntrySystemConfigV71 entry_config; entry_config.mode = EntryMode; entry_config.use_ml = UseMLPrediction; entry_config.ml_threshold = MLConfidenceThreshold; entry_config.max_positions = MaxPositions; entry_config.min_time_between = MinTimeBetweenTrades; if(!EntrySys.Initialize(entry_config)) return false; //--- Technical Analysis enhanced if(!TechAnalysis.InitializeEnhanced(CORRELATION_WINDOW)) return false; //--- Utilities with performance optimization if(!Utils.InitializeOptimized(LogLevel, UltraLowLatencyMode)) return false; return true; } //+------------------------------------------------------------------+ //| INITIALIZE SYMBOL DATA CACHE | //+------------------------------------------------------------------+ bool InitializeSymbolData() { g_ActiveSymbols = 0; //--- Get all symbols in Market Watch int total_symbols = SymbolsTotal(true); for(int i = 0; i < total_symbols && g_ActiveSymbols < MAX_SYMBOLS; i++) { string symbol = SymbolName(i, true); //--- Skip if not selected in Market Watch if(!SymbolInfoInteger(symbol, SYMBOL_SELECT)) continue; //--- Cache symbol data g_SymbolData[g_ActiveSymbols].symbol = symbol; g_SymbolData[g_ActiveSymbols].tick_value = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); g_SymbolData[g_ActiveSymbols].tick_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); g_SymbolData[g_ActiveSymbols].min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); g_SymbolData[g_ActiveSymbols].max_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX); g_SymbolData[g_ActiveSymbols].lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); g_SymbolData[g_ActiveSymbols].contract_size = SymbolInfoDouble(symbol, SYMBOL_TRADE_CONTRACT_SIZE); g_SymbolData[g_ActiveSymbols].digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS); g_SymbolData[g_ActiveSymbols].point = SymbolInfoDouble(symbol, SYMBOL_POINT); g_SymbolData[g_ActiveSymbols].is_active = true; g_SymbolData[g_ActiveSymbols].last_update = TimeCurrent(); //--- Calculate initial volatility double atr = TechAnalysis.GetSymbolATR(symbol, 14); g_SymbolData[g_ActiveSymbols].volatility_5m = atr; g_ActiveSymbols++; } Print("Initialized ", g_ActiveSymbols, " symbols in cache"); return g_ActiveSymbols > 0; } //+------------------------------------------------------------------+ //| CACHE TICK DATA FOR BATCH PROCESSING | //+------------------------------------------------------------------+ void CacheTickData(string symbol, MqlTick &tick) { int index = GetSymbolIndex(symbol); if(index < 0 || index >= ArraySize(g_TickCache)) return; //--- Add tick to circular buffer int write_pos = g_TickCache[index].write_index; g_TickCache[index].ticks[write_pos] = tick; //--- Update indices g_TickCache[index].write_index = (write_pos + 1) % TICK_BUFFER_SIZE; if(g_TickCache[index].count < TICK_BUFFER_SIZE) g_TickCache[index].count++; else g_TickCache[index].read_index = (g_TickCache[index].read_index + 1) % TICK_BUFFER_SIZE; g_TickCache[index].last_update = tick.time_msc; } //+------------------------------------------------------------------+ //| PROCESS CACHED TICKS IN BATCH | //+------------------------------------------------------------------+ void ProcessCachedTicks() { for(int i = 0; i < g_ActiveSymbols; i++) { if(g_TickCache[i].count == 0) continue; //--- Process available ticks while(g_TickCache[i].read_index != g_TickCache[i].write_index) { MqlTick tick = g_TickCache[i].ticks[g_TickCache[i].read_index]; //--- Update spread tracking double spread = (tick.ask - tick.bid) / g_SymbolData[i].point; g_SymbolData[i].spread_average = 0.9 * g_SymbolData[i].spread_average + 0.1 * spread; //--- Update volatility estimate static double last_price[MAX_SYMBOLS] = {0}; if(last_price[i] > 0) { double price_change = MathAbs(tick.bid - last_price[i]); g_SymbolData[i].volatility_1m = 0.95 * g_SymbolData[i].volatility_1m + 0.05 * price_change; } last_price[i] = tick.bid; //--- Move to next tick g_TickCache[i].read_index = (g_TickCache[i].read_index + 1) % TICK_BUFFER_SIZE; g_TickCache[i].count--; } } } //+------------------------------------------------------------------+ //| UPDATE ML PREDICTIONS | //+------------------------------------------------------------------+ void UpdateMLPredictions(string symbol) { int index = GetSymbolIndex(symbol); if(index < 0 || MLEngine == NULL) return; //--- Check if prediction is still valid if(g_MLCache[index].is_valid && TimeCurrent() - g_MLCache[index].prediction_time < 60) // 1-minute cache return; //--- Get new prediction MLPrediction prediction = MLEngine.Predict(symbol); //--- Update cache g_MLCache[index].symbol = symbol; g_MLCache[index].predicted_direction = prediction.direction; g_MLCache[index].confidence = prediction.confidence; g_MLCache[index].expected_return = prediction.expected_return; g_MLCache[index].predicted_volatility = prediction.volatility; g_MLCache[index].prediction_time = TimeCurrent(); g_MLCache[index].is_valid = true; } //+------------------------------------------------------------------+ //| PROCESS ENTRY SIGNALS WITH ML | //+------------------------------------------------------------------+ void ProcessEntrySignalsOptimized() { //--- Check position limits if(ArraySize(g_ManagedTrades) >= MaxPositions) return; //--- Check time between trades static datetime last_trade_time = 0; if(TimeCurrent() - last_trade_time < MinTimeBetweenTrades) return; //--- Get base signal EntrySignalV71 signal = EntrySys.CheckSignalEnhanced(_Symbol, g_MarketConditions); //--- Enhance with ML if enabled if(UseMLPrediction && signal.strength > 0) { int index = GetSymbolIndex(_Symbol); if(index >= 0 && g_MLCache[index].is_valid) { //--- Combine signals if(g_MLCache[index].confidence >= MLConfidenceThreshold) { signal.strength *= (1.0 + g_MLCache[index].confidence); signal.expected_return = g_MLCache[index].expected_return; signal.ml_enhanced = true; } } } //--- Validate with order flow if(EnableOrderFlow && OrderFlow != NULL) { double flow_signal = OrderFlow.GetSignalStrength(_Symbol); signal.strength *= (1.0 + flow_signal * 0.5); } //--- Execute if signal is strong enough if(signal.strength >= EntrySys.GetMinSignalStrength()) { ExecuteOptimizedEntry(signal); last_trade_time = TimeCurrent(); } } //+------------------------------------------------------------------+ //| EXECUTE OPTIMIZED ENTRY | //+------------------------------------------------------------------+ void ExecuteOptimizedEntry(EntrySignalV71 &signal) { //--- Calculate position size with portfolio optimization double position_size = RiskMgr.CalculateOptimalSize( signal.symbol, signal.stop_loss, signal.expected_return, g_SystemState.correlation_matrix ); //--- Apply execution optimization if(UseSmartRouting && ExecOptimizer != NULL) { ExecutionPlan plan = ExecOptimizer.CreatePlan( signal.symbol, signal.direction, position_size, signal.entry_price ); //--- Execute with smart routing bool success = TradeMgr.ExecuteSmartOrder(plan); //--- Track execution quality if(success && TrackExecutionQuality) { double slippage = TradeMgr.GetLastExecutionSlippage(); UpdateExecutionStats(slippage); } } else { //--- Standard execution TradeMgr.OpenPosition( signal.symbol, signal.direction, position_size, signal.stop_loss, signal.take_profit, signal.comment ); } } //+------------------------------------------------------------------+ //| MONITOR PORTFOLIO RISK IN REAL-TIME | //+------------------------------------------------------------------+ void MonitorPortfolioRiskRealtime() { //--- Calculate current VaR g_SystemState.current_var = RiskMgr.CalculatePortfolioVaR( g_ManagedTrades, 0.95, // 95% confidence 1 // 1-day horizon ); //--- Calculate CVaR g_SystemState.current_cvar = RiskMgr.CalculatePortfolioCVaR( g_ManagedTrades, 0.95, 1 ); //--- Check limits if(g_SystemState.current_var > DailyVaRLimit) { Utils.Log(LOG_WARNING, StringFormat("VaR limit exceeded: %.2f%% > %.2f%%", g_SystemState.current_var, DailyVaRLimit)); //--- Reduce positions if needed if(UsePortfolioOptimization) { ReducePortfolioRisk(); } } //--- Update correlation matrix if(g_SystemState.tick_count % 1000 == 0) { UpdateCorrelationMatrix(); } } //+------------------------------------------------------------------+ //| UPDATE CORRELATION MATRIX | //+------------------------------------------------------------------+ void UpdateCorrelationMatrix() { int active_count = 0; string active_symbols[]; //--- Get active symbols from positions for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { bool found = false; for(int j = 0; j < active_count; j++) { if(active_symbols[j] == g_ManagedTrades[i].symbol) { found = true; break; } } if(!found) { ArrayResize(active_symbols, active_count + 1); active_symbols[active_count] = g_ManagedTrades[i].symbol; active_count++; } } //--- Calculate correlations if(active_count > 1) { g_SystemState.correlation_matrix = TechAnalysis.CalculateCorrelationMatrix( active_symbols, CORRELATION_WINDOW ); } } //+------------------------------------------------------------------+ //| OPTIMIZE PORTFOLIO WEIGHTS | //+------------------------------------------------------------------+ void OptimizePortfolioWeights() { if(!UsePortfolioOptimization || ArraySize(g_ManagedTrades) < 2) return; //--- Get optimal weights using Markowitz optimization double weights[]; double expected_returns[]; double covariance_matrix[]; //--- Prepare data int n = ArraySize(g_ManagedTrades); ArrayResize(weights, n); ArrayResize(expected_returns, n); for(int i = 0; i < n; i++) { expected_returns[i] = g_ManagedTrades[i].expected_return; } //--- Calculate optimal weights RiskMgr.CalculateOptimalWeights( expected_returns, g_SystemState.correlation_matrix, g_SystemState.current_var, weights ); //--- Rebalance positions RebalancePortfolio(weights); } //+------------------------------------------------------------------+ //| GET SYMBOL INDEX IN CACHE | //+------------------------------------------------------------------+ int GetSymbolIndex(string symbol) { for(int i = 0; i < g_ActiveSymbols; i++) { if(g_SymbolData[i].symbol == symbol) return i; } return -1; } //+------------------------------------------------------------------+ //| QUICK POSITION UPDATE | //+------------------------------------------------------------------+ void QuickPositionUpdate(int symbol_index) { //--- Update positions for specific symbol for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { if(g_ManagedTrades[i].symbol == g_SymbolData[symbol_index].symbol) { //--- Fast update using cached values if(PositionSelectByTicket(g_ManagedTrades[i].ticket)) { g_ManagedTrades[i].profit = PositionGetDouble(POSITION_PROFIT); g_ManagedTrades[i].swap = PositionGetDouble(POSITION_SWAP); //--- Update risk metrics double current_price = (g_ManagedTrades[i].type == POSITION_TYPE_BUY) ? SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_BID) : SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_ASK); //--- Apply management rules if(TradeMgr != NULL) { TradeMgr.ManageTradeOptimized(g_ManagedTrades[i], g_SymbolData[symbol_index]); } } } } } //+------------------------------------------------------------------+ //| UPDATE ALL POSITIONS OPTIMIZED | //+------------------------------------------------------------------+ void UpdateAllPositionsOptimized() { //--- Batch update all positions ulong start_time = GetMicrosecondCount(); int positions_total = PositionsTotal(); //--- First pass: collect all position tickets ulong tickets[]; ArrayResize(tickets, positions_total); for(int i = 0; i < positions_total; i++) { tickets[i] = PositionGetTicket(i); } //--- Second pass: update managed trades for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { bool found = false; for(int j = 0; j < positions_total; j++) { if(g_ManagedTrades[i].ticket == tickets[j]) { found = true; //--- Update position data if(PositionSelectByTicket(tickets[j])) { UpdateManagedTrade(g_ManagedTrades[i]); } break; } } //--- Remove if position closed if(!found) { RemoveManagedTrade(i); i--; } } //--- Third pass: add new external trades if(ManageExternalTrades) { CheckForNewExternalTradesOptimized(tickets); } //--- Update performance metrics UpdatePerformanceMetrics(); //--- Log update time in microseconds ulong update_time = GetMicrosecondCount() - start_time; if(update_time > 1000) // Log if takes more than 1ms { Utils.Log(LOG_DEBUG, StringFormat("Position update took %.2f ms", update_time / 1000.0)); } } //+------------------------------------------------------------------+ //| LOAD EXISTING POSITIONS OPTIMIZED | //+------------------------------------------------------------------+ void LoadExistingPositionsOptimized() { int positions = PositionsTotal(); ArrayResize(g_ManagedTrades, 0); for(int i = 0; i < positions; i++) { ulong ticket = PositionGetTicket(i); if(ticket == 0) continue; if(PositionSelectByTicket(ticket)) { //--- Check if we should manage this position long magic = PositionGetInteger(POSITION_MAGIC); if(magic == TradingMagic || (ManageExternalTrades && (MagicNumberFilter == 0 || magic == MagicNumberFilter))) { //--- Create managed trade ManagedTradeV71 trade; if(CreateManagedTradeOptimized(ticket, trade)) { ArrayResize(g_ManagedTrades, ArraySize(g_ManagedTrades) + 1); g_ManagedTrades[ArraySize(g_ManagedTrades) - 1] = trade; } } } } g_TotalTrades = ArraySize(g_ManagedTrades); Print("Loaded ", g_TotalTrades, " existing positions"); } //+------------------------------------------------------------------+ //| CREATE MANAGED TRADE OPTIMIZED | //+------------------------------------------------------------------+ bool CreateManagedTradeOptimized(ulong ticket, ManagedTradeV71 &trade) { if(!PositionSelectByTicket(ticket)) return false; //--- Fill basic data trade.ticket = ticket; trade.symbol = PositionGetString(POSITION_SYMBOL); trade.magic = PositionGetInteger(POSITION_MAGIC); trade.type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); trade.volume = PositionGetDouble(POSITION_VOLUME); trade.open_price = PositionGetDouble(POSITION_PRICE_OPEN); trade.open_time = (datetime)PositionGetInteger(POSITION_TIME); trade.sl = PositionGetDouble(POSITION_SL); trade.tp = PositionGetDouble(POSITION_TP); trade.profit = PositionGetDouble(POSITION_PROFIT); trade.swap = PositionGetDouble(POSITION_SWAP); trade.comment = PositionGetString(POSITION_COMMENT); //--- Get symbol data int symbol_index = GetSymbolIndex(trade.symbol); if(symbol_index < 0) return false; //--- Calculate risk metrics using cached data if(trade.sl > 0) { double stop_distance = (trade.type == POSITION_TYPE_BUY) ? trade.open_price - trade.sl : trade.sl - trade.open_price; double potential_loss = (stop_distance / g_SymbolData[symbol_index].tick_size) * g_SymbolData[symbol_index].tick_value * trade.volume; trade.risk_amount = potential_loss; trade.risk_percent = (potential_loss / AccountInfoDouble(ACCOUNT_BALANCE)) * 100; } //--- Initialize management flags trade.is_managed = true; trade.is_external = (trade.magic != TradingMagic); trade.management_start = TimeCurrent(); //--- Get ML prediction if available if(UseMLPrediction && g_MLCache[symbol_index].is_valid) { trade.expected_return = g_MLCache[symbol_index].expected_return; trade.ml_confidence = g_MLCache[symbol_index].confidence; } return true; } //+------------------------------------------------------------------+ //| CHECK FOR NEW EXTERNAL TRADES OPTIMIZED | //+------------------------------------------------------------------+ void CheckForNewExternalTradesOptimized(ulong &tickets[]) { int ticket_count = ArraySize(tickets); for(int i = 0; i < ticket_count; i++) { if(!PositionSelectByTicket(tickets[i])) continue; long magic = PositionGetInteger(POSITION_MAGIC); //--- Skip our own trades if(magic == TradingMagic) continue; //--- Check magic filter if(MagicNumberFilter != 0 && magic != MagicNumberFilter) continue; //--- Check if already managed bool already_managed = false; for(int j = 0; j < ArraySize(g_ManagedTrades); j++) { if(g_ManagedTrades[j].ticket == tickets[i]) { already_managed = true; break; } } if(!already_managed) { //--- Add new external trade ManagedTradeV71 trade; if(CreateManagedTradeOptimized(tickets[i], trade)) { ArrayResize(g_ManagedTrades, ArraySize(g_ManagedTrades) + 1); g_ManagedTrades[ArraySize(g_ManagedTrades) - 1] = trade; Utils.Log(LOG_INFO, StringFormat("New external trade detected: #%d", tickets[i])); //--- Apply risk rules if(RiskMgr != NULL) { RiskMgr.EnforceRiskRulesOptimized(g_ManagedTrades[ArraySize(g_ManagedTrades) - 1]); } } } } } //+------------------------------------------------------------------+ //| UPDATE MANAGED TRADE | //+------------------------------------------------------------------+ void UpdateManagedTrade(ManagedTradeV71 &trade) { //--- Update current values trade.profit = PositionGetDouble(POSITION_PROFIT); trade.swap = PositionGetDouble(POSITION_SWAP); trade.commission = Utils.CalculateCommissionOptimized(trade.ticket); //--- Update derived metrics double current_pl = trade.profit + trade.swap + trade.commission; if(trade.risk_amount > 0) { trade.r_multiple = current_pl / trade.risk_amount; } //--- Track MAE/MFE if(current_pl < trade.mae) trade.mae = current_pl; if(current_pl > trade.mfe) trade.mfe = current_pl; //--- Update time in trade trade.bars_in_trade = iBars(trade.symbol, PERIOD_CURRENT) - iBarShift(trade.symbol, PERIOD_CURRENT, trade.open_time); } //+------------------------------------------------------------------+ //| REMOVE MANAGED TRADE | //+------------------------------------------------------------------+ void RemoveManagedTrade(int index) { if(index < 0 || index >= ArraySize(g_ManagedTrades)) return; //--- Save to history if enabled if(GenerateReports) { Utils.SaveTradeHistoryOptimized(g_ManagedTrades[index]); } //--- Update performance metrics g_Performance.total_trades++; if(g_ManagedTrades[index].profit > 0) { g_Performance.winning_trades++; g_Performance.gross_profit += g_ManagedTrades[index].profit; } else { g_Performance.losing_trades++; g_Performance.gross_loss += MathAbs(g_ManagedTrades[index].profit); } //--- Remove from array ArrayRemove(g_ManagedTrades, index, 1); g_TotalTrades = ArraySize(g_ManagedTrades); } //+------------------------------------------------------------------+ //| UPDATE PERFORMANCE METRICS | //+------------------------------------------------------------------+ void UpdatePerformanceMetrics() { //--- Calculate basic metrics g_Performance.net_profit = g_Performance.gross_profit - g_Performance.gross_loss; g_Performance.profit_factor = (g_Performance.gross_loss > 0) ? g_Performance.gross_profit / g_Performance.gross_loss : 0; g_Performance.win_rate = (g_Performance.total_trades > 0) ? (double)g_Performance.winning_trades / g_Performance.total_trades * 100 : 0; //--- Update drawdown double current_balance = AccountInfoDouble(ACCOUNT_BALANCE); if(current_balance > g_SystemState.peak_balance) g_SystemState.peak_balance = current_balance; double drawdown = g_SystemState.peak_balance - current_balance; double drawdown_percent = (g_SystemState.peak_balance > 0) ? drawdown / g_SystemState.peak_balance * 100 : 0; if(drawdown_percent > g_Performance.max_drawdown_percent) { g_Performance.max_drawdown = drawdown; g_Performance.max_drawdown_percent = drawdown_percent; } //--- Calculate Sharpe ratio (simplified) if(g_Performance.total_trades > 30) { double returns[]; ArrayResize(returns, g_Performance.total_trades); // Simplified: use fixed return calculation double avg_return = g_Performance.net_profit / g_Performance.total_trades; double std_dev = MathSqrt(g_Performance.gross_loss / g_Performance.total_trades); if(std_dev > 0) g_Performance.sharpe_ratio = avg_return / std_dev * MathSqrt(252); // Annualized } //--- Update real-time Sharpe g_SystemState.sharpe_real_time = g_Performance.sharpe_ratio; } //+------------------------------------------------------------------+ //| UPDATE EXECUTION METRICS | //+------------------------------------------------------------------+ void UpdateExecutionMetrics() { //--- Get latest execution data from trade manager if(TradeMgr != NULL) { ExecutionStats stats = TradeMgr.GetExecutionStats(); //--- Update metrics with exponential smoothing g_ExecMetrics.avg_slippage = 0.9 * g_ExecMetrics.avg_slippage + 0.1 * stats.last_slippage; g_ExecMetrics.avg_fill_time_ms = 0.9 * g_ExecMetrics.avg_fill_time_ms + 0.1 * stats.last_fill_time; if(stats.last_slippage < 0) g_ExecMetrics.positive_slippage_rate = 0.95 * g_ExecMetrics.positive_slippage_rate + 0.05; else g_ExecMetrics.positive_slippage_rate = 0.95 * g_ExecMetrics.positive_slippage_rate; g_ExecMetrics.rejected_orders = stats.total_rejected; } } //+------------------------------------------------------------------+ //| PROCESS HIGH PRIORITY TASKS | //+------------------------------------------------------------------+ void ProcessHighPriorityTasks() { //--- Check for stop loss hits for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { if(g_ManagedTrades[i].sl > 0) { double current_price = (g_ManagedTrades[i].type == POSITION_TYPE_BUY) ? SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_BID) : SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_ASK); bool sl_hit = (g_ManagedTrades[i].type == POSITION_TYPE_BUY && current_price <= g_ManagedTrades[i].sl) || (g_ManagedTrades[i].type == POSITION_TYPE_SELL && current_price >= g_ManagedTrades[i].sl); if(sl_hit && UseSmartRouting) { //--- Execute emergency close with smart routing ExecOptimizer.ExecuteEmergencyClose(g_ManagedTrades[i].ticket); } } } //--- Check for critical risk events if(g_SystemState.current_var > DailyVaRLimit * 1.2) { Utils.Log(LOG_CRITICAL, "Critical VaR breach - initiating risk reduction"); EmergencyRiskReduction(); } } //+------------------------------------------------------------------+ //| UPDATE REAL-TIME ANALYTICS | //+------------------------------------------------------------------+ void UpdateRealtimeAnalytics() { //--- Portfolio Greeks if(UsePortfolioOptimization) { g_SystemState.portfolio_beta = RiskMgr.CalculatePortfolioBeta(g_ManagedTrades); } //--- Liquidity analysis if(EnableOrderFlow && OrderFlow != NULL) { for(int i = 0; i < g_ActiveSymbols; i++) { g_SymbolData[i].liquidity_score = OrderFlow.GetLiquidityScore(g_SymbolData[i].symbol); } } //--- Performance attribution if(Reporter != NULL && g_Performance.total_trades > 0) { Reporter.UpdatePerformanceAttribution(g_ManagedTrades, g_Performance); } } //+------------------------------------------------------------------+ //| REDUCE PORTFOLIO RISK | //+------------------------------------------------------------------+ void ReducePortfolioRisk() { //--- Sort trades by risk contribution RiskContribution contributions[]; ArrayResize(contributions, ArraySize(g_ManagedTrades)); for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { contributions[i].index = i; contributions[i].risk = g_ManagedTrades[i].risk_percent; contributions[i].correlation_risk = RiskMgr.CalculateCorrelationRisk( g_ManagedTrades[i], g_SystemState.correlation_matrix ); } //--- Sort by total risk contribution ArraySort(contributions); //--- Reduce highest risk positions int positions_to_reduce = MathMin(3, ArraySize(contributions)); for(int i = 0; i < positions_to_reduce; i++) { int index = contributions[ArraySize(contributions) - 1 - i].index; //--- Reduce position by 50% double reduce_volume = g_ManagedTrades[index].volume * 0.5; TradeMgr.PartialCloseOptimized(g_ManagedTrades[index].ticket, reduce_volume); Utils.Log(LOG_WARNING, StringFormat("Reduced position #%d by 50%% due to risk limits", g_ManagedTrades[index].ticket)); } } //+------------------------------------------------------------------+ //| EMERGENCY RISK REDUCTION | //+------------------------------------------------------------------+ void EmergencyRiskReduction() { //--- Close all losing positions immediately for(int i = ArraySize(g_ManagedTrades) - 1; i >= 0; i--) { if(g_ManagedTrades[i].profit < 0) { TradeMgr.ClosePositionOptimized(g_ManagedTrades[i].ticket); } } //--- Reduce all winning positions by 75% for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { if(g_ManagedTrades[i].profit > 0) { double reduce_volume = g_ManagedTrades[i].volume * 0.75; TradeMgr.PartialCloseOptimized(g_ManagedTrades[i].ticket, reduce_volume); } } //--- Disable new entries g_SystemState.is_active = false; Utils.Log(LOG_CRITICAL, "Emergency risk reduction completed - system disabled"); } //+------------------------------------------------------------------+ //| REBALANCE PORTFOLIO | //+------------------------------------------------------------------+ void RebalancePortfolio(double &target_weights[]) { //--- Calculate current weights double total_value = 0; double current_values[]; ArrayResize(current_values, ArraySize(g_ManagedTrades)); for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { current_values[i] = g_ManagedTrades[i].volume * SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_BID) * g_SymbolData[GetSymbolIndex(g_ManagedTrades[i].symbol)].contract_size; total_value += current_values[i]; } //--- Calculate adjustments needed for(int i = 0; i < ArraySize(g_ManagedTrades); i++) { double current_weight = current_values[i] / total_value; double weight_diff = target_weights[i] - current_weight; if(MathAbs(weight_diff) > 0.05) // 5% threshold { //--- Calculate volume adjustment double target_value = total_value * target_weights[i]; double value_diff = target_value - current_values[i]; int symbol_index = GetSymbolIndex(g_ManagedTrades[i].symbol); double adj_volume = MathAbs(value_diff) / (SymbolInfoDouble(g_ManagedTrades[i].symbol, SYMBOL_BID) * g_SymbolData[symbol_index].contract_size); //--- Normalize to lot step adj_volume = MathRound(adj_volume / g_SymbolData[symbol_index].lot_step) * g_SymbolData[symbol_index].lot_step; if(value_diff < 0 && adj_volume > 0) { //--- Reduce position TradeMgr.PartialCloseOptimized(g_ManagedTrades[i].ticket, adj_volume); } else if(value_diff > 0 && adj_volume > 0) { //--- Increase position (if allowed) if(EnableMultipleEntries) { TradeMgr.AddToPositionOptimized(g_ManagedTrades[i], adj_volume); } } } } } //+------------------------------------------------------------------+ //| GET UNINIT REASON TEXT | //+------------------------------------------------------------------+ string GetUninitReasonText(int reason) { switch(reason) { case REASON_PROGRAM: return "Program terminated"; case REASON_REMOVE: return "Program removed from chart"; case REASON_RECOMPILE: return "Program recompiled"; case REASON_CHARTCHANGE: return "Symbol or timeframe changed"; case REASON_CHARTCLOSE: return "Chart closed"; case REASON_PARAMETERS: return "Input parameters changed"; case REASON_ACCOUNT: return "Account changed"; default: return "Other reason"; } }