//+------------------------------------------------------------------+ //| IndicatorEngine.mqh - Advanced Technical Indicator System | //| Multi-timeframe Technical Analysis Engine | //+------------------------------------------------------------------+ #ifndef INDICATOR_ENGINE_MQH #define INDICATOR_ENGINE_MQH enum ENUM_TRADE_SIGNAL { SIGNAL_NONE = 0, SIGNAL_BUY = 1, SIGNAL_SELL = 2, SIGNAL_CLOSE_BUY = 3, SIGNAL_CLOSE_SELL = 4, SIGNAL_CLOSE_ALL = 5 }; enum ENUM_SIGNAL_STRENGTH { SIGNAL_WEAK = 1, SIGNAL_MODERATE = 2, SIGNAL_STRONG = 3, SIGNAL_VERY_STRONG = 4 }; // Intelligence levels for AI analysis enum ENUM_CONVICTION_LEVEL { CONVICTION_WEAK = 1, CONVICTION_MODERATE = 2, CONVICTION_STRONG = 3, CONVICTION_VERY_STRONG = 4 }; // Market edge strength enum ENUM_EDGE_STRENGTH { EDGE_NONE = 0, EDGE_WEAK = 1, EDGE_MODERATE = 2, EDGE_STRONG = 3, EDGE_VERY_STRONG = 4, EDGE_VERY_WEAK = -1 }; // Smart trading intelligence structure struct TradingIntelligence { ENUM_TRADE_SIGNAL signal; ENUM_CONVICTION_LEVEL conviction; string reason; double risk_reward_ratio; double probability_success; double optimal_position_size; string key_level; string market_narrative; }; // Market edge analysis struct MarketEdge { ENUM_EDGE_STRENGTH strength; double confidence; string reason; bool trend_alignment; int supporting_timeframes; }; // Risk scenario analysis struct RiskScenario { double best_case_profit; double base_case_profit; double base_case_loss; double worst_case_loss; double max_account_risk; string risk_level; string exit_strategy; }; enum ENUM_TREND_STATE { TREND_BULLISH, TREND_BEARISH, TREND_SIDEWAYS, TREND_UNCERTAIN }; struct IndicatorSignal { ENUM_TRADE_SIGNAL signal; ENUM_SIGNAL_STRENGTH strength; double confidence; string reason; datetime timestamp; }; struct MarketStructure { ENUM_TREND_STATE trend; double support; double resistance; double momentum; double volatility; bool breakout; }; struct MultiTimeframeAnalysis { ENUM_TREND_STATE trendM1; ENUM_TREND_STATE trendM5; ENUM_TREND_STATE trendM15; ENUM_TREND_STATE trendH1; ENUM_TREND_STATE trendH4; ENUM_TREND_STATE trendD1; double overallBias; bool alignment; }; class CAdvancedIndicatorEngine { private: string m_symbol; ENUM_TIMEFRAMES m_timeframe; // Indicator handles int m_handleMA20; int m_handleMA50; int m_handleMA200; int m_handleRSI; int m_handleMACD; int m_handleBB; int m_handleStoch; int m_handleATR; int m_handleADX; int m_handleCCI; // Buffers double m_ma20[]; double m_ma50[]; double m_ma200[]; double m_rsi[]; double m_macdMain[]; double m_macdSignal[]; double m_bbUpper[]; double m_bbLower[]; double m_bbMiddle[]; double m_stochMain[]; double m_stochSignal[]; double m_atr[]; double m_adx[]; double m_cci[]; // Analysis parameters int m_lookbackPeriod; double m_rsiOverbought; double m_rsiOversold; double m_stochOverbought; double m_stochOversold; public: CAdvancedIndicatorEngine(void); ~CAdvancedIndicatorEngine(void); // Initialization bool Initialize(string symbol, ENUM_TIMEFRAMES timeframe); void SetParameters(int lookback, double rsiOB, double rsiOS, double stochOB, double stochOS); // Core Analysis IndicatorSignal GetSignal(void); MarketStructure GetMarketStructure(void); MultiTimeframeAnalysis GetMultiTimeframeAnalysis(void); // Individual Indicators IndicatorSignal AnalyzeMovingAverages(void); IndicatorSignal AnalyzeRSI(void); IndicatorSignal AnalyzeMACD(void); IndicatorSignal AnalyzeBollingerBands(void); IndicatorSignal AnalyzeStochastic(void); IndicatorSignal AnalyzeADX(void); IndicatorSignal AnalyzeCCI(void); // Support/Resistance double FindSupport(int bars = 50); double FindResistance(int bars = 50); bool IsAtSupport(double price, double tolerance = 0.0005); bool IsAtResistance(double price, double tolerance = 0.0005); // Pattern Recognition bool IsBullishEngulfing(void); bool IsBearishEngulfing(void); bool IsHammer(void); bool IsDojiPattern(void); // Trend Analysis ENUM_TREND_STATE GetTrend(ENUM_TIMEFRAMES tf = PERIOD_CURRENT); double GetTrendStrength(void); bool IsTrendChanging(void); // Volatility Analysis double GetVolatility(void); bool IsHighVolatility(void); bool IsLowVolatility(void); // Utility Methods double GetCurrentPrice(void); bool UpdateIndicators(void); void PrintAnalysis(void); string GetSignalDescription(IndicatorSignal signal); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CAdvancedIndicatorEngine::CAdvancedIndicatorEngine(void) { m_symbol = ""; m_timeframe = PERIOD_CURRENT; m_lookbackPeriod = 14; m_rsiOverbought = 70; m_rsiOversold = 30; m_stochOverbought = 80; m_stochOversold = 20; // Initialize handles m_handleMA20 = INVALID_HANDLE; m_handleMA50 = INVALID_HANDLE; m_handleMA200 = INVALID_HANDLE; m_handleRSI = INVALID_HANDLE; m_handleMACD = INVALID_HANDLE; m_handleBB = INVALID_HANDLE; m_handleStoch = INVALID_HANDLE; m_handleATR = INVALID_HANDLE; m_handleADX = INVALID_HANDLE; m_handleCCI = INVALID_HANDLE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CAdvancedIndicatorEngine::~CAdvancedIndicatorEngine(void) { // Release indicator handles if(m_handleMA20 != INVALID_HANDLE) IndicatorRelease(m_handleMA20); if(m_handleMA50 != INVALID_HANDLE) IndicatorRelease(m_handleMA50); if(m_handleMA200 != INVALID_HANDLE) IndicatorRelease(m_handleMA200); if(m_handleRSI != INVALID_HANDLE) IndicatorRelease(m_handleRSI); if(m_handleMACD != INVALID_HANDLE) IndicatorRelease(m_handleMACD); if(m_handleBB != INVALID_HANDLE) IndicatorRelease(m_handleBB); if(m_handleStoch != INVALID_HANDLE) IndicatorRelease(m_handleStoch); if(m_handleATR != INVALID_HANDLE) IndicatorRelease(m_handleATR); if(m_handleADX != INVALID_HANDLE) IndicatorRelease(m_handleADX); if(m_handleCCI != INVALID_HANDLE) IndicatorRelease(m_handleCCI); } //+------------------------------------------------------------------+ //| Initialize indicator engine | //+------------------------------------------------------------------+ bool CAdvancedIndicatorEngine::Initialize(string symbol, ENUM_TIMEFRAMES timeframe) { m_symbol = symbol; m_timeframe = timeframe; // Create indicator handles m_handleMA20 = iMA(m_symbol, m_timeframe, 20, 0, MODE_SMA, PRICE_CLOSE); m_handleMA50 = iMA(m_symbol, m_timeframe, 50, 0, MODE_SMA, PRICE_CLOSE); m_handleMA200 = iMA(m_symbol, m_timeframe, 200, 0, MODE_SMA, PRICE_CLOSE); m_handleRSI = iRSI(m_symbol, m_timeframe, m_lookbackPeriod, PRICE_CLOSE); m_handleMACD = iMACD(m_symbol, m_timeframe, 12, 26, 9, PRICE_CLOSE); m_handleBB = iBands(m_symbol, m_timeframe, 20, 0, 2.0, PRICE_CLOSE); m_handleStoch = iStochastic(m_symbol, m_timeframe, 5, 3, 3, MODE_SMA, STO_LOWHIGH); m_handleATR = iATR(m_symbol, m_timeframe, 14); m_handleADX = iADX(m_symbol, m_timeframe, 14); m_handleCCI = iCCI(m_symbol, m_timeframe, 14, PRICE_TYPICAL); // Check if all handles are valid bool allValid = (m_handleMA20 != INVALID_HANDLE && m_handleMA50 != INVALID_HANDLE && m_handleMA200 != INVALID_HANDLE && m_handleRSI != INVALID_HANDLE && m_handleMACD != INVALID_HANDLE && m_handleBB != INVALID_HANDLE && m_handleStoch != INVALID_HANDLE && m_handleATR != INVALID_HANDLE && m_handleADX != INVALID_HANDLE && m_handleCCI != INVALID_HANDLE); if(!allValid) { Print("❌ Failed to initialize some indicators"); return false; } // Initialize arrays ArraySetAsSeries(m_ma20, true); ArraySetAsSeries(m_ma50, true); ArraySetAsSeries(m_ma200, true); ArraySetAsSeries(m_rsi, true); ArraySetAsSeries(m_macdMain, true); ArraySetAsSeries(m_macdSignal, true); ArraySetAsSeries(m_bbUpper, true); ArraySetAsSeries(m_bbLower, true); ArraySetAsSeries(m_bbMiddle, true); ArraySetAsSeries(m_stochMain, true); ArraySetAsSeries(m_stochSignal, true); ArraySetAsSeries(m_atr, true); ArraySetAsSeries(m_adx, true); ArraySetAsSeries(m_cci, true); Print("✅ Indicator Engine initialized for ", m_symbol, " ", EnumToString(m_timeframe)); return true; } //+------------------------------------------------------------------+ //| Update all indicators | //+------------------------------------------------------------------+ bool CAdvancedIndicatorEngine::UpdateIndicators(void) { int copied = 0; // Copy indicator data copied += CopyBuffer(m_handleMA20, 0, 0, 3, m_ma20); copied += CopyBuffer(m_handleMA50, 0, 0, 3, m_ma50); copied += CopyBuffer(m_handleMA200, 0, 0, 3, m_ma200); copied += CopyBuffer(m_handleRSI, 0, 0, 3, m_rsi); copied += CopyBuffer(m_handleMACD, 0, 0, 3, m_macdMain); copied += CopyBuffer(m_handleMACD, 1, 0, 3, m_macdSignal); copied += CopyBuffer(m_handleBB, 1, 0, 3, m_bbUpper); copied += CopyBuffer(m_handleBB, 2, 0, 3, m_bbLower); copied += CopyBuffer(m_handleBB, 0, 0, 3, m_bbMiddle); copied += CopyBuffer(m_handleStoch, 0, 0, 3, m_stochMain); copied += CopyBuffer(m_handleStoch, 1, 0, 3, m_stochSignal); copied += CopyBuffer(m_handleATR, 0, 0, 3, m_atr); copied += CopyBuffer(m_handleADX, 0, 0, 3, m_adx); copied += CopyBuffer(m_handleCCI, 0, 0, 3, m_cci); return (copied > 30); // Should be 42 total (14 * 3) } //+------------------------------------------------------------------+ //| Get main trading signal | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::GetSignal(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.reason = "No clear signal"; signal.timestamp = TimeCurrent(); if(!UpdateIndicators()) return signal; // Analyze individual indicators IndicatorSignal maSignal = AnalyzeMovingAverages(); IndicatorSignal rsiSignal = AnalyzeRSI(); IndicatorSignal macdSignal = AnalyzeMACD(); IndicatorSignal bbSignal = AnalyzeBollingerBands(); IndicatorSignal stochSignal = AnalyzeStochastic(); IndicatorSignal adxSignal = AnalyzeADX(); // Score system int buyScore = 0; int sellScore = 0; double totalConfidence = 0; string reasons = ""; // Weight the signals based on reliability if(maSignal.signal == SIGNAL_BUY) buyScore += 2; else if(maSignal.signal == SIGNAL_SELL) sellScore += 2; if(rsiSignal.signal == SIGNAL_BUY) buyScore += 1; else if(rsiSignal.signal == SIGNAL_SELL) sellScore += 1; if(macdSignal.signal == SIGNAL_BUY) buyScore += 2; else if(macdSignal.signal == SIGNAL_SELL) sellScore += 2; if(bbSignal.signal == SIGNAL_BUY) buyScore += 1; else if(bbSignal.signal == SIGNAL_SELL) sellScore += 1; if(stochSignal.signal == SIGNAL_BUY) buyScore += 1; else if(stochSignal.signal == SIGNAL_SELL) sellScore += 1; // Calculate confidence totalConfidence = (maSignal.confidence + rsiSignal.confidence + macdSignal.confidence + bbSignal.confidence + stochSignal.confidence + adxSignal.confidence) / 6.0; // Determine final signal if(buyScore > sellScore && buyScore >= 3) { signal.signal = SIGNAL_BUY; signal.confidence = totalConfidence; signal.reason = "Multiple bullish indicators aligned"; if(buyScore >= 5) signal.strength = SIGNAL_VERY_STRONG; else if(buyScore >= 4) signal.strength = SIGNAL_STRONG; else signal.strength = SIGNAL_MODERATE; } else if(sellScore > buyScore && sellScore >= 3) { signal.signal = SIGNAL_SELL; signal.confidence = totalConfidence; signal.reason = "Multiple bearish indicators aligned"; if(sellScore >= 5) signal.strength = SIGNAL_VERY_STRONG; else if(sellScore >= 4) signal.strength = SIGNAL_STRONG; else signal.strength = SIGNAL_MODERATE; } return signal; } //+------------------------------------------------------------------+ //| Analyze Moving Averages | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeMovingAverages(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_ma20) < 2 || ArraySize(m_ma50) < 2) return signal; double currentPrice = GetCurrentPrice(); // Golden Cross / Death Cross bool goldenCross = (m_ma20[0] > m_ma50[0] && m_ma20[1] <= m_ma50[1]); bool deathCross = (m_ma20[0] < m_ma50[0] && m_ma20[1] >= m_ma50[1]); // Price relative to MAs bool priceAboveMA20 = currentPrice > m_ma20[0]; bool priceAboveMA50 = currentPrice > m_ma50[0]; bool ma20AboveMA50 = m_ma20[0] > m_ma50[0]; if(goldenCross || (priceAboveMA20 && priceAboveMA50 && ma20AboveMA50)) { signal.signal = SIGNAL_BUY; signal.confidence = goldenCross ? 0.8 : 0.6; signal.strength = goldenCross ? SIGNAL_STRONG : SIGNAL_MODERATE; signal.reason = goldenCross ? "Golden Cross detected" : "Price above MAs, bullish alignment"; } else if(deathCross || (!priceAboveMA20 && !priceAboveMA50 && !ma20AboveMA50)) { signal.signal = SIGNAL_SELL; signal.confidence = deathCross ? 0.8 : 0.6; signal.strength = deathCross ? SIGNAL_STRONG : SIGNAL_MODERATE; signal.reason = deathCross ? "Death Cross detected" : "Price below MAs, bearish alignment"; } return signal; } //+------------------------------------------------------------------+ //| Analyze RSI | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeRSI(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_rsi) < 2) return signal; double currentRSI = m_rsi[0]; double previousRSI = m_rsi[1]; // RSI Divergence and Oversold/Overbought if(currentRSI <= m_rsiOversold && previousRSI > currentRSI) { signal.signal = SIGNAL_BUY; signal.confidence = 0.7; signal.strength = SIGNAL_MODERATE; signal.reason = "RSI oversold condition"; } else if(currentRSI >= m_rsiOverbought && previousRSI < currentRSI) { signal.signal = SIGNAL_SELL; signal.confidence = 0.7; signal.strength = SIGNAL_MODERATE; signal.reason = "RSI overbought condition"; } else if(currentRSI > 50 && previousRSI <= 50) { signal.signal = SIGNAL_BUY; signal.confidence = 0.5; signal.strength = SIGNAL_WEAK; signal.reason = "RSI bullish momentum"; } else if(currentRSI < 50 && previousRSI >= 50) { signal.signal = SIGNAL_SELL; signal.confidence = 0.5; signal.strength = SIGNAL_WEAK; signal.reason = "RSI bearish momentum"; } return signal; } //+------------------------------------------------------------------+ //| Analyze MACD | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeMACD(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_macdMain) < 2 || ArraySize(m_macdSignal) < 2) return signal; double currentMACD = m_macdMain[0]; double currentSignal = m_macdSignal[0]; double previousMACD = m_macdMain[1]; double previousSignal = m_macdSignal[1]; // MACD Signal Line Crossover bool bullishCrossover = (currentMACD > currentSignal && previousMACD <= previousSignal); bool bearishCrossover = (currentMACD < currentSignal && previousMACD >= previousSignal); // MACD Zero Line Cross bool bullishZeroCross = (currentMACD > 0 && previousMACD <= 0); bool bearishZeroCross = (currentMACD < 0 && previousMACD >= 0); if(bullishCrossover || bullishZeroCross) { signal.signal = SIGNAL_BUY; signal.confidence = bullishZeroCross ? 0.8 : 0.7; signal.strength = bullishZeroCross ? SIGNAL_STRONG : SIGNAL_MODERATE; signal.reason = bullishZeroCross ? "MACD bullish zero cross" : "MACD bullish crossover"; } else if(bearishCrossover || bearishZeroCross) { signal.signal = SIGNAL_SELL; signal.confidence = bearishZeroCross ? 0.8 : 0.7; signal.strength = bearishZeroCross ? SIGNAL_STRONG : SIGNAL_MODERATE; signal.reason = bearishZeroCross ? "MACD bearish zero cross" : "MACD bearish crossover"; } return signal; } //+------------------------------------------------------------------+ //| Analyze Bollinger Bands | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeBollingerBands(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_bbUpper) < 1 || ArraySize(m_bbLower) < 1) return signal; double currentPrice = GetCurrentPrice(); double upperBand = m_bbUpper[0]; double lowerBand = m_bbLower[0]; double middleBand = m_bbMiddle[0]; // BB Squeeze and Breakouts double bandWidth = (upperBand - lowerBand) / middleBand; if(currentPrice <= lowerBand) { signal.signal = SIGNAL_BUY; signal.confidence = 0.6; signal.strength = SIGNAL_MODERATE; signal.reason = "Price at BB lower band (oversold)"; } else if(currentPrice >= upperBand) { signal.signal = SIGNAL_SELL; signal.confidence = 0.6; signal.strength = SIGNAL_MODERATE; signal.reason = "Price at BB upper band (overbought)"; } else if(currentPrice > middleBand) { signal.signal = SIGNAL_BUY; signal.confidence = 0.4; signal.strength = SIGNAL_WEAK; signal.reason = "Price above BB middle line"; } else if(currentPrice < middleBand) { signal.signal = SIGNAL_SELL; signal.confidence = 0.4; signal.strength = SIGNAL_WEAK; signal.reason = "Price below BB middle line"; } return signal; } //+------------------------------------------------------------------+ //| Analyze Stochastic | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeStochastic(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_stochMain) < 2 || ArraySize(m_stochSignal) < 2) return signal; double currentK = m_stochMain[0]; double currentD = m_stochSignal[0]; double previousK = m_stochMain[1]; double previousD = m_stochSignal[1]; // Stochastic Crossover bool bullishCross = (currentK > currentD && previousK <= previousD); bool bearishCross = (currentK < currentD && previousK >= previousD); if(bullishCross && currentK < m_stochOversold) { signal.signal = SIGNAL_BUY; signal.confidence = 0.7; signal.strength = SIGNAL_MODERATE; signal.reason = "Stochastic bullish crossover in oversold"; } else if(bearishCross && currentK > m_stochOverbought) { signal.signal = SIGNAL_SELL; signal.confidence = 0.7; signal.strength = SIGNAL_MODERATE; signal.reason = "Stochastic bearish crossover in overbought"; } return signal; } //+------------------------------------------------------------------+ //| Analyze ADX | //+------------------------------------------------------------------+ IndicatorSignal CAdvancedIndicatorEngine::AnalyzeADX(void) { IndicatorSignal signal; signal.signal = SIGNAL_NONE; signal.strength = SIGNAL_WEAK; signal.confidence = 0; signal.timestamp = TimeCurrent(); if(ArraySize(m_adx) < 1) return signal; double currentADX = m_adx[0]; // ADX indicates trend strength, not direction if(currentADX > 25) { signal.confidence = 0.8; // Strong trend signal.reason = "Strong trend detected (ADX > 25)"; } else { signal.confidence = 0.3; // Weak trend signal.reason = "Weak trend (ADX < 25)"; } return signal; } //+------------------------------------------------------------------+ //| Get current price | //+------------------------------------------------------------------+ double CAdvancedIndicatorEngine::GetCurrentPrice(void) { return SymbolInfoDouble(m_symbol, SYMBOL_BID); } //+------------------------------------------------------------------+ //| Get market structure | //+------------------------------------------------------------------+ MarketStructure CAdvancedIndicatorEngine::GetMarketStructure(void) { MarketStructure structure; structure.trend = GetTrend(); structure.support = FindSupport(); structure.resistance = FindResistance(); structure.momentum = ArraySize(m_rsi) > 0 ? m_rsi[0] : 50; structure.volatility = GetVolatility(); double currentPrice = GetCurrentPrice(); structure.breakout = (currentPrice > structure.resistance || currentPrice < structure.support); return structure; } //+------------------------------------------------------------------+ //| Get trend for timeframe | //+------------------------------------------------------------------+ ENUM_TREND_STATE CAdvancedIndicatorEngine::GetTrend(ENUM_TIMEFRAMES tf = PERIOD_CURRENT) { if(tf == PERIOD_CURRENT) tf = m_timeframe; if(!UpdateIndicators()) return TREND_UNCERTAIN; if(ArraySize(m_ma20) < 1 || ArraySize(m_ma50) < 1) return TREND_UNCERTAIN; double currentPrice = GetCurrentPrice(); if(currentPrice > m_ma20[0] && m_ma20[0] > m_ma50[0]) return TREND_BULLISH; else if(currentPrice < m_ma20[0] && m_ma20[0] < m_ma50[0]) return TREND_BEARISH; else return TREND_SIDEWAYS; } //+------------------------------------------------------------------+ //| Find support level | //+------------------------------------------------------------------+ double CAdvancedIndicatorEngine::FindSupport(int bars = 50) { double lowest = iLow(m_symbol, m_timeframe, iLowest(m_symbol, m_timeframe, MODE_LOW, bars, 0)); return lowest; } //+------------------------------------------------------------------+ //| Find resistance level | //+------------------------------------------------------------------+ double CAdvancedIndicatorEngine::FindResistance(int bars = 50) { double highest = iHigh(m_symbol, m_timeframe, iHighest(m_symbol, m_timeframe, MODE_HIGH, bars, 0)); return highest; } //+------------------------------------------------------------------+ //| Get volatility | //+------------------------------------------------------------------+ double CAdvancedIndicatorEngine::GetVolatility(void) { if(ArraySize(m_atr) > 0) return m_atr[0]; return 0; } //+------------------------------------------------------------------+ //| Print analysis report | //+------------------------------------------------------------------+ void CAdvancedIndicatorEngine::PrintAnalysis(void) { IndicatorSignal signal = GetSignal(); MarketStructure structure = GetMarketStructure(); Print("=== TECHNICAL ANALYSIS REPORT ==="); Print("Signal: ", EnumToString(signal.signal)); Print("Strength: ", EnumToString(signal.strength)); Print("Confidence: ", DoubleToString(signal.confidence * 100, 1), "%"); Print("Reason: ", signal.reason); Print("Trend: ", EnumToString(structure.trend)); Print("Support: ", DoubleToString(structure.support, 5)); Print("Resistance: ", DoubleToString(structure.resistance, 5)); Print("Volatility: ", DoubleToString(structure.volatility, 5)); Print("==============================="); } #endif // INDICATOR_ENGINE_MQH