1785 linhas
54 KiB
Text
1785 linhas
54 KiB
Text
//+------------------------------------------------------------------+
| |||
//| AI_MLEngine_PatternDetector.mqh|
| |||
//| Machine Learning & Pattern Recognition |
| |||
//+------------------------------------------------------------------+
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Candlestick Pattern Detector |
| |||
//+------------------------------------------------------------------+
| |||
class CPatternDetector
| |||
{
| |||
private:
| |||
string m_symbol;
| |||
ENUM_TIMEFRAMES m_timeframe;
| |||
| |||
MqlRates m_rates[];
| |||
| |||
public:
| |||
CPatternDetector(string symbol, ENUM_TIMEFRAMES tf)
| |||
{
| |||
m_symbol = symbol;
| |||
m_timeframe = tf;
| |||
ArraySetAsSeries(m_rates, true);
| |||
}
| |||
| |||
bool UpdateData()
| |||
{
| |||
return CopyRates(m_symbol, m_timeframe, 0, 10, m_rates) > 0;
| |||
}
| |||
| |||
// Bullish Engulfing
| |||
bool IsBullishEngulfing()
| |||
{
| |||
if(ArraySize(m_rates) < 2) return false;
| |||
| |||
bool prevBearish = m_rates[1].close < m_rates[1].open;
| |||
bool currBullish = m_rates[0].close > m_rates[0].open;
| |||
bool engulfs = m_rates[0].close > m_rates[1].open &&
| |||
m_rates[0].open < m_rates[1].close;
| |||
| |||
return prevBearish && currBullish && engulfs;
| |||
}
| |||
| |||
// Bearish Engulfing
| |||
bool IsBearishEngulfing()
| |||
{
| |||
if(ArraySize(m_rates) < 2) return false;
| |||
| |||
bool prevBullish = m_rates[1].close > m_rates[1].open;
| |||
bool currBearish = m_rates[0].close < m_rates[0].open;
| |||
bool engulfs = m_rates[0].close < m_rates[1].open &&
| |||
m_rates[0].open > m_rates[1].close;
| |||
| |||
return prevBullish && currBearish && engulfs;
| |||
}
| |||
| |||
// Pin Bar (Hammer/Shooting Star)
| |||
int DetectPinBar()
| |||
{
| |||
if(ArraySize(m_rates) < 1) return 0;
| |||
| |||
double body = MathAbs(m_rates[0].close - m_rates[0].open);
| |||
double upperWick = m_rates[0].high - MathMax(m_rates[0].close, m_rates[0].open);
| |||
double lowerWick = MathMin(m_rates[0].close, m_rates[0].open) - m_rates[0].low;
| |||
double totalRange = m_rates[0].high - m_rates[0].low;
| |||
| |||
if(totalRange == 0) return 0;
| |||
| |||
// Bullish Pin (Hammer)
| |||
if(lowerWick > body * 2 && lowerWick > totalRange * 0.6 && upperWick < body)
| |||
return 1;
| |||
| |||
// Bearish Pin (Shooting Star)
| |||
if(upperWick > body * 2 && upperWick > totalRange * 0.6 && lowerWick < body)
| |||
return -1;
| |||
| |||
return 0;
| |||
}
| |||
| |||
// Doji
| |||
bool IsDoji()
| |||
{
| |||
if(ArraySize(m_rates) < 1) return false;
| |||
| |||
double body = MathAbs(m_rates[0].close - m_rates[0].open);
| |||
double totalRange = m_rates[0].high - m_rates[0].low;
| |||
| |||
return (body < totalRange * 0.1);
| |||
}
| |||
| |||
// Morning/Evening Star (3-candle pattern)
| |||
int DetectStar()
| |||
{
| |||
if(ArraySize(m_rates) < 3) return 0;
| |||
| |||
double body1 = MathAbs(m_rates[2].close - m_rates[2].open);
| |||
double body2 = MathAbs(m_rates[1].close - m_rates[1].open);
| |||
double body3 = MathAbs(m_rates[0].close - m_rates[0].open);
| |||
| |||
// Morning Star (Bullish)
| |||
if(m_rates[2].close < m_rates[2].open && // Bearish candle
| |||
body2 < body1 * 0.3 && // Small middle candle
| |||
m_rates[0].close > m_rates[0].open && // Bullish candle
| |||
m_rates[0].close > m_rates[2].open) // Closes above first candle open
| |||
return 1;
| |||
| |||
// Evening Star (Bearish)
| |||
if(m_rates[2].close > m_rates[2].open && // Bullish candle
| |||
body2 < body1 * 0.3 && // Small middle candle
| |||
m_rates[0].close < m_rates[0].open && // Bearish candle
| |||
m_rates[0].close < m_rates[2].open) // Closes below first candle open
| |||
return -1;
| |||
| |||
return 0;
| |||
}
| |||
| |||
// Get pattern score (combined)
| |||
double GetPatternScore()
| |||
{
| |||
UpdateData();
| |||
| |||
double score = 0;
| |||
| |||
if(IsBullishEngulfing()) score += 30;
| |||
if(IsBearishEngulfing()) score -= 30;
| |||
| |||
int pinBar = DetectPinBar();
| |||
score += pinBar * 25;
| |||
| |||
int star = DetectStar();
| |||
score += star * 35;
| |||
| |||
if(IsDoji()) score += 0; // Neutral - indecision
| |||
| |||
return score;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Support & Resistance Level Detector |
| |||
//+------------------------------------------------------------------+
| |||
class CLevelDetector
| |||
{
| |||
private:
| |||
string m_symbol;
| |||
ENUM_TIMEFRAMES m_timeframe;
| |||
| |||
double m_supportLevels[];
| |||
double m_resistanceLevels[];
| |||
| |||
int m_lookbackBars;
| |||
| |||
public:
| |||
CLevelDetector(string symbol, ENUM_TIMEFRAMES tf, int lookback = 100)
| |||
{
| |||
m_symbol = symbol;
| |||
m_timeframe = tf;
| |||
m_lookbackBars = lookback;
| |||
}
| |||
| |||
void DetectLevels()
| |||
{
| |||
ArrayResize(m_supportLevels, 0);
| |||
ArrayResize(m_resistanceLevels, 0);
| |||
| |||
MqlRates rates[];
| |||
ArraySetAsSeries(rates, true);
| |||
| |||
if(CopyRates(m_symbol, m_timeframe, 0, m_lookbackBars, rates) <= 0)
| |||
return;
| |||
| |||
// Detect swing highs and lows
| |||
for(int i = 3; i < m_lookbackBars - 3; i++)
| |||
{
| |||
// Swing High (Resistance)
| |||
if(rates[i].high > rates[i-1].high && rates[i].high > rates[i-2].high &&
| |||
rates[i].high > rates[i+1].high && rates[i].high > rates[i+2].high)
| |||
{
| |||
AddResistance(rates[i].high);
| |||
}
| |||
| |||
// Swing Low (Support)
| |||
if(rates[i].low < rates[i-1].low && rates[i].low < rates[i-2].low &&
| |||
rates[i].low < rates[i+1].low && rates[i].low < rates[i+2].low)
| |||
{
| |||
AddSupport(rates[i].low);
| |||
}
| |||
}
| |||
| |||
// Cluster nearby levels
| |||
ClusterLevels();
| |||
}
| |||
| |||
void AddSupport(double level)
| |||
{
| |||
int size = ArraySize(m_supportLevels);
| |||
ArrayResize(m_supportLevels, size + 1);
| |||
m_supportLevels[size] = level;
| |||
}
| |||
| |||
void AddResistance(double level)
| |||
{
| |||
int size = ArraySize(m_resistanceLevels);
| |||
ArrayResize(m_resistanceLevels, size + 1);
| |||
m_resistanceLevels[size] = level;
| |||
}
| |||
| |||
void ClusterLevels()
| |||
{
| |||
double threshold = SymbolInfoDouble(m_symbol, SYMBOL_POINT) * 50;
| |||
| |||
// Cluster support levels
| |||
for(int i = 0; i < ArraySize(m_supportLevels); i++)
| |||
{
| |||
for(int j = i + 1; j < ArraySize(m_supportLevels); j++)
| |||
{
| |||
if(MathAbs(m_supportLevels[i] - m_supportLevels[j]) < threshold)
| |||
{
| |||
m_supportLevels[i] = (m_supportLevels[i] + m_supportLevels[j]) / 2;
| |||
ArrayRemove(m_supportLevels, j, 1);
| |||
j--;
| |||
}
| |||
}
| |||
}
| |||
| |||
// Cluster resistance levels
| |||
for(int i = 0; i < ArraySize(m_resistanceLevels); i++)
| |||
{
| |||
for(int j = i + 1; j < ArraySize(m_resistanceLevels); j++)
| |||
{
| |||
if(MathAbs(m_resistanceLevels[i] - m_resistanceLevels[j]) < threshold)
| |||
{
| |||
m_resistanceLevels[i] = (m_resistanceLevels[i] + m_resistanceLevels[j]) / 2;
| |||
ArrayRemove(m_resistanceLevels, j, 1);
| |||
j--;
| |||
}
| |||
}
| |||
}
| |||
}
| |||
| |||
double GetNearestSupport(double price)
| |||
{
| |||
double nearest = 0;
| |||
double minDist = DBL_MAX;
| |||
| |||
for(int i = 0; i < ArraySize(m_supportLevels); i++)
| |||
{
| |||
if(m_supportLevels[i] < price)
| |||
{
| |||
double dist = price - m_supportLevels[i];
| |||
if(dist < minDist)
| |||
{
| |||
minDist = dist;
| |||
nearest = m_supportLevels[i];
| |||
}
| |||
}
| |||
}
| |||
| |||
return nearest;
| |||
}
| |||
| |||
double GetNearestResistance(double price)
| |||
{
| |||
double nearest = 0;
| |||
double minDist = DBL_MAX;
| |||
| |||
for(int i = 0; i < ArraySize(m_resistanceLevels); i++)
| |||
{
| |||
if(m_resistanceLevels[i] > price)
| |||
{
| |||
double dist = m_resistanceLevels[i] - price;
| |||
if(dist < minDist)
| |||
{
| |||
minDist = dist;
| |||
nearest = m_resistanceLevels[i];
| |||
}
| |||
}
| |||
}
| |||
| |||
return nearest;
| |||
}
| |||
| |||
bool IsNearSupport(double price, double threshold = 0.0005)
| |||
{
| |||
double support = GetNearestSupport(price);
| |||
if(support == 0) return false;
| |||
| |||
return (MathAbs(price - support) / price < threshold);
| |||
}
| |||
| |||
bool IsNearResistance(double price, double threshold = 0.0005)
| |||
{
| |||
double resistance = GetNearestResistance(price);
| |||
if(resistance == 0) return false;
| |||
| |||
return (MathAbs(price - resistance) / price < threshold);
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Simple Neural Network for Decision Making |
| |||
//+------------------------------------------------------------------+
| |||
class CNeuralNetwork
| |||
{
| |||
private:
| |||
// Simple 3-layer network: Input -> Hidden -> Output
| |||
int m_inputSize;
| |||
int m_hiddenSize;
| |||
int m_outputSize;
| |||
| |||
double m_weightsIH[][]; // Input to Hidden
| |||
double m_weightsHO[][]; // Hidden to Output
| |||
double m_biasH[];
| |||
double m_biasO[];
| |||
| |||
public:
| |||
CNeuralNetwork(int inputSize, int hiddenSize, int outputSize)
| |||
{
| |||
m_inputSize = inputSize;
| |||
m_hiddenSize = hiddenSize;
| |||
m_outputSize = outputSize;
| |||
| |||
InitializeWeights();
| |||
}
| |||
| |||
void InitializeWeights()
| |||
{
| |||
// Initialize with small random values
| |||
ArrayResize(m_weightsIH, m_inputSize);
| |||
for(int i = 0; i < m_inputSize; i++)
| |||
{
| |||
ArrayResize(m_weightsIH[i], m_hiddenSize);
| |||
for(int j = 0; j < m_hiddenSize; j++)
| |||
m_weightsIH[i][j] = (MathRand() / 32767.0 - 0.5) * 0.5;
| |||
}
| |||
| |||
ArrayResize(m_weightsHO, m_hiddenSize);
| |||
for(int i = 0; i < m_hiddenSize; i++)
| |||
{
| |||
ArrayResize(m_weightsHO[i], m_outputSize);
| |||
for(int j = 0; j < m_outputSize; j++)
| |||
m_weightsHO[i][j] = (MathRand() / 32767.0 - 0.5) * 0.5;
| |||
}
| |||
| |||
ArrayResize(m_biasH, m_hiddenSize);
| |||
ArrayResize(m_biasO, m_outputSize);
| |||
ArrayInitialize(m_biasH, 0);
| |||
ArrayInitialize(m_biasO, 0);
| |||
}
| |||
| |||
double Sigmoid(double x)
| |||
{
| |||
return 1.0 / (1.0 + MathExp(-x));
| |||
}
| |||
| |||
double ReLU(double x)
| |||
{
| |||
return MathMax(0, x);
| |||
}
| |||
| |||
void Forward(double &inputs[], double &outputs[])
| |||
{
| |||
ArrayResize(outputs, m_outputSize);
| |||
| |||
// Hidden layer
| |||
double hidden[];
| |||
ArrayResize(hidden, m_hiddenSize);
| |||
| |||
for(int j = 0; j < m_hiddenSize; j++)
| |||
{
| |||
double sum = m_biasH[j];
| |||
for(int i = 0; i < m_inputSize; i++)
| |||
sum += inputs[i] * m_weightsIH[i][j];
| |||
hidden[j] = ReLU(sum);
| |||
}
| |||
| |||
// Output layer
| |||
for(int k = 0; k < m_outputSize; k++)
| |||
{
| |||
double sum = m_biasO[k];
| |||
for(int j = 0; j < m_hiddenSize; j++)
| |||
sum += hidden[j] * m_weightsHO[j][k];
| |||
outputs[k] = Sigmoid(sum);
| |||
}
| |||
}
| |||
| |||
// Simplified training (would need proper backpropagation in production)
| |||
void Train(double &inputs[], double &targets[], double learningRate = 0.01)
| |||
{
| |||
// This is a placeholder - implement full backpropagation for production
| |||
// For now, just forward pass
| |||
double outputs[];
| |||
Forward(inputs, outputs);
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| AI Decision Engine - Combines All Intelligence |
| |||
//+------------------------------------------------------------------+
| |||
class CAIDecisionEngine
| |||
{
| |||
private:
| |||
CPatternDetector *m_patternH1;
| |||
CPatternDetector *m_patternH4;
| |||
CLevelDetector *m_levelH4;
| |||
CNeuralNetwork *m_neuralNet;
| |||
| |||
string m_symbol;
| |||
| |||
public:
| |||
CAIDecisionEngine(string symbol)
| |||
{
| |||
m_symbol = symbol;
| |||
m_patternH1 = new CPatternDetector(symbol, PERIOD_H1);
| |||
m_patternH4 = new CPatternDetector(symbol, PERIOD_H4);
| |||
m_levelH4 = new CLevelDetector(symbol, PERIOD_H4, 200);
| |||
| |||
// Neural network: 10 inputs -> 20 hidden -> 3 outputs (Buy/Neutral/Sell)
| |||
m_neuralNet = new CNeuralNetwork(10, 20, 3);
| |||
}
| |||
| |||
~CAIDecisionEngine()
| |||
{
| |||
delete m_patternH1;
| |||
delete m_patternH4;
| |||
delete m_levelH4;
| |||
delete m_neuralNet;
| |||
}
| |||
| |||
double MakeDecision(MarketContext &ctx)
| |||
{
| |||
// Update levels
| |||
m_levelH4.DetectLevels();
| |||
| |||
// Get pattern scores
| |||
double patternScoreH1 = m_patternH1.GetPatternScore();
| |||
double patternScoreH4 = m_patternH4.GetPatternScore();
| |||
| |||
// Check proximity to levels
| |||
ctx.nearSupport = m_levelH4.IsNearSupport(ctx.currentPrice);
| |||
ctx.nearResistance = m_levelH4.IsNearResistance(ctx.currentPrice);
| |||
| |||
// Prepare neural network inputs (normalized 0-1)
| |||
double inputs[10];
| |||
inputs[0] = (ctx.trendStrengthH1 + 100) / 200.0; // -100 to 100 -> 0 to 1
| |||
inputs[1] = (ctx.trendStrengthH4 + 100) / 200.0;
| |||
inputs[2] = (ctx.trendStrengthD1 + 100) / 200.0;
| |||
inputs[3] = ctx.volatilityRatio / 3.0; // Normalize assuming max 3x
| |||
inputs[4] = (patternScoreH1 + 100) / 200.0;
| |||
inputs[5] = (patternScoreH4 + 100) / 200.0;
| |||
inputs[6] = ctx.nearSupport ? 1.0 : 0.0;
| |||
inputs[7] = ctx.nearResistance ? 1.0 : 0.0;
| |||
inputs[8] = ctx.isNewsTime ? 1.0 : 0.0;
| |||
inputs[9] = (ctx.usdStrength + 100) / 200.0;
| |||
| |||
// Get neural network decision
| |||
double outputs[];
| |||
m_neuralNet.Forward(inputs, outputs);
| |||
| |||
// outputs[0] = Buy probability
| |||
// outputs[1] = Neutral probability
| |||
// outputs[2] = Sell probability
| |||
| |||
// Return decision score: -1 (Strong Sell) to +1 (Strong Buy)
| |||
double decision = outputs[0] - outputs[2];
| |||
| |||
return decision;
| |||
}
| |||
};
| |||
//+------------------------------------------------------------------+
| |||
//+------------------------------------------------------------------+
| |||
//| UltraFast_AI_XAUUSD_System.mq5 |
| |||
//| High-Frequency AI Trading Framework |
| |||
//| Sub-Second Multi-Factor Analysis |
| |||
//+------------------------------------------------------------------+
| |||
#property copyright "Ultra-Fast AI Gold Trading System"
| |||
#property version "2.00"
| |||
#property strict
| |||
| |||
#include <Trade\Trade.mqh>
| |||
#include <Trade\SymbolInfo.mqh>
| |||
#include <Trade\PositionInfo.mqh>
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| INPUT PARAMETERS - Fine-tune for HFT performance |
| |||
//+------------------------------------------------------------------+
| |||
input group "=== CORE SETTINGS ==="
| |||
input double RiskPercentPerTrade = 1.0; // Risk % per trade
| |||
input double MaxDailyLoss = 3.0; // Max daily loss %
| |||
input int MagicNumber = 123456; // EA Magic Number
| |||
input string TradeComment = "AI_HFT_Gold"; // Trade comment
| |||
| |||
input group "=== HIGH-FREQUENCY SETTINGS ==="
| |||
input bool EnableSubSecondAnalysis = true; // Enable tick-by-tick analysis
| |||
input int MinTicksBeforeTrade = 3; // Min ticks for signal confirmation
| |||
input int MaxSlippagePips = 5; // Max allowed slippage
| |||
input bool UseMarketExecution = true; // Use instant execution (faster)
| |||
input int MaxSpreadPips = 30; // Max spread to trade
| |||
| |||
input group "=== MULTI-FACTOR SCORING ==="
| |||
input double TrendWeight = 30.0; // Trend strength weight %
| |||
input double VolatilityWeight = 20.0; // Volatility regime weight %
| |||
input double IndicatorWeight = 25.0; // Indicator confluence weight %
| |||
input double PatternWeight = 25.0; // Pattern recognition weight %
| |||
input double MinConfluenceScore = 65.0; // Min score to trade (0-100)
| |||
| |||
input group "=== EXECUTION DISCIPLINE ==="
| |||
input bool InstantStopLoss = true; // Place SL immediately
| |||
input double StopLossATRMultiplier = 1.5; // SL = ATR * multiplier
| |||
input double TakeProfitATRMultiplier = 3.0; // TP = ATR * multiplier
| |||
input bool UseTrailingStop = true; // Enable trailing stop
| |||
input double TrailingStopATRMultiplier = 1.0;// Trailing stop distance
| |||
| |||
input group "=== ADVANCED FILTERS ==="
| |||
input bool FilterHighSpread = true; // Block trades on high spread
| |||
input bool FilterNewsEvents = true; // Block trades during news
| |||
input int NewsBufferMinutes = 15; // Minutes before/after news
| |||
input bool FilterSessionTimes = true; // Trade only in specific sessions
| |||
input bool AllowLondonSession = true; // Trade during London
| |||
input bool AllowNYSession = true; // Trade during NY
| |||
input bool AllowAsianSession = false; // Trade during Asian
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| ENUMERATIONS |
| |||
//+------------------------------------------------------------------+
| |||
enum ENUM_MARKET_REGIME
| |||
{
| |||
REGIME_STRONG_UPTREND,
| |||
REGIME_WEAK_UPTREND,
| |||
REGIME_STRONG_DOWNTREND,
| |||
REGIME_WEAK_DOWNTREND,
| |||
REGIME_RANGING,
| |||
REGIME_BREAKOUT_UP,
| |||
REGIME_BREAKOUT_DOWN,
| |||
REGIME_HIGH_VOLATILITY,
| |||
REGIME_UNKNOWN
| |||
};
| |||
| |||
enum ENUM_SIGNAL_STRENGTH
| |||
{
| |||
SIGNAL_VERY_STRONG_BUY = 100,
| |||
SIGNAL_STRONG_BUY = 75,
| |||
SIGNAL_WEAK_BUY = 50,
| |||
SIGNAL_NEUTRAL = 0,
| |||
SIGNAL_WEAK_SELL = -50,
| |||
SIGNAL_STRONG_SELL = -75,
| |||
SIGNAL_VERY_STRONG_SELL = -100
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Ultra-Fast Market Context - Optimized for Speed |
| |||
//+------------------------------------------------------------------+
| |||
struct UltraFastContext
| |||
{
| |||
// Timing (microsecond precision)
| |||
datetime lastTickTime;
| |||
ulong lastTickMicroseconds;
| |||
int tickCounter;
| |||
| |||
// Price action (immediate)
| |||
double bid, ask, spread;
| |||
double lastClose, currentClose;
| |||
double priceChangeRate; // Price velocity
| |||
| |||
// Market structure
| |||
ENUM_MARKET_REGIME regime;
| |||
double trendScore; // -100 to +100
| |||
double volatilityScore; // 0 to 100
| |||
| |||
// Multi-factor scores
| |||
double indicatorScore; // 0 to 100
| |||
double patternScore; // -100 to +100
| |||
double confluenceScore; // Final weighted score
| |||
| |||
// Execution context
| |||
bool canTrade;
| |||
bool isHighSpread;
| |||
bool isNewsTime;
| |||
bool isValidSession;
| |||
| |||
// Risk metrics
| |||
double atrValue;
| |||
double dynamicSL;
| |||
double dynamicTP;
| |||
| |||
void Reset()
| |||
{
| |||
tickCounter = 0;
| |||
regime = REGIME_UNKNOWN;
| |||
trendScore = 0;
| |||
volatilityScore = 0;
| |||
indicatorScore = 0;
| |||
patternScore = 0;
| |||
confluenceScore = 0;
| |||
canTrade = false;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Ultra-Fast Indicator Engine - Pre-calculated & Cached |
| |||
//+------------------------------------------------------------------+
| |||
class CUltraFastIndicators
| |||
{
| |||
private:
| |||
// Cached handles (initialized once)
| |||
int h_ema_fast, h_ema_medium, h_ema_slow;
| |||
int h_rsi, h_macd, h_atr, h_adx;
| |||
int h_bb, h_stoch;
| |||
| |||
// Cached buffers (updated only on bar change)
| |||
double cache_ema_fast[3], cache_ema_medium[3], cache_ema_slow[3];
| |||
double cache_rsi[3], cache_macd_main[3], cache_macd_signal[3];
| |||
double cache_atr[3], cache_adx[3];
| |||
double cache_bb_upper[3], cache_bb_lower[3], cache_bb_middle[3];
| |||
double cache_stoch_main[3], cache_stoch_signal[3];
| |||
| |||
// Real-time tick data (updated every tick)
| |||
double tick_price;
| |||
double tick_ema_fast; // Exponential smoothing on ticks
| |||
| |||
datetime lastBarTime;
| |||
string m_symbol;
| |||
ENUM_TIMEFRAMES m_tf;
| |||
| |||
// Exponential smoothing factor for tick-level EMA
| |||
double alpha_fast;
| |||
| |||
public:
| |||
CUltraFastIndicators(string symbol, ENUM_TIMEFRAMES tf = PERIOD_M1)
| |||
{
| |||
m_symbol = symbol;
| |||
m_tf = tf;
| |||
lastBarTime = 0;
| |||
tick_ema_fast = 0;
| |||
alpha_fast = 2.0 / (10.0 + 1.0); // 10-period EMA smoothing
| |||
| |||
InitializeIndicators();
| |||
}
| |||
| |||
~CUltraFastIndicators()
| |||
{
| |||
ReleaseIndicators();
| |||
}
| |||
| |||
bool InitializeIndicators()
| |||
{
| |||
// Initialize all indicators
| |||
h_ema_fast = iMA(m_symbol, m_tf, 9, 0, MODE_EMA, PRICE_CLOSE);
| |||
h_ema_medium = iMA(m_symbol, m_tf, 21, 0, MODE_EMA, PRICE_CLOSE);
| |||
h_ema_slow = iMA(m_symbol, m_tf, 50, 0, MODE_EMA, PRICE_CLOSE);
| |||
h_rsi = iRSI(m_symbol, m_tf, 14, PRICE_CLOSE);
| |||
h_macd = iMACD(m_symbol, m_tf, 12, 26, 9, PRICE_CLOSE);
| |||
h_atr = iATR(m_symbol, m_tf, 14);
| |||
h_adx = iADX(m_symbol, m_tf, 14);
| |||
h_bb = iBands(m_symbol, m_tf, 20, 0, 2.0, PRICE_CLOSE);
| |||
h_stoch = iStochastic(m_symbol, m_tf, 5, 3, 3, MODE_SMA, STO_LOWHIGH);
| |||
| |||
if(h_ema_fast == INVALID_HANDLE || h_rsi == INVALID_HANDLE)
| |||
{
| |||
Print("ERROR: Indicator initialization failed!");
| |||
return false;
| |||
}
| |||
| |||
// Pre-fill cache
| |||
Sleep(100); // Allow indicators to calculate
| |||
UpdateCache(true);
| |||
| |||
return true;
| |||
}
| |||
| |||
void ReleaseIndicators()
| |||
{
| |||
IndicatorRelease(h_ema_fast);
| |||
IndicatorRelease(h_ema_medium);
| |||
IndicatorRelease(h_ema_slow);
| |||
IndicatorRelease(h_rsi);
| |||
IndicatorRelease(h_macd);
| |||
IndicatorRelease(h_atr);
| |||
IndicatorRelease(h_adx);
| |||
IndicatorRelease(h_bb);
| |||
IndicatorRelease(h_stoch);
| |||
}
| |||
| |||
// Update cache only on new bar (efficient)
| |||
bool UpdateCache(bool force = false)
| |||
{
| |||
datetime currentBarTime = iTime(m_symbol, m_tf, 0);
| |||
| |||
if(!force && currentBarTime == lastBarTime)
| |||
return false; // No new bar, use cached values
| |||
| |||
lastBarTime = currentBarTime;
| |||
| |||
// Copy all buffers at once (optimized)
| |||
if(CopyBuffer(h_ema_fast, 0, 0, 3, cache_ema_fast) <= 0) return false;
| |||
if(CopyBuffer(h_ema_medium, 0, 0, 3, cache_ema_medium) <= 0) return false;
| |||
if(CopyBuffer(h_ema_slow, 0, 0, 3, cache_ema_slow) <= 0) return false;
| |||
if(CopyBuffer(h_rsi, 0, 0, 3, cache_rsi) <= 0) return false;
| |||
if(CopyBuffer(h_macd, 0, 0, 3, cache_macd_main) <= 0) return false;
| |||
if(CopyBuffer(h_macd, 1, 0, 3, cache_macd_signal) <= 0) return false;
| |||
if(CopyBuffer(h_atr, 0, 0, 3, cache_atr) <= 0) return false;
| |||
if(CopyBuffer(h_adx, 0, 0, 3, cache_adx) <= 0) return false;
| |||
if(CopyBuffer(h_bb, 1, 0, 3, cache_bb_upper) <= 0) return false;
| |||
if(CopyBuffer(h_bb, 2, 0, 3, cache_bb_lower) <= 0) return false;
| |||
if(CopyBuffer(h_bb, 0, 0, 3, cache_bb_middle) <= 0) return false;
| |||
if(CopyBuffer(h_stoch, 0, 0, 3, cache_stoch_main) <= 0) return false;
| |||
if(CopyBuffer(h_stoch, 1, 0, 3, cache_stoch_signal) <= 0) return false;
| |||
| |||
return true;
| |||
}
| |||
| |||
// Ultra-fast tick update (sub-millisecond)
| |||
void UpdateTick(double price)
| |||
{
| |||
tick_price = price;
| |||
| |||
// Real-time EMA calculation on ticks
| |||
if(tick_ema_fast == 0)
| |||
tick_ema_fast = price;
| |||
else
| |||
tick_ema_fast = alpha_fast * price + (1 - alpha_fast) * tick_ema_fast;
| |||
}
| |||
| |||
// Instant access to cached values (microsecond speed)
| |||
double GetEMAFast(int shift = 0) { return cache_ema_fast[shift]; }
| |||
double GetEMAMedium(int shift = 0) { return cache_ema_medium[shift]; }
| |||
double GetEMASlow(int shift = 0) { return cache_ema_slow[shift]; }
| |||
double GetRSI(int shift = 0) { return cache_rsi[shift]; }
| |||
double GetMACD(int shift = 0) { return cache_macd_main[shift]; }
| |||
double GetMACDSignal(int shift = 0) { return cache_macd_signal[shift]; }
| |||
double GetATR(int shift = 0) { return cache_atr[shift]; }
| |||
double GetADX(int shift = 0) { return cache_adx[shift]; }
| |||
double GetBBUpper(int shift = 0) { return cache_bb_upper[shift]; }
| |||
double GetBBLower(int shift = 0) { return cache_bb_lower[shift]; }
| |||
double GetBBMiddle(int shift = 0) { return cache_bb_middle[shift]; }
| |||
double GetStochMain(int shift = 0) { return cache_stoch_main[shift]; }
| |||
double GetStochSignal(int shift = 0) { return cache_stoch_signal[shift]; }
| |||
| |||
// Tick-level indicators
| |||
double GetTickEMA() { return tick_ema_fast; }
| |||
double GetTickPrice() { return tick_price; }
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Ultra-Fast Multi-Factor Analyzer |
| |||
//+------------------------------------------------------------------+
| |||
class CMultiFactorAnalyzer
| |||
{
| |||
private:
| |||
CUltraFastIndicators *indicators;
| |||
string m_symbol;
| |||
| |||
public:
| |||
CMultiFactorAnalyzer(string symbol)
| |||
{
| |||
m_symbol = symbol;
| |||
indicators = new CUltraFastIndicators(symbol, PERIOD_M1);
| |||
}
| |||
| |||
~CMultiFactorAnalyzer()
| |||
{
| |||
delete indicators;
| |||
}
| |||
| |||
// FACTOR 1: Trend Strength Analysis (-100 to +100)
| |||
double AnalyzeTrendStrength()
| |||
{
| |||
double score = 0;
| |||
double price = SymbolInfoDouble(m_symbol, SYMBOL_BID);
| |||
| |||
// EMA alignment (50 points max)
| |||
double ema_fast = indicators.GetEMAFast();
| |||
double ema_medium = indicators.GetEMAMedium();
| |||
double ema_slow = indicators.GetEMASlow();
| |||
| |||
if(ema_fast > ema_medium && ema_medium > ema_slow)
| |||
score += 50; // Perfect bullish alignment
| |||
else if(ema_fast < ema_medium && ema_medium < ema_slow)
| |||
score -= 50; // Perfect bearish alignment
| |||
else
| |||
score += 0; // Mixed signals
| |||
| |||
// Price position relative to EMAs (30 points max)
| |||
if(price > ema_fast && price > ema_medium && price > ema_slow)
| |||
score += 30;
| |||
else if(price < ema_fast && price < ema_medium && price < ema_slow)
| |||
score -= 30;
| |||
| |||
// ADX strength confirmation (20 points max)
| |||
double adx = indicators.GetADX();
| |||
if(adx > 25)
| |||
score *= 1.2; // Boost score in strong trend
| |||
else if(adx < 15)
| |||
score *= 0.5; // Reduce score in weak trend
| |||
| |||
return NormalizeDouble(MathMax(-100, MathMin(100, score)), 2);
| |||
}
| |||
| |||
// FACTOR 2: Volatility Regime Detection (0 to 100)
| |||
double AnalyzeVolatility()
| |||
{
| |||
double atr = indicators.GetATR();
| |||
double atr_prev = indicators.GetATR(1);
| |||
double atr_change = (atr - atr_prev) / atr_prev * 100;
| |||
| |||
// Calculate volatility percentile
| |||
double score = 50; // Base score
| |||
| |||
// ATR expansion/contraction
| |||
if(atr_change > 10)
| |||
score += 30; // Volatility expanding
| |||
else if(atr_change < -10)
| |||
score -= 20; // Volatility contracting
| |||
| |||
// Bollinger Band width
| |||
double bb_upper = indicators.GetBBUpper();
| |||
double bb_lower = indicators.GetBBLower();
| |||
double bb_width = (bb_upper - bb_lower) / indicators.GetBBMiddle() * 100;
| |||
| |||
if(bb_width > 2.0)
| |||
score += 20;
| |||
else if(bb_width < 1.0)
| |||
score -= 20;
| |||
| |||
return NormalizeDouble(MathMax(0, MathMin(100, score)), 2);
| |||
}
| |||
| |||
// FACTOR 3: Indicator Confluence Scoring (0 to 100)
| |||
double AnalyzeIndicatorConfluence()
| |||
{
| |||
double score = 0;
| |||
int bullish_signals = 0;
| |||
int bearish_signals = 0;
| |||
| |||
// RSI analysis
| |||
double rsi = indicators.GetRSI();
| |||
if(rsi > 50 && rsi < 70)
| |||
bullish_signals++;
| |||
else if(rsi < 50 && rsi > 30)
| |||
bearish_signals++;
| |||
| |||
// MACD analysis
| |||
double macd = indicators.GetMACD();
| |||
double macd_signal = indicators.GetMACDSignal();
| |||
if(macd > macd_signal && macd > 0)
| |||
bullish_signals++;
| |||
else if(macd < macd_signal && macd < 0)
| |||
bearish_signals++;
| |||
| |||
// Stochastic analysis
| |||
double stoch_main = indicators.GetStochMain();
| |||
double stoch_signal = indicators.GetStochSignal();
| |||
if(stoch_main > stoch_signal && stoch_main < 80)
| |||
bullish_signals++;
| |||
else if(stoch_main < stoch_signal && stoch_main > 20)
| |||
bearish_signals++;
| |||
| |||
// Bollinger Bands position
| |||
double price = SymbolInfoDouble(m_symbol, SYMBOL_BID);
| |||
double bb_middle = indicators.GetBBMiddle();
| |||
if(price > bb_middle)
| |||
bullish_signals++;
| |||
else if(price < bb_middle)
| |||
bearish_signals++;
| |||
| |||
// Calculate confluence
| |||
int total_signals = bullish_signals + bearish_signals;
| |||
if(total_signals > 0)
| |||
{
| |||
double confluence_ratio = (double)MathMax(bullish_signals, bearish_signals) / total_signals;
| |||
score = confluence_ratio * 100;
| |||
}
| |||
| |||
return NormalizeDouble(score, 2);
| |||
}
| |||
| |||
// FACTOR 4: Pattern Recognition (-100 to +100)
| |||
double AnalyzePatterns()
| |||
{
| |||
double score = 0;
| |||
MqlRates rates[];
| |||
ArraySetAsSeries(rates, true);
| |||
| |||
if(CopyRates(m_symbol, PERIOD_M1, 0, 5, rates) < 5)
| |||
return 0;
| |||
| |||
// Bullish Engulfing
| |||
if(IsBullishEngulfing(rates))
| |||
score += 40;
| |||
| |||
// Bearish Engulfing
| |||
if(IsBearishEngulfing(rates))
| |||
score -= 40;
| |||
| |||
// Pin Bar detection
| |||
int pinBar = DetectPinBar(rates);
| |||
score += pinBar * 30;
| |||
| |||
// Higher High / Lower Low patterns
| |||
if(rates[0].high > rates[1].high && rates[1].high > rates[2].high)
| |||
score += 20; // Bullish momentum
| |||
else if(rates[0].low < rates[1].low && rates[1].low < rates[2].low)
| |||
score -= 20; // Bearish momentum
| |||
| |||
return NormalizeDouble(MathMax(-100, MathMin(100, score)), 2);
| |||
}
| |||
| |||
bool IsBullishEngulfing(MqlRates &rates[])
| |||
{
| |||
return (rates[1].close < rates[1].open &&
| |||
rates[0].close > rates[0].open &&
| |||
rates[0].close > rates[1].open &&
| |||
rates[0].open < rates[1].close);
| |||
}
| |||
| |||
bool IsBearishEngulfing(MqlRates &rates[])
| |||
{
| |||
return (rates[1].close > rates[1].open &&
| |||
rates[0].close < rates[0].open &&
| |||
rates[0].close < rates[1].open &&
| |||
rates[0].open > rates[1].close);
| |||
}
| |||
| |||
int DetectPinBar(MqlRates &rates[])
| |||
{
| |||
double body = MathAbs(rates[0].close - rates[0].open);
| |||
double upperWick = rates[0].high - MathMax(rates[0].close, rates[0].open);
| |||
double lowerWick = MathMin(rates[0].close, rates[0].open) - rates[0].low;
| |||
double range = rates[0].high - rates[0].low;
| |||
| |||
if(range == 0) return 0;
| |||
| |||
if(lowerWick > body * 2 && lowerWick > range * 0.6)
| |||
return 1; // Bullish pin
| |||
if(upperWick > body * 2 && upperWick > range * 0.6)
| |||
return -1; // Bearish pin
| |||
| |||
return 0;
| |||
}
| |||
| |||
// Update indicators (call on new bar only)
| |||
void UpdateIndicators()
| |||
{
| |||
indicators.UpdateCache();
| |||
}
| |||
| |||
// Update tick data (call every tick)
| |||
void UpdateTick(double price)
| |||
{
| |||
indicators.UpdateTick(price);
| |||
}
| |||
| |||
double GetATR() { return indicators.GetATR(); }
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Lightning-Fast Execution Engine |
| |||
//+------------------------------------------------------------------+
| |||
class CLightningExecutor
| |||
{
| |||
private:
| |||
CTrade trade;
| |||
CSymbolInfo symbolInfo;
| |||
CPositionInfo positionInfo;
| |||
| |||
string m_symbol;
| |||
int m_magic;
| |||
| |||
public:
| |||
CLightningExecutor(string symbol, int magic)
| |||
{
| |||
m_symbol = symbol;
| |||
m_magic = magic;
| |||
| |||
trade.SetExpertMagicNumber(m_magic);
| |||
trade.SetDeviationInPoints(MaxSlippagePips * 10);
| |||
trade.SetTypeFilling(ORDER_FILLING_IOC); // Immediate or Cancel
| |||
trade.SetAsyncMode(false); // Synchronous for reliability
| |||
| |||
symbolInfo.Name(m_symbol);
| |||
}
| |||
| |||
// Execute BUY with instant SL/TP
| |||
bool ExecuteBuy(double lots, double sl, double tp, string comment)
| |||
{
| |||
symbolInfo.Refresh();
| |||
double ask = symbolInfo.Ask();
| |||
| |||
if(!trade.Buy(lots, m_symbol, ask, sl, tp, comment))
| |||
{
| |||
Print("BUY FAILED: ", trade.ResultRetcodeDescription());
| |||
return false;
| |||
}
| |||
| |||
Print("BUY EXECUTED: ", lots, " lots @ ", ask, " | SL:", sl, " TP:", tp);
| |||
return true;
| |||
}
| |||
| |||
// Execute SELL with instant SL/TP
| |||
bool ExecuteSell(double lots, double sl, double tp, string comment)
| |||
{
| |||
symbolInfo.Refresh();
| |||
double bid = symbolInfo.Bid();
| |||
| |||
if(!trade.Sell(lots, m_symbol, bid, sl, tp, comment))
| |||
{
| |||
Print("SELL FAILED: ", trade.ResultRetcodeDescription());
| |||
return false;
| |||
}
| |||
| |||
Print("SELL EXECUTED: ", lots, " lots @ ", bid, " | SL:", sl, " TP:", tp);
| |||
return true;
| |||
}
| |||
| |||
// Trailing stop implementation
| |||
void ManageTrailingStop(double atr)
| |||
{
| |||
if(!UseTrailingStop) return;
| |||
| |||
for(int i = PositionsTotal() - 1; i >= 0; i--)
| |||
{
| |||
if(!positionInfo.SelectByIndex(i)) continue;
| |||
if(positionInfo.Symbol() != m_symbol || positionInfo.Magic() != m_magic) continue;
| |||
| |||
double trailDistance = atr * TrailingStopATRMultiplier;
| |||
double currentPrice = positionInfo.Type() == POSITION_TYPE_BUY ?
| |||
symbolInfo.Bid() : symbolInfo.Ask();
| |||
double currentSL = positionInfo.StopLoss();
| |||
| |||
if(positionInfo.Type() == POSITION_TYPE_BUY)
| |||
{
| |||
double newSL = currentPrice - trailDistance;
| |||
if(newSL > currentSL && newSL < currentPrice)
| |||
trade.PositionModify(positionInfo.Ticket(), newSL, positionInfo.TakeProfit());
| |||
}
| |||
else
| |||
{
| |||
double newSL = currentPrice + trailDistance;
| |||
if(newSL < currentSL && newSL > currentPrice)
| |||
trade.PositionModify(positionInfo.Ticket(), newSL, positionInfo.TakeProfit());
| |||
}
| |||
}
| |||
}
| |||
| |||
bool HasOpenPosition()
| |||
{
| |||
for(int i = 0; i < PositionsTotal(); i++)
| |||
{
| |||
if(positionInfo.SelectByIndex(i))
| |||
{
| |||
if(positionInfo.Symbol() == m_symbol && positionInfo.Magic() == m_magic)
| |||
return true;
| |||
}
| |||
}
| |||
return false;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Main Ultra-Fast Trading Bot |
| |||
//+------------------------------------------------------------------+
| |||
class CUltraFastTradingBot
| |||
{
| |||
private:
| |||
CMultiFactorAnalyzer *analyzer;
| |||
CLightningExecutor *executor;
| |||
| |||
UltraFastContext ctx;
| |||
datetime lastBarTime;
| |||
| |||
string m_symbol;
| |||
| |||
public:
| |||
CUltraFastTradingBot()
| |||
{
| |||
m_symbol = _Symbol;
| |||
analyzer = new CMultiFactorAnalyzer(m_symbol);
| |||
executor = new CLightningExecutor(m_symbol, MagicNumber);
| |||
lastBarTime = 0;
| |||
}
| |||
| |||
~CUltraFastTradingBot()
| |||
{
| |||
delete analyzer;
| |||
delete executor;
| |||
}
| |||
| |||
void OnTick()
| |||
{
| |||
// Update context
| |||
ctx.Reset();
| |||
ctx.bid = SymbolInfoDouble(m_symbol, SYMBOL_BID);
| |||
ctx.ask = SymbolInfoDouble(m_symbol, SYMBOL_ASK);
| |||
ctx.spread = (ctx.ask - ctx.bid) / SymbolInfoDouble(m_symbol, SYMBOL_POINT);
| |||
| |||
// Check if new bar
| |||
datetime currentBarTime = iTime(m_symbol, PERIOD_M1, 0);
| |||
if(currentBarTime != lastBarTime)
| |||
{
| |||
lastBarTime = currentBarTime;
| |||
analyzer.UpdateIndicators();
| |||
}
| |||
| |||
// Sub-second tick analysis
| |||
if(EnableSubSecondAnalysis)
| |||
{
| |||
analyzer.UpdateTick(ctx.bid);
| |||
ctx.tickCounter++;
| |||
}
| |||
| |||
// Pre-flight checks
| |||
if(!PerformPreflightChecks())
| |||
return;
| |||
| |||
// Multi-factor analysis
| |||
PerformMultiFactorAnalysis();
| |||
| |||
// Generate and execute signal
| |||
if(ctx.confluenceScore >= MinConfluenceScore && !executor.HasOpenPosition())
| |||
{
| |||
ExecuteSignal();
| |||
}
| |||
| |||
// Manage existing positions
| |||
executor.ManageTrailingStop(ctx.atrValue);
| |||
}
| |||
| |||
bool PerformPreflightChecks()
| |||
{
| |||
// Spread filter
| |||
if(FilterHighSpread && ctx.spread > MaxSpreadPips)
| |||
{
| |||
ctx.canTrade = false;
| |||
return false;
| |||
}
| |||
| |||
// Session filter
| |||
if(FilterSessionTimes && !IsValidSession())
| |||
{
| |||
ctx.canTrade = false;
| |||
return false;
| |||
}
| |||
| |||
// Tick confirmation
| |||
if(EnableSubSecondAnalysis && ctx.tickCounter < MinTicksBeforeTrade)
| |||
{
| |||
ctx.canTrade = false;
| |||
return false;
| |||
}
| |||
| |||
ctx.canTrade = true;
| |||
return true;
| |||
}
| |||
| |||
void PerformMultiFactorAnalysis()
| |||
{
| |||
// Factor 1: Trend
| |||
ctx.trendScore = analyzer.AnalyzeTrendStrength();
| |||
| |||
// Factor 2: Volatility
| |||
ctx.volatilityScore = analyzer.AnalyzeVolatility();
| |||
| |||
// Factor 3: Indicators
| |||
ctx.indicatorScore = analyzer.AnalyzeIndicatorConfluence();
| |||
| |||
// Factor 4: Patterns
| |||
ctx.patternScore = analyzer.AnalyzePatterns();
| |||
| |||
// Get ATR
| |||
ctx.atrValue = analyzer.GetATR();
| |||
| |||
// Calculate weighted confluence score
| |||
double trendComponent = (ctx.trendScore + 100) / 2.0 * TrendWeight / 100.0;
| |||
double volatilityComponent = ctx.volatilityScore * VolatilityWeight / 100.0;
| |||
double indicatorComponent = ctx.indicatorScore * IndicatorWeight / 100.0;
| |||
double patternComponent = (ctx.patternScore + 100) / 2.0 * PatternWeight / 100.0;
| |||
| |||
ctx.confluenceScore = trendComponent + volatilityComponent +
| |||
indicatorComponent + patternComponent;
| |||
| |||
// Determine direction
| |||
double directionScore = (ctx.trendScore + ctx.patternScore) / 2.0;
| |||
| |||
if(directionScore > 30)
| |||
ctx.regime = REGIME_STRONG_UPTREND;
| |||
else if(directionScore < -30)
| |||
ctx.regime = REGIME_STRONG_DOWNTREND;
| |||
else
| |||
ctx.regime = REGIME_RANGING;
| |||
}
| |||
| |||
void ExecuteSignal()
| |||
{
| |||
double lots = CalculatePositionSize();
| |||
| |||
// Calculate SL/TP
| |||
if(ctx.regime == REGIME_STRONG_UPTREND)
| |||
{
| |||
double sl = ctx.bid - (ctx.atrValue * StopLossATRMultiplier);
| |||
double tp = ctx.bid + (ctx.atrValue * TakeProfitATRMultiplier);
| |||
executor.ExecuteBuy(lots, sl, tp, TradeComment);
| |||
}
| |||
else if(ctx.regime == REGIME_STRONG_DOWNTREND)
| |||
{
| |||
double sl = ctx.ask + (ctx.atrValue * StopLossATRMultiplier);
| |||
double tp = ctx.ask - (ctx.atrValue * TakeProfitATRMultiplier);
| |||
executor.ExecuteSell(lots, sl, tp, TradeComment);
| |||
}
| |||
}
| |||
| |||
double CalculatePositionSize()
| |||
{
| |||
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
| |||
double riskAmount = balance * RiskPercentPerTrade / 100.0;
| |||
| |||
double slDistance = ctx.atrValue * StopLossATRMultiplier;
| |||
double tickValue = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_VALUE);
| |||
double tickSize = SymbolInfoDouble(m_symbol, SYMBOL_TRADE_TICK_SIZE);
| |||
double point = SymbolInfoDouble(m_symbol, SYMBOL_POINT);
| |||
| |||
double slValue = slDistance / tickSize * tickValue;
| |||
double lots = riskAmount / slValue;
| |||
| |||
// Normalize lot size
| |||
double minLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MIN);
| |||
double maxLot = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_MAX);
| |||
double lotStep = SymbolInfoDouble(m_symbol, SYMBOL_VOLUME_STEP);
| |||
| |||
lots = MathFloor(lots / lotStep) * lotStep;
| |||
lots = MathMax(minLot, MathMin(maxLot, lots));
| |||
| |||
return lots;
| |||
}
| |||
| |||
bool IsValidSession()
| |||
{
| |||
MqlDateTime dt;
| |||
TimeToStruct(TimeCurrent(), dt);
| |||
int hour = dt.hour;
| |||
| |||
// London: 08:00-17:00 GMT
| |||
if(AllowLondonSession && hour >= 8 && hour < 17) return true;
| |||
| |||
// NY: 13:00-22:00 GMT
| |||
if(AllowNYSession && hour >= 13 && hour < 22) return true;
| |||
| |||
// Asian: 00:00-09:00 GMT
| |||
if(AllowAsianSession && hour >= 0 && hour < 9) return true;
| |||
| |||
return false;
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Expert initialization function |
| |||
//+------------------------------------------------------------------+
| |||
CUltraFastTradingBot *bot;
| |||
| |||
int OnInit()
| |||
{
| |||
Print("========================================");
| |||
Print(" ULTRA-FAST AI GOLD TRADING SYSTEM");
| |||
Print(" Sub-Second Multi-Factor Analysis");
| |||
Print("========================================");
| |||
Print("Confluence Threshold: ", MinConfluenceScore, "%");
| |||
Print("Trend Weight: ", TrendWeight, "%");
| |||
Print("Volatility Weight: ", VolatilityWeight, "%");
| |||
Print("Indicator Weight: ", IndicatorWeight, "%");
| |||
Print("Pattern Weight: ", PatternWeight, "%");
| |||
Print("========================================");
| |||
| |||
bot = new CUltraFastTradingBot();
| |||
| |||
if(bot == NULL)
| |||
{
| |||
Print("ERROR: Failed to initialize bot");
| |||
return INIT_FAILED;
| |||
}
| |||
| |||
Print("Bot initialized successfully!");
| |||
Print("Waiting for trading signals...");
| |||
| |||
return INIT_SUCCEEDED;
| |||
}
| |||
| |||
void OnDeinit(const int reason)
| |||
{
| |||
Print("========================================");
| |||
Print("EA Stopped. Reason: ", reason);
| |||
Print("========================================");
| |||
delete bot;
| |||
}
| |||
| |||
void OnTick()
| |||
{
| |||
bot.OnTick();
| |||
}
| |||
//+------------------------------------------------------------------+
| |||
//+------------------------------------------------------------------+
| |||
//| Dashboard_RiskManagement.mqh |
| |||
//| Real-Time Performance & Risk Analytics |
| |||
//+------------------------------------------------------------------+
| |||
| |||
#include <ChartObjects\ChartObjectsTxtControls.mqh>
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Performance Metrics Tracker |
| |||
//+------------------------------------------------------------------+
| |||
class CPerformanceTracker
| |||
{
| |||
private:
| |||
struct TradeRecord
| |||
{
| |||
datetime openTime;
| |||
datetime closeTime;
| |||
double openPrice;
| |||
double closePrice;
| |||
double profit;
| |||
double lots;
| |||
int type; // 0=Buy, 1=Sell
| |||
bool isWin;
| |||
};
| |||
| |||
TradeRecord history[];
| |||
int totalTrades;
| |||
int winningTrades;
| |||
int losingTrades;
| |||
| |||
double totalProfit;
| |||
double totalLoss;
| |||
double largestWin;
| |||
double largestLoss;
| |||
double currentDrawdown;
| |||
double maxDrawdown;
| |||
| |||
double initialBalance;
| |||
double currentBalance;
| |||
| |||
// Daily metrics
| |||
datetime currentDay;
| |||
double dailyProfit;
| |||
int dailyTrades;
| |||
| |||
public:
| |||
CPerformanceTracker()
| |||
{
| |||
Reset();
| |||
}
| |||
| |||
void Reset()
| |||
{
| |||
totalTrades = 0;
| |||
winningTrades = 0;
| |||
losingTrades = 0;
| |||
totalProfit = 0;
| |||
totalLoss = 0;
| |||
largestWin = 0;
| |||
largestLoss = 0;
| |||
currentDrawdown = 0;
| |||
maxDrawdown = 0;
| |||
initialBalance = AccountInfoDouble(ACCOUNT_BALANCE);
| |||
currentBalance = initialBalance;
| |||
dailyProfit = 0;
| |||
dailyTrades = 0;
| |||
currentDay = 0;
| |||
}
| |||
| |||
void RecordTrade(double openPrice, double closePrice, double profit, double lots, int type)
| |||
{
| |||
totalTrades++;
| |||
| |||
// Check if new day
| |||
datetime now = TimeCurrent();
| |||
MqlDateTime dt;
| |||
TimeToStruct(now, dt);
| |||
datetime today = StringToTime(IntegerToString(dt.year) + "." +
| |||
IntegerToString(dt.mon) + "." +
| |||
IntegerToString(dt.day));
| |||
| |||
if(today != currentDay)
| |||
{
| |||
currentDay = today;
| |||
dailyProfit = 0;
| |||
dailyTrades = 0;
| |||
}
| |||
| |||
dailyTrades++;
| |||
dailyProfit += profit;
| |||
| |||
// Record win/loss
| |||
if(profit > 0)
| |||
{
| |||
winningTrades++;
| |||
totalProfit += profit;
| |||
if(profit > largestWin) largestWin = profit;
| |||
}
| |||
else if(profit < 0)
| |||
{
| |||
losingTrades++;
| |||
totalLoss += MathAbs(profit);
| |||
if(MathAbs(profit) > largestLoss) largestLoss = MathAbs(profit);
| |||
}
| |||
| |||
// Update balance
| |||
currentBalance += profit;
| |||
| |||
// Calculate drawdown
| |||
if(currentBalance < initialBalance)
| |||
{
| |||
currentDrawdown = (initialBalance - currentBalance) / initialBalance * 100;
| |||
if(currentDrawdown > maxDrawdown)
| |||
maxDrawdown = currentDrawdown;
| |||
}
| |||
else
| |||
{
| |||
currentDrawdown = 0;
| |||
initialBalance = currentBalance; // New high watermark
| |||
}
| |||
}
| |||
| |||
double GetWinRate()
| |||
{
| |||
if(totalTrades == 0) return 0;
| |||
return (double)winningTrades / totalTrades * 100;
| |||
}
| |||
| |||
double GetProfitFactor()
| |||
{
| |||
if(totalLoss == 0) return totalProfit > 0 ? 999 : 0;
| |||
return totalProfit / totalLoss;
| |||
}
| |||
| |||
double GetAverageWin()
| |||
{
| |||
if(winningTrades == 0) return 0;
| |||
return totalProfit / winningTrades;
| |||
}
| |||
| |||
double GetAverageLoss()
| |||
{
| |||
if(losingTrades == 0) return 0;
| |||
return totalLoss / losingTrades;
| |||
}
| |||
| |||
double GetExpectancy()
| |||
{
| |||
if(totalTrades == 0) return 0;
| |||
return (totalProfit - totalLoss) / totalTrades;
| |||
}
| |||
| |||
double GetROI()
| |||
{
| |||
double startBalance = AccountInfoDouble(ACCOUNT_BALANCE) - (currentBalance - initialBalance);
| |||
if(startBalance == 0) return 0;
| |||
return (currentBalance - startBalance) / startBalance * 100;
| |||
}
| |||
| |||
// Getters
| |||
int GetTotalTrades() { return totalTrades; }
| |||
int GetWinningTrades() { return winningTrades; }
| |||
int GetLosingTrades() { return losingTrades; }
| |||
double GetTotalProfit() { return totalProfit; }
| |||
double GetTotalLoss() { return totalLoss; }
| |||
double GetLargestWin() { return largestWin; }
| |||
double GetLargestLoss() { return largestLoss; }
| |||
double GetMaxDrawdown() { return maxDrawdown; }
| |||
double GetCurrentDrawdown() { return currentDrawdown; }
| |||
double GetDailyProfit() { return dailyProfit; }
| |||
int GetDailyTrades() { return dailyTrades; }
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Advanced Risk Manager with Real-Time Monitoring |
| |||
//+------------------------------------------------------------------+
| |||
class CAdvancedRiskManager
| |||
{
| |||
private:
| |||
CPerformanceTracker *tracker;
| |||
| |||
// Risk limits
| |||
double maxDailyLossPercent;
| |||
double maxDrawdownPercent;
| |||
double maxPositionSize;
| |||
| |||
// Dynamic risk adjustment
| |||
bool useAdaptiveRisk;
| |||
double baseRiskPercent;
| |||
double currentRiskPercent;
| |||
| |||
// Circuit breaker
| |||
bool circuitBreakerActive;
| |||
datetime circuitBreakerUntil;
| |||
| |||
// Correlation monitor
| |||
double correlationThreshold;
| |||
| |||
public:
| |||
CAdvancedRiskManager(double dailyLoss, double maxDD, double baseRisk)
| |||
{
| |||
tracker = new CPerformanceTracker();
| |||
maxDailyLossPercent = dailyLoss;
| |||
maxDrawdownPercent = maxDD;
| |||
baseRiskPercent = baseRisk;
| |||
currentRiskPercent = baseRisk;
| |||
useAdaptiveRisk = true;
| |||
circuitBreakerActive = false;
| |||
}
| |||
| |||
~CAdvancedRiskManager()
| |||
{
| |||
delete tracker;
| |||
}
| |||
| |||
// Check if trading is allowed
| |||
bool CanTrade()
| |||
{
| |||
// Circuit breaker check
| |||
if(circuitBreakerActive)
| |||
{
| |||
if(TimeCurrent() < circuitBreakerUntil)
| |||
{
| |||
Print("CIRCUIT BREAKER ACTIVE - Trading suspended until ", circuitBreakerUntil);
| |||
return false;
| |||
}
| |||
else
| |||
{
| |||
circuitBreakerActive = false;
| |||
Print("Circuit breaker reset - Trading resumed");
| |||
}
| |||
}
| |||
| |||
// Daily loss limit
| |||
double dailyLoss = -tracker.GetDailyProfit();
| |||
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
| |||
double dailyLossPercent = dailyLoss / balance * 100;
| |||
| |||
if(dailyLossPercent >= maxDailyLossPercent)
| |||
{
| |||
ActivateCircuitBreaker(24); // 24 hour suspension
| |||
Print("DAILY LOSS LIMIT REACHED: ", dailyLossPercent, "% - Circuit breaker activated");
| |||
return false;
| |||
}
| |||
| |||
// Drawdown limit
| |||
if(tracker.GetCurrentDrawdown() >= maxDrawdownPercent)
| |||
{
| |||
ActivateCircuitBreaker(48); // 48 hour suspension
| |||
Print("MAX DRAWDOWN REACHED: ", tracker.GetCurrentDrawdown(), "% - Circuit breaker activated");
| |||
return false;
| |||
}
| |||
| |||
// Consecutive loss protection
| |||
if(GetConsecutiveLosses() >= 5)
| |||
{
| |||
ActivateCircuitBreaker(6); // 6 hour cooldown
| |||
Print("5 CONSECUTIVE LOSSES - Cooling down for 6 hours");
| |||
return false;
| |||
}
| |||
| |||
return true;
| |||
}
| |||
| |||
void ActivateCircuitBreaker(int hours)
| |||
{
| |||
circuitBreakerActive = true;
| |||
circuitBreakerUntil = TimeCurrent() + hours * 3600;
| |||
}
| |||
| |||
// Adaptive risk calculation
| |||
double GetCurrentRiskPercent()
| |||
{
| |||
if(!useAdaptiveRisk)
| |||
return baseRiskPercent;
| |||
| |||
// Reduce risk after losses
| |||
double winRate = tracker.GetWinRate();
| |||
double profitFactor = tracker.GetProfitFactor();
| |||
| |||
currentRiskPercent = baseRiskPercent;
| |||
| |||
// Adjust based on performance
| |||
if(winRate < 40)
| |||
currentRiskPercent *= 0.5; // Reduce risk by 50%
| |||
else if(winRate > 60 && profitFactor > 1.5)
| |||
currentRiskPercent *= 1.2; // Increase risk by 20%
| |||
| |||
// Drawdown adjustment
| |||
double dd = tracker.GetCurrentDrawdown();
| |||
if(dd > 5)
| |||
currentRiskPercent *= (1 - dd / 100); // Scale down with drawdown
| |||
| |||
// Keep within bounds
| |||
currentRiskPercent = MathMax(0.25, MathMin(2.0, currentRiskPercent));
| |||
| |||
return currentRiskPercent;
| |||
}
| |||
| |||
int GetConsecutiveLosses()
| |||
{
| |||
// Check last 10 positions for consecutive losses
| |||
int consecutive = 0;
| |||
| |||
for(int i = HistoryDealsTotal() - 1; i >= HistoryDealsTotal() - 10 && i >= 0; i--)
| |||
{
| |||
ulong ticket = HistoryDealGetTicket(i);
| |||
if(ticket == 0) continue;
| |||
| |||
if(HistoryDealGetInteger(ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT)
| |||
{
| |||
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
| |||
if(profit < 0)
| |||
consecutive++;
| |||
else
| |||
break;
| |||
}
| |||
}
| |||
| |||
return consecutive;
| |||
}
| |||
| |||
void RecordTrade(double openPrice, double closePrice, double profit, double lots, int type)
| |||
{
| |||
tracker.RecordTrade(openPrice, closePrice, profit, lots, type);
| |||
}
| |||
| |||
CPerformanceTracker* GetTracker() { return tracker; }
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Real-Time Dashboard Display |
| |||
//+------------------------------------------------------------------+
| |||
class CPerformanceDashboard
| |||
{
| |||
private:
| |||
CAdvancedRiskManager *riskManager;
| |||
| |||
// Chart objects
| |||
CChartObjectLabel lblTitle;
| |||
CChartObjectLabel lblStats[];
| |||
| |||
int windowIndex;
| |||
int xPosition;
| |||
int yPosition;
| |||
| |||
string prefix;
| |||
| |||
public:
| |||
CPerformanceDashboard(CAdvancedRiskManager *rm)
| |||
{
| |||
riskManager = rm;
| |||
prefix = "Dashboard_";
| |||
windowIndex = 0;
| |||
xPosition = 10;
| |||
yPosition = 20;
| |||
}
| |||
| |||
void Initialize()
| |||
{
| |||
// Create title
| |||
lblTitle.Create(0, prefix + "Title", windowIndex, xPosition, yPosition);
| |||
lblTitle.Description("═══ AI GOLD SYSTEM PERFORMANCE ═══");
| |||
lblTitle.Color(clrYellow);
| |||
lblTitle.FontSize(10);
| |||
| |||
// Create stat labels
| |||
ArrayResize(lblStats, 15);
| |||
| |||
string labels[] = {
| |||
"Total Trades:", "Win Rate:", "Profit Factor:",
| |||
"Total Profit:", "Max Drawdown:", "Daily P/L:",
| |||
"Avg Win:", "Avg Loss:", "Expectancy:",
| |||
"ROI:", "Risk Level:", "Status:",
| |||
"Largest Win:", "Largest Loss:", "Daily Trades:"
| |||
};
| |||
| |||
for(int i = 0; i < 15; i++)
| |||
{
| |||
lblStats[i].Create(0, prefix + "Stat" + IntegerToString(i),
| |||
windowIndex, xPosition, yPosition + 30 + (i * 18));
| |||
lblStats[i].Description(labels[i]);
| |||
lblStats[i].Color(clrWhite);
| |||
lblStats[i].FontSize(8);
| |||
}
| |||
}
| |||
| |||
void Update()
| |||
{
| |||
CPerformanceTracker *tracker = riskManager.GetTracker();
| |||
| |||
UpdateLabel(0, "Total Trades: " + IntegerToString(tracker.GetTotalTrades()));
| |||
UpdateLabel(1, "Win Rate: " + DoubleToString(tracker.GetWinRate(), 1) + "%",
| |||
tracker.GetWinRate() >= 50 ? clrLime : clrRed);
| |||
UpdateLabel(2, "Profit Factor: " + DoubleToString(tracker.GetProfitFactor(), 2),
| |||
tracker.GetProfitFactor() >= 1.5 ? clrLime : clrOrange);
| |||
UpdateLabel(3, "Total Profit: $" + DoubleToString(tracker.GetTotalProfit(), 2),
| |||
tracker.GetTotalProfit() > 0 ? clrLime : clrRed);
| |||
UpdateLabel(4, "Max DD: " + DoubleToString(tracker.GetMaxDrawdown(), 2) + "%",
| |||
tracker.GetMaxDrawdown() < 10 ? clrLime : clrRed);
| |||
UpdateLabel(5, "Daily P/L: $" + DoubleToString(tracker.GetDailyProfit(), 2),
| |||
tracker.GetDailyProfit() > 0 ? clrLime : clrRed);
| |||
UpdateLabel(6, "Avg Win: $" + DoubleToString(tracker.GetAverageWin(), 2));
| |||
UpdateLabel(7, "Avg Loss: $" + DoubleToString(tracker.GetAverageLoss(), 2));
| |||
UpdateLabel(8, "Expectancy: $" + DoubleToString(tracker.GetExpectancy(), 2),
| |||
tracker.GetExpectancy() > 0 ? clrLime : clrRed);
| |||
UpdateLabel(9, "ROI: " + DoubleToString(tracker.GetROI(), 2) + "%",
| |||
tracker.GetROI() > 0 ? clrLime : clrRed);
| |||
UpdateLabel(10, "Risk Level: " + DoubleToString(riskManager.GetCurrentRiskPercent(), 2) + "%");
| |||
UpdateLabel(11, riskManager.CanTrade() ? "Status: ACTIVE" : "Status: SUSPENDED",
| |||
riskManager.CanTrade() ? clrLime : clrRed);
| |||
UpdateLabel(12, "Largest Win: $" + DoubleToString(tracker.GetLargestWin(), 2));
| |||
UpdateLabel(13, "Largest Loss: $" + DoubleToString(tracker.GetLargestLoss(), 2));
| |||
UpdateLabel(14, "Daily Trades: " + IntegerToString(tracker.GetDailyTrades()));
| |||
}
| |||
| |||
void UpdateLabel(int index, string text, color clr = clrWhite)
| |||
{
| |||
if(index >= 0 && index < ArraySize(lblStats))
| |||
{
| |||
lblStats[index].Description(text);
| |||
lblStats[index].Color(clr);
| |||
}
| |||
}
| |||
| |||
void Destroy()
| |||
{
| |||
lblTitle.Delete();
| |||
for(int i = 0; i < ArraySize(lblStats); i++)
| |||
lblStats[i].Delete();
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Signal Quality Analyzer - Pre-Trade Validation |
| |||
//+------------------------------------------------------------------+
| |||
class CSignalQualityAnalyzer
| |||
{
| |||
private:
| |||
double qualityThreshold;
| |||
| |||
public:
| |||
CSignalQualityAnalyzer(double threshold = 70.0)
| |||
{
| |||
qualityThreshold = threshold;
| |||
}
| |||
| |||
// Comprehensive signal quality scoring (0-100)
| |||
double AnalyzeSignalQuality(double trendScore, double volatilityScore,
| |||
double indicatorScore, double patternScore,
| |||
double atr, double spread)
| |||
{
| |||
double quality = 0;
| |||
| |||
// 1. Trend alignment (30 points)
| |||
if(MathAbs(trendScore) > 70)
| |||
quality += 30;
| |||
else if(MathAbs(trendScore) > 40)
| |||
quality += 15;
| |||
| |||
// 2. Volatility appropriateness (20 points)
| |||
if(volatilityScore > 40 && volatilityScore < 80)
| |||
quality += 20; // Ideal volatility
| |||
else if(volatilityScore > 80)
| |||
quality += 5; // Too volatile
| |||
| |||
// 3. Indicator confluence (25 points)
| |||
quality += indicatorScore * 0.25;
| |||
| |||
// 4. Pattern strength (25 points)
| |||
if(MathAbs(patternScore) > 60)
| |||
quality += 25;
| |||
else if(MathAbs(patternScore) > 30)
| |||
quality += 12;
| |||
| |||
// 5. Spread penalty
| |||
if(spread > 20)
| |||
quality *= 0.8; // 20% penalty
| |||
| |||
return NormalizeDouble(quality, 2);
| |||
}
| |||
| |||
bool IsHighQualitySignal(double quality)
| |||
{
| |||
return quality >= qualityThreshold;
| |||
}
| |||
};
| |||
//+------------------------------------------------------------------+
|