Algo_bot_mt5/script/DAX_ORB_Ultimate_AI_MT5.mq5

1213 lines
43 KiB
MQL5
Raw Permalink Normal View History

2025-11-05 09:17:39 +00:00
//+------------------------------------------------------------------+
//| 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;
}