//+------------------------------------------------------------------+ //| DAX_ORB_Ultimate_AI_MT5.mq5 | //| AI-Enhanced ORB Trading Bot | //| Version 2.0 | //+------------------------------------------------------------------+ #property copyright "AI Trading Systems" #property link "https://github.com/ai-trading" #property version "2.00" #property description "DAX Opening Range Breakout with AI/ML Integration" #property description "- Advanced AI signal filtering and market regime detection" #property description "- Dynamic risk management and position sizing" #property description "- Real-time volatility adaptation" #property description "- News sentiment integration" //--- Input parameters //============================= ORB SETTINGS ============================= input group "ORB Settings" input int InpORBStartHour = 7; // ORB Start Hour (UTC) input int InpORBStartMinute = 40; // ORB Start Minute input int InpORBEndHour = 8; // ORB End Hour (UTC) input int InpORBEndMinute = 0; // ORB End Minute input bool InpExcludeWicks = true; // Exclude Wicks from ORB input int InpMarketCloseHour = 16; // Market Close Hour //============================= AI/ML SETTINGS ============================= input group "AI/ML Settings" input bool InpEnableAI = true; // Enable AI Integration input double InpAIThreshold = 0.7; // AI Confidence Threshold (0.1-1.0) input int InpMarketRegimeWindow = 50; // Market Regime Window (20-200) input int InpFeaturePeriod = 100; // Feature Engineering Period (50-500) input double InpNewsSentimentWeight = 0.3; // News Sentiment Weight (0.0-1.0) //============================= RISK MANAGEMENT ============================= input group "Risk Management" input double InpVolume = 0.1; // Volume (Lots) input bool InpUseDynamicSizing = true; // Dynamic Position Sizing input double InpRiskPerTrade = 1.0; // Risk Per Trade (%) input bool InpUseDynamicSL = true; // Use Dynamic SL/TP input double InpBaseSL = 30; // Base SL (Pips) input double InpBaseTP = 90; // Base TP (Pips) input double InpVolatilityFactor = 1.5; // Volatility Adjustment Factor input double InpMinRR = 2.0; // Minimum R:R Ratio input string InpMagicComment = "DAX_ORB_AI"; // Order Comment //============================= TRAILING STOP ============================= input group "Trailing Stop" input bool InpUseTrailing = true; // Use Trailing Stop input double InpTrailStart = 1.0; // Trail Start (ATR multiplier) input double InpTrailDistance = 1.0; // Trail Distance (ATR multiplier) //--- Global variables //============================= INDICATORS ============================= int atr_handle; int ema9_handle, ema21_handle, ema50_handle; int rsi_handle; int macd_handle; int bb_handle; int stddev_handle; int momentum_handle; //============================= ORB VARIABLES ============================= double orb_high = 0; double orb_low = 0; bool orb_ready = false; double orb_building_high = 0; double orb_building_low = 0; datetime last_orb_date = 0; double highest_since_entry = 0; double lowest_since_entry = DBL_MAX; //============================= AI/ML VARIABLES ============================= double price_features[]; double volume_features[]; double volatility_features[]; double recent_predictions[]; double current_market_regime = 0; // -1 = bearish, 0 = neutral, 1 = bullish double ai_signal_confidence = 0; double last_news_sentiment = 0; //============================= DYNAMIC RISK VARIABLES ============================= double current_volatility = 0; double market_stress = 0; double adaptive_risk_multiplier = 1.0; //============================= MAGIC NUMBER ============================= int magic_number = 20241105; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Initialize indicators atr_handle = iATR(_Symbol, PERIOD_CURRENT, 14); ema9_handle = iMA(_Symbol, PERIOD_CURRENT, 9, 0, MODE_EMA, PRICE_CLOSE); ema21_handle = iMA(_Symbol, PERIOD_CURRENT, 21, 0, MODE_EMA, PRICE_CLOSE); ema50_handle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_EMA, PRICE_CLOSE); rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); bb_handle = iBands(_Symbol, PERIOD_CURRENT, 20, 0, 2.0, PRICE_CLOSE); stddev_handle = iStdDev(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE); momentum_handle = iMomentum(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE); //--- Check indicator handles if(atr_handle == INVALID_HANDLE || ema9_handle == INVALID_HANDLE || ema21_handle == INVALID_HANDLE || ema50_handle == INVALID_HANDLE || rsi_handle == INVALID_HANDLE || macd_handle == INVALID_HANDLE || bb_handle == INVALID_HANDLE || stddev_handle == INVALID_HANDLE || momentum_handle == INVALID_HANDLE) { Print("Error initializing indicators"); return INIT_FAILED; } //--- Initialize AI components if(InpEnableAI) { InitializeAIFeatures(); Print("AI Integration enabled"); } //--- Initialize dynamic risk parameters double atr_buffer[]; ArraySetAsSeries(atr_buffer, true); if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) > 0) current_volatility = atr_buffer[0]; adaptive_risk_multiplier = 1.0; Print("DAX ORB Ultimate AI MT5 EA started successfully"); Print("AI Enabled: ", InpEnableAI, ", Dynamic SL/TP: ", InpUseDynamicSL, ", Dynamic Sizing: ", InpUseDynamicSizing); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Release indicator handles IndicatorRelease(atr_handle); IndicatorRelease(ema9_handle); IndicatorRelease(ema21_handle); IndicatorRelease(ema50_handle); IndicatorRelease(rsi_handle); IndicatorRelease(macd_handle); IndicatorRelease(bb_handle); IndicatorRelease(stddev_handle); IndicatorRelease(momentum_handle); Print("DAX ORB Ultimate AI MT5 EA stopped"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Check for new bar static datetime last_bar_time = 0; datetime current_bar_time = iTime(_Symbol, PERIOD_CURRENT, 0); if(current_bar_time == last_bar_time) return; last_bar_time = current_bar_time; //--- Main logic on new bar OnBar(); } //+------------------------------------------------------------------+ //| New bar processing function | //+------------------------------------------------------------------+ void OnBar() { datetime current_time = TimeCurrent(); MqlDateTime dt_struct; TimeToStruct(current_time, dt_struct); datetime current_date = StringToTime(StringFormat("%04d.%02d.%02d", dt_struct.year, dt_struct.mon, dt_struct.day)); //--- Reset ORB on new day if(current_date != last_orb_date) { last_orb_date = current_date; orb_high = 0; orb_low = 0; orb_ready = false; orb_building_high = 0; orb_building_low = 0; ResetAIFeatures(); Print("New day - ORB and AI features reset"); } //--- Update AI features and market analysis if(InpEnableAI && Bars(_Symbol, PERIOD_CURRENT) > InpFeaturePeriod) { UpdateAIFeatures(); AnalyzeMarketRegime(); UpdateVolatilityMetrics(); UpdateNewsSentiment(); } //--- Build ORB during specified period if(IsORBPeriod(current_time) && !orb_ready) { double high_val = InpExcludeWicks ? iClose(_Symbol, PERIOD_CURRENT, 1) : iHigh(_Symbol, PERIOD_CURRENT, 1); double low_val = InpExcludeWicks ? iClose(_Symbol, PERIOD_CURRENT, 1) : iLow(_Symbol, PERIOD_CURRENT, 1); if(orb_building_high == 0 || orb_building_low == 0) { orb_building_high = high_val; orb_building_low = low_val; Print("ORB building: High=", orb_building_high, ", Low=", orb_building_low); } else { orb_building_high = MathMax(orb_building_high, high_val); orb_building_low = MathMin(orb_building_low, low_val); } } //--- Finalize ORB if(ORBEnded(current_time) && !orb_ready && orb_building_high > 0) { orb_high = orb_building_high; orb_low = orb_building_low; orb_ready = true; double orb_range = orb_high - orb_low; Print("ORB finalized: High=", orb_high, ", Low=", orb_low, ", Range=", orb_range / _Point, " points"); //--- Update AI with ORB completion if(InpEnableAI) { CalculateAISignalConfidence(); } } //--- Update trailing stops if(PositionsTotal() > 0) { UpdateTrailingStops(); } //--- Look for entry signals if(GetPositionCount() == 0 && orb_ready && IsMarketOpen(current_time)) { CheckEntrySignals(); } } //+------------------------------------------------------------------+ //| Check if current time is ORB period | //+------------------------------------------------------------------+ bool IsORBPeriod(datetime time) { MqlDateTime dt; TimeToStruct(time, dt); int start_minutes = InpORBStartHour * 60 + InpORBStartMinute; int end_minutes = InpORBEndHour * 60 + InpORBEndMinute; int current_minutes = dt.hour * 60 + dt.min; return (current_minutes >= start_minutes && current_minutes < end_minutes); } //+------------------------------------------------------------------+ //| Check if ORB period has ended | //+------------------------------------------------------------------+ bool ORBEnded(datetime time) { MqlDateTime dt; TimeToStruct(time, dt); int end_minutes = InpORBEndHour * 60 + InpORBEndMinute; int current_minutes = dt.hour * 60 + dt.min; return (current_minutes == end_minutes); } //+------------------------------------------------------------------+ //| Check if market is open | //+------------------------------------------------------------------+ bool IsMarketOpen(datetime time) { MqlDateTime dt; TimeToStruct(time, dt); return (dt.hour >= InpORBStartHour && dt.hour <= InpMarketCloseHour); } //+------------------------------------------------------------------+ //| Check for entry signals | //+------------------------------------------------------------------+ void CheckEntrySignals() { double close = iClose(_Symbol, PERIOD_CURRENT, 0); double high = iHigh(_Symbol, PERIOD_CURRENT, 0); double low = iLow(_Symbol, PERIOD_CURRENT, 0); //--- Check for ORB breakout bool breakout_bull = high > orb_high; bool breakout_bear = low < orb_low; if(!breakout_bull && !breakout_bear) return; //--- Get current market conditions double atr_buffer[]; ArraySetAsSeries(atr_buffer, true); if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) <= 0) return; double atr_value = atr_buffer[0]; current_volatility = atr_value; //--- AI Signal Analysis bool ai_approval = true; if(InpEnableAI) { ai_approval = (ai_signal_confidence >= InpAIThreshold); Print("AI Signal Confidence: ", DoubleToString(ai_signal_confidence, 3), ", Market Regime: ", DoubleToString(current_market_regime, 2)); } //--- Traditional technical analysis double ema9_buffer[], ema21_buffer[], rsi_buffer[], macd_main[], macd_signal[]; ArraySetAsSeries(ema9_buffer, true); ArraySetAsSeries(ema21_buffer, true); ArraySetAsSeries(rsi_buffer, true); ArraySetAsSeries(macd_main, true); ArraySetAsSeries(macd_signal, true); if(CopyBuffer(ema9_handle, 0, 0, 1, ema9_buffer) <= 0 || CopyBuffer(ema21_handle, 0, 0, 1, ema21_buffer) <= 0 || CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer) <= 0 || CopyBuffer(macd_handle, 0, 0, 1, macd_main) <= 0 || CopyBuffer(macd_handle, 1, 0, 1, macd_signal) <= 0) return; double ema9_value = ema9_buffer[0]; double ema21_value = ema21_buffer[0]; double rsi_value = rsi_buffer[0]; double macd_value = macd_main[0]; double macd_signal_value = macd_signal[0]; //--- Technical filter scores int bull_score = 0; int bear_score = 0; //--- EMA trend if(ema9_value > ema21_value) bull_score++; else bear_score++; //--- RSI momentum if(rsi_value > 45 && rsi_value < 75) bull_score++; if(rsi_value < 55 && rsi_value > 25) bear_score++; //--- MACD direction if(macd_value > macd_signal_value) bull_score++; else bear_score++; bool tech_ok_bull = (bull_score >= 2); bool tech_ok_bear = (bear_score >= 2); //--- Calculate dynamic position size double position_volume = CalculateDynamicPositionSize(); //--- Execute BULLISH breakout if(breakout_bull && tech_ok_bull && ai_approval) { double entry_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); //--- Calculate dynamic SL/TP double sl, tp; CalculateDynamicSLTP(ORDER_TYPE_BUY, entry_price, atr_value, sl, tp); //--- Verify risk/reward ratio double risk_points = (entry_price - sl) / _Point; double reward_points = (tp - entry_price) / _Point; double rr = reward_points / risk_points; if(rr >= InpMinRR && risk_points > 0) { if(OrderSend(_Symbol, ORDER_TYPE_BUY, position_volume, entry_price, 10, sl, tp, InpMagicComment, magic_number)) { highest_since_entry = entry_price; Print("BUY EXECUTED - Entry: ", entry_price, ", SL: ", sl, " (-", DoubleToString(risk_points, 1), "p), TP: ", tp, " (+", DoubleToString(reward_points, 1), "p), R:R: ", DoubleToString(rr, 2), ", Vol: ", position_volume); Print("AI Confidence: ", DoubleToString(ai_signal_confidence, 3), ", Volatility: ", DoubleToString(current_volatility, 5)); } else { Print("BUY ORDER FAILED: ", GetLastError()); } } else { Print("BUY REJECTED - Poor R:R: ", DoubleToString(rr, 2), " (min: ", InpMinRR, "), Risk: ", DoubleToString(risk_points, 1), "p"); } } //--- Execute BEARISH breakout else if(breakout_bear && tech_ok_bear && ai_approval) { double entry_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); //--- Calculate dynamic SL/TP double sl, tp; CalculateDynamicSLTP(ORDER_TYPE_SELL, entry_price, atr_value, sl, tp); //--- Verify risk/reward ratio double risk_points = (sl - entry_price) / _Point; double reward_points = (entry_price - tp) / _Point; double rr = reward_points / risk_points; if(rr >= InpMinRR && risk_points > 0) { if(OrderSend(_Symbol, ORDER_TYPE_SELL, position_volume, entry_price, 10, sl, tp, InpMagicComment, magic_number)) { lowest_since_entry = entry_price; Print("SELL EXECUTED - Entry: ", entry_price, ", SL: ", sl, " (+", DoubleToString(risk_points, 1), "p), TP: ", tp, " (-", DoubleToString(reward_points, 1), "p), R:R: ", DoubleToString(rr, 2), ", Vol: ", position_volume); Print("AI Confidence: ", DoubleToString(ai_signal_confidence, 3), ", Volatility: ", DoubleToString(current_volatility, 5)); } else { Print("SELL ORDER FAILED: ", GetLastError()); } } else { Print("SELL REJECTED - Poor R:R: ", DoubleToString(rr, 2), " (min: ", InpMinRR, "), Risk: ", DoubleToString(risk_points, 1), "p"); } } else { if(!ai_approval) Print("TRADE REJECTED - AI Confidence too low: ", DoubleToString(ai_signal_confidence, 3), " < ", InpAIThreshold); if(!tech_ok_bull && !tech_ok_bear) Print("TRADE REJECTED - Technical filter failed. Bull: ", bull_score, "/3, Bear: ", bear_score, "/3"); } } //+------------------------------------------------------------------+ //| Update trailing stops | //+------------------------------------------------------------------+ void UpdateTrailingStops() { if(!InpUseTrailing) return; double atr_buffer[]; ArraySetAsSeries(atr_buffer, true); if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) <= 0) return; double atr_value = atr_buffer[0]; for(int i = 0; i < PositionsTotal(); i++) { if(!PositionSelectByTicket(PositionGetTicket(i))) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetString(POSITION_COMMENT) != InpMagicComment) continue; ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); double pos_entry = PositionGetDouble(POSITION_PRICE_OPEN); double pos_sl = PositionGetDouble(POSITION_SL); ulong pos_ticket = PositionGetInteger(POSITION_TICKET); if(pos_type == POSITION_TYPE_BUY) { double current_price = SymbolInfoDouble(_Symbol, SYMBOL_BID); highest_since_entry = MathMax(highest_since_entry, current_price); double profit_atr = (highest_since_entry - pos_entry) / atr_value; if(profit_atr >= InpTrailStart) { double new_sl = highest_since_entry - atr_value * InpTrailDistance; if(new_sl > pos_sl) { if(!PositionModify(pos_ticket, new_sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify BUY position: ", GetLastError()); } } } } else if(pos_type == POSITION_TYPE_SELL) { double current_price = SymbolInfoDouble(_Symbol, SYMBOL_ASK); lowest_since_entry = MathMin(lowest_since_entry, current_price); double profit_atr = (pos_entry - lowest_since_entry) / atr_value; if(profit_atr >= InpTrailStart) { double new_sl = lowest_since_entry + atr_value * InpTrailDistance; if(new_sl < pos_sl || pos_sl == 0) { if(!PositionModify(pos_ticket, new_sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify SELL position: ", GetLastError()); } } } } } } //+------------------------------------------------------------------+ //| Calculate Simple Moving Average | //+------------------------------------------------------------------+ double CalculateSMA(int period) { double sum = 0; for(int i = 0; i < period; i++) { sum += iClose(_Symbol, PERIOD_CURRENT, i); } return sum / period; } //+------------------------------------------------------------------+ //| Calculate Standard Deviation | //+------------------------------------------------------------------+ double CalculateStdDev(int period) { double mean = CalculateSMA(period); double sum_sq = 0; for(int i = 0; i < period; i++) { double diff = iClose(_Symbol, PERIOD_CURRENT, i) - mean; sum_sq += diff * diff; } return MathSqrt(sum_sq / period); } //============================= AI/ML METHODS ============================= //+------------------------------------------------------------------+ //| Initialize AI Features | //+------------------------------------------------------------------+ void InitializeAIFeatures() { ArrayResize(price_features, 0); ArrayResize(volume_features, 0); ArrayResize(volatility_features, 0); ArrayResize(recent_predictions, 0); ai_signal_confidence = 0.5; // neutral starting point current_market_regime = 0; last_news_sentiment = 0; } //+------------------------------------------------------------------+ //| Reset AI Features | //+------------------------------------------------------------------+ void ResetAIFeatures() { if(ArraySize(price_features) > InpFeaturePeriod) ArrayResize(price_features, InpFeaturePeriod); if(ArraySize(volume_features) > InpFeaturePeriod) ArrayResize(volume_features, InpFeaturePeriod); if(ArraySize(volatility_features) > InpFeaturePeriod) ArrayResize(volatility_features, InpFeaturePeriod); ai_signal_confidence = 0.5; } //+------------------------------------------------------------------+ //| Update AI Features | //+------------------------------------------------------------------+ void UpdateAIFeatures() { double close = iClose(_Symbol, PERIOD_CURRENT, 0); double volume = (double)iVolume(_Symbol, PERIOD_CURRENT, 0); double atr_buffer[]; ArraySetAsSeries(atr_buffer, true); if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) <= 0) return; double atr_value = atr_buffer[0]; //--- Price-based features double price_change = 0; if(Bars(_Symbol, PERIOD_CURRENT) > 1) { double prev_close = iClose(_Symbol, PERIOD_CURRENT, 1); if(prev_close != 0) price_change = (close - prev_close) / prev_close; } //--- Add to feature arrays int size = ArraySize(price_features); ArrayResize(price_features, size + 1); ArrayResize(volume_features, size + 1); ArrayResize(volatility_features, size + 1); price_features[size] = price_change; volume_features[size] = volume; volatility_features[size] = atr_value; //--- Maintain feature window size if(ArraySize(price_features) > InpFeaturePeriod) { ArrayRemove(price_features, 0, 1); ArrayRemove(volume_features, 0, 1); ArrayRemove(volatility_features, 0, 1); } //--- Calculate additional ML features CalculateAdvancedFeatures(); } //+------------------------------------------------------------------+ //| Calculate Advanced Features | //+------------------------------------------------------------------+ void CalculateAdvancedFeatures() { if(ArraySize(price_features) < 20) return; //--- Fractal dimension calculation double fractal_dim = CalculateFractalDimension(); //--- Hurst exponent for mean reversion/trending double hurst_exponent = CalculateHurstExponent(); //--- Volume-price trend correlation double vp_correlation = CalculateVolumePriceCorrelation(); //--- Store these for AI decision making Print("ML Features - Fractal: ", DoubleToString(fractal_dim, 3), ", Hurst: ", DoubleToString(hurst_exponent, 3), ", VP-Corr: ", DoubleToString(vp_correlation, 3)); } //+------------------------------------------------------------------+ //| Calculate Fractal Dimension | //+------------------------------------------------------------------+ double CalculateFractalDimension() { if(ArraySize(price_features) < 10) return 1.5; int start_idx = MathMax(0, ArraySize(price_features) - 20); int count = ArraySize(price_features) - start_idx; double max_val = price_features[start_idx]; double min_val = price_features[start_idx]; for(int i = start_idx; i < ArraySize(price_features); i++) { max_val = MathMax(max_val, price_features[i]); min_val = MathMin(min_val, price_features[i]); } double range = max_val - min_val; if(range == 0) return 1.5; //--- Simple approximation of fractal dimension double volatility = CalculateStdDev(20); double fractal_dim = 1.0 + (volatility / range) * 0.5; return MathMax(1.0, MathMin(2.0, fractal_dim)); } //+------------------------------------------------------------------+ //| Calculate Hurst Exponent | //+------------------------------------------------------------------+ double CalculateHurstExponent() { if(ArraySize(price_features) < 20) return 0.5; int start_idx = MathMax(0, ArraySize(price_features) - 20); int count = ArraySize(price_features) - start_idx; //--- Calculate mean double sum = 0; for(int i = start_idx; i < ArraySize(price_features); i++) sum += price_features[i]; double mean = sum / count; //--- Calculate variance double sum_sq = 0; for(int i = start_idx; i < ArraySize(price_features); i++) { double diff = price_features[i] - mean; sum_sq += diff * diff; } double variance = sum_sq / count; if(variance == 0) return 0.5; //--- R/S analysis approximation double cum_deviations[]; ArrayResize(cum_deviations, count); cum_deviations[0] = price_features[start_idx] - mean; for(int i = 1; i < count; i++) { cum_deviations[i] = cum_deviations[i-1] + (price_features[start_idx + i] - mean); } double max_dev = cum_deviations[0]; double min_dev = cum_deviations[0]; for(int i = 0; i < count; i++) { max_dev = MathMax(max_dev, cum_deviations[i]); min_dev = MathMin(min_dev, cum_deviations[i]); } double range = max_dev - min_dev; double standard_dev = MathSqrt(variance); if(standard_dev == 0) return 0.5; double rs = range / standard_dev; double hurst = MathLog(rs) / MathLog(count); return MathMax(0.1, MathMin(0.9, hurst)); } //+------------------------------------------------------------------+ //| Calculate Volume Price Correlation | //+------------------------------------------------------------------+ double CalculateVolumePriceCorrelation() { if(ArraySize(price_features) < 10 || ArraySize(volume_features) < 10) return 0; int start_idx = MathMax(0, ArraySize(price_features) - 10); int count = ArraySize(price_features) - start_idx; //--- Calculate means double price_sum = 0, volume_sum = 0; for(int i = start_idx; i < ArraySize(price_features); i++) { price_sum += price_features[i]; volume_sum += volume_features[i]; } double price_mean = price_sum / count; double volume_mean = volume_sum / count; //--- Calculate correlation double numerator = 0; double price_var = 0; double volume_var = 0; for(int i = start_idx; i < ArraySize(price_features); i++) { double price_diff = price_features[i] - price_mean; double volume_diff = volume_features[i] - volume_mean; numerator += price_diff * volume_diff; price_var += price_diff * price_diff; volume_var += volume_diff * volume_diff; } double denominator = MathSqrt(price_var * volume_var); return (denominator == 0) ? 0 : numerator / denominator; } //+------------------------------------------------------------------+ //| Analyze Market Regime | //+------------------------------------------------------------------+ void AnalyzeMarketRegime() { if(ArraySize(price_features) < InpMarketRegimeWindow) return; //--- Market regime classification using multiple indicators int start_idx = MathMax(0, ArraySize(price_features) - InpMarketRegimeWindow); //--- Trend strength double trend_strength = CalculateTrendStrength(start_idx); //--- Volatility regime double vol_regime = CalculateVolatilityRegime(start_idx); //--- Momentum regime double momentum_regime = CalculateMomentumRegime(); //--- Combine signals for overall market regime current_market_regime = (trend_strength + vol_regime + momentum_regime) / 3.0; //--- Clamp to [-1, 1] range current_market_regime = MathMax(-1.0, MathMin(1.0, current_market_regime)); } //+------------------------------------------------------------------+ //| Calculate Trend Strength | //+------------------------------------------------------------------+ double CalculateTrendStrength(int start_idx) { int count = ArraySize(price_features) - start_idx; if(count < 5) return 0; //--- Linear regression slope double sum_x = 0, sum_y = 0, sum_xy = 0, sum_x2 = 0; for(int i = 0; i < count; i++) { double x = i; double y = price_features[start_idx + i]; sum_x += x; sum_y += y; sum_xy += x * y; sum_x2 += x * x; } double slope = (count * sum_xy - sum_x * sum_y) / (count * sum_x2 - sum_x * sum_x); //--- Normalize slope to [-1, 1] range double avg_price = sum_y / count; double normalized_slope = slope / avg_price * 1000; // Scale for readability return MathMax(-1.0, MathMin(1.0, normalized_slope)); } //+------------------------------------------------------------------+ //| Calculate Volatility Regime | //+------------------------------------------------------------------+ double CalculateVolatilityRegime(int start_idx) { int count = ArraySize(volatility_features) - start_idx; if(count < 5) return 0; //--- Calculate average volatility double sum = 0; for(int i = start_idx; i < ArraySize(volatility_features); i++) sum += volatility_features[i]; double avg_vol = sum / count; //--- Calculate recent volatility (last 5) double recent_sum = 0; int recent_count = MathMin(5, count); for(int i = ArraySize(volatility_features) - recent_count; i < ArraySize(volatility_features); i++) recent_sum += volatility_features[i]; double recent_vol = recent_sum / recent_count; //--- High volatility = bearish regime, low volatility = bullish regime double vol_ratio = (avg_vol != 0) ? (avg_vol - recent_vol) / avg_vol : 0; return MathMax(-1.0, MathMin(1.0, vol_ratio)); } //+------------------------------------------------------------------+ //| Calculate Momentum Regime | //+------------------------------------------------------------------+ double CalculateMomentumRegime() { if(Bars(_Symbol, PERIOD_CURRENT) < 20) return 0; double rsi_buffer[], macd_hist[]; ArraySetAsSeries(rsi_buffer, true); ArraySetAsSeries(macd_hist, true); if(CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer) <= 0 || CopyBuffer(macd_handle, 2, 0, 10, macd_hist) <= 0) return 0; double rsi_value = rsi_buffer[0]; //--- RSI momentum (50 = neutral) double rsi_momentum = (rsi_value - 50) / 50; //--- MACD momentum double avg_macd_hist = 0; int macd_count = MathMin(10, ArraySize(macd_hist)); for(int i = 0; i < macd_count; i++) avg_macd_hist += macd_hist[i]; avg_macd_hist /= macd_count; double macd_momentum = (avg_macd_hist > 0) ? 0.5 : -0.5; return (rsi_momentum + macd_momentum) / 2.0; } //+------------------------------------------------------------------+ //| Update Volatility Metrics | //+------------------------------------------------------------------+ void UpdateVolatilityMetrics() { double atr_buffer[], stddev_buffer[]; ArraySetAsSeries(atr_buffer, true); ArraySetAsSeries(stddev_buffer, true); if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) <= 0 || CopyBuffer(stddev_handle, 0, 0, 1, stddev_buffer) <= 0) return; current_volatility = atr_buffer[0]; double stddev_value = stddev_buffer[0]; //--- Market stress indicator double close = iClose(_Symbol, PERIOD_CURRENT, 0); double price_vol = (close != 0) ? stddev_value / close : 0; double vol_vol = 0; if(ArraySize(volatility_features) > 10) { // Calculate standard deviation of volatility int start_idx = ArraySize(volatility_features) - 10; double sum = 0; for(int i = start_idx; i < ArraySize(volatility_features); i++) sum += volatility_features[i]; double mean_vol = sum / 10; double sum_sq = 0; for(int i = start_idx; i < ArraySize(volatility_features); i++) { double diff = volatility_features[i] - mean_vol; sum_sq += diff * diff; } vol_vol = MathSqrt(sum_sq / 10); } market_stress = (price_vol + vol_vol) * 100; // Scale to percentage //--- Adaptive risk multiplier based on market conditions if(market_stress > 2.0) // High stress adaptive_risk_multiplier = 1.5; else if(market_stress > 1.0) // Medium stress adaptive_risk_multiplier = 1.2; else // Low stress adaptive_risk_multiplier = 0.8; } //+------------------------------------------------------------------+ //| Calculate AI Signal Confidence | //+------------------------------------------------------------------+ void CalculateAISignalConfidence() { if(!InpEnableAI || ArraySize(price_features) < 20) { ai_signal_confidence = 0.5; return; } //--- Multi-factor confidence scoring double confidence_score = 0.5; // Start neutral //--- 1. Market regime confidence double regime_confidence = MathAbs(current_market_regime); confidence_score += regime_confidence * 0.3; //--- 2. Technical confluence double ema9_buffer[], ema21_buffer[], rsi_buffer[], macd_main[], macd_signal[]; ArraySetAsSeries(ema9_buffer, true); ArraySetAsSeries(ema21_buffer, true); ArraySetAsSeries(rsi_buffer, true); ArraySetAsSeries(macd_main, true); ArraySetAsSeries(macd_signal, true); if(CopyBuffer(ema9_handle, 0, 0, 1, ema9_buffer) > 0 && CopyBuffer(ema21_handle, 0, 0, 1, ema21_buffer) > 0 && CopyBuffer(rsi_handle, 0, 0, 1, rsi_buffer) > 0 && CopyBuffer(macd_handle, 0, 0, 1, macd_main) > 0 && CopyBuffer(macd_handle, 1, 0, 1, macd_signal) > 0) { double ema9_value = ema9_buffer[0]; double ema21_value = ema21_buffer[0]; double rsi_value = rsi_buffer[0]; double macd_value = macd_main[0]; double macd_signal_value = macd_signal[0]; int technical_alignment = 0; if((ema9_value > ema21_value && rsi_value > 50 && macd_value > macd_signal_value) || (ema9_value < ema21_value && rsi_value < 50 && macd_value < macd_signal_value)) technical_alignment = 1; confidence_score += technical_alignment * 0.2; } //--- 3. Volatility environment assessment double vol_confidence = (current_volatility > 0) ? MathMin(1.0, 1.0 / (1.0 + market_stress)) : 0.5; confidence_score += vol_confidence * 0.2; //--- 4. ORB quality assessment double orb_range = orb_high - orb_low; double orb_quality = (orb_range > 0) ? MathMin(1.0, orb_range / (current_volatility * 2)) : 0.5; confidence_score += orb_quality * 0.3; //--- Normalize to [0, 1] range ai_signal_confidence = MathMax(0.1, MathMin(1.0, confidence_score)); //--- Add news sentiment if available if(MathAbs(last_news_sentiment) > 0.1) { ai_signal_confidence = ai_signal_confidence * (1.0 - InpNewsSentimentWeight) + MathAbs(last_news_sentiment) * InpNewsSentimentWeight; } } //============================= DYNAMIC RISK MANAGEMENT ============================= //+------------------------------------------------------------------+ //| Calculate Dynamic Position Size | //+------------------------------------------------------------------+ double CalculateDynamicPositionSize() { if(!InpUseDynamicSizing) return InpVolume; //--- Account equity based sizing double account_equity = AccountInfoDouble(ACCOUNT_EQUITY); double risk_amount = account_equity * (InpRiskPerTrade / 100.0); //--- Calculate risk per pip based on current volatility double risk_pips = InpUseDynamicSL ? (InpBaseSL + current_volatility * InpVolatilityFactor / _Point) : InpBaseSL; if(risk_pips <= 0) return InpVolume; //--- Position size = Risk amount / (Risk pips * Pip value) double pip_value = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE); double position_size = risk_amount / (risk_pips * pip_value); //--- Apply adaptive risk multiplier position_size *= adaptive_risk_multiplier; //--- Convert to lots and apply limits double min_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); double max_lot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX); double lot_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP); position_size = MathMax(min_lot, position_size); position_size = MathMin(InpVolume * 5, position_size); // Max 5x base volume position_size = MathMin(max_lot, position_size); //--- Round to lot step position_size = MathFloor(position_size / lot_step) * lot_step; return position_size; } //+------------------------------------------------------------------+ //| Calculate Dynamic SL/TP | //+------------------------------------------------------------------+ void CalculateDynamicSLTP(ENUM_ORDER_TYPE order_type, double entry_price, double atr_value, double &sl, double &tp) { if(InpUseDynamicSL) { //--- Dynamic SL/TP based on volatility and market conditions double sl_distance = (InpBaseSL + atr_value * InpVolatilityFactor * adaptive_risk_multiplier) * _Point; double tp_distance = sl_distance * InpMinRR; // Maintain minimum R:R //--- Adjust for market regime if(MathAbs(current_market_regime) > 0.5) { //--- Strong trending market - wider stops sl_distance *= 1.2; tp_distance *= 1.1; } else { //--- Ranging market - tighter stops sl_distance *= 0.9; tp_distance *= 1.0; } if(order_type == ORDER_TYPE_BUY) { sl = entry_price - sl_distance; tp = entry_price + tp_distance; } else { sl = entry_price + sl_distance; tp = entry_price - tp_distance; } } else { //--- Fixed SL/TP double sl_pips = InpBaseSL * _Point; double tp_pips = InpBaseTP * _Point; if(order_type == ORDER_TYPE_BUY) { sl = entry_price - sl_pips; tp = entry_price + tp_pips; } else { sl = entry_price + sl_pips; tp = entry_price - tp_pips; } } } //============================= NEWS SENTIMENT INTEGRATION ============================= //+------------------------------------------------------------------+ //| Update News Sentiment | //+------------------------------------------------------------------+ void UpdateNewsSentiment() { //--- Update sentiment periodically (not every bar to avoid overprocessing) MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); if(dt.min % 15 == 0) // Every 15 minutes { GetNewsSentiment(); } } //+------------------------------------------------------------------+ //| Get News Sentiment | //+------------------------------------------------------------------+ void GetNewsSentiment() { //--- Simplified news sentiment analysis //--- In production, you would integrate with news APIs like: //--- - Alpha Vantage News API //--- - NewsAPI //--- - Financial Modeling Prep //--- - Custom sentiment analysis service //--- For now, return simulated sentiment based on market conditions MqlDateTime dt; TimeToStruct(TimeCurrent(), dt); double time_score = (dt.hour >= 8 && dt.hour <= 16) ? 0.1 : -0.1; // Market hours boost //--- Use volatility as proxy for market stress/sentiment double vol_sentiment = (current_volatility > 0) ? MathMin(0.5, MathMax(-0.5, -market_stress * 0.1)) : 0; double simulated_sentiment = time_score + vol_sentiment; last_news_sentiment = MathMax(-1.0, MathMin(1.0, simulated_sentiment)); if(MathAbs(last_news_sentiment) > 0.1) Print("News Sentiment: ", DoubleToString(last_news_sentiment, 3), " (simulated)"); } //============================= HELPER FUNCTIONS ============================= //+------------------------------------------------------------------+ //| Get position count for this EA | //+------------------------------------------------------------------+ int GetPositionCount() { int count = 0; for(int i = 0; i < PositionsTotal(); i++) { if(!PositionSelectByTicket(PositionGetTicket(i))) continue; if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue; if(PositionGetString(POSITION_COMMENT) != InpMagicComment) continue; count++; } return count; } //+------------------------------------------------------------------+ //| Order Send function with error handling | //+------------------------------------------------------------------+ bool OrderSend(string symbol, ENUM_ORDER_TYPE order_type, double volume, double price, int slippage, double sl, double tp, string comment, int magic) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_DEAL; request.symbol = symbol; request.volume = volume; request.type = order_type; request.price = price; request.deviation = slippage; request.sl = sl; request.tp = tp; request.comment = comment; request.magic = magic; if(!OrderSend(request, result)) { Print("OrderSend failed: ", GetLastError()); return false; } if(result.retcode != TRADE_RETCODE_DONE) { Print("Order failed with retcode: ", result.retcode); return false; } return true; } //+------------------------------------------------------------------+ //| Position Modify function with error handling | //+------------------------------------------------------------------+ bool PositionModify(ulong ticket, double sl, double tp) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_SLTP; request.position = ticket; request.sl = sl; request.tp = tp; if(!OrderSend(request, result)) { Print("PositionModify failed: ", GetLastError()); return false; } if(result.retcode != TRADE_RETCODE_DONE) { Print("Position modify failed with retcode: ", result.retcode); return false; } return true; }