1461 lines
51 KiB
MQL5
1461 lines
51 KiB
MQL5
|
//+------------------------------------------------------------------+
|
||
|
//| 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 <Trade/Trade.mqh>
|
||
|
#include <Math/Stat/Math.mqh>
|
||
|
#include <Arrays/ArrayObj.mqh>
|
||
|
#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";
|
||
|
}
|
||
|
}
|