//+------------------------------------------------------------------+ //| Consolidation Detector EA | //| Detects consolidations using multiple methods | //+------------------------------------------------------------------+ #property copyright "Your Name" #property link "https://www.example.com" #property version "1.01" // Input Parameters input group "Consolidation Detection Settings" input bool UsePriceRange = true; // Enable Price Range Analysis input int PriceRangeBars = 20; // Bars for Price Range input double PriceRangeThreshold = 0.5; // Price Range Threshold (% of ATR) input bool UseBollingerSqueeze = true; // Enable Bollinger Bands Squeeze input int BollingerPeriod = 20; // Bollinger Bands Period input double BollingerThreshold = 0.02; // Bollinger Bandwidth Threshold input bool UseATRCrossover = true; // Enable ATR Crossover input int FastATRPeriod = 5; // Fast ATR Period input int SlowATRPeriod = 20; // Slow ATR Period input bool UseVolumeAnalysis = true; // Enable Volume Analysis input int VolumeBars = 20; // Bars for Volume Analysis input double VolumeThreshold = 0.7; // Volume Threshold (% of Avg Volume) input group "Visualization and Alerts" input bool DrawZones = true; // Draw Consolidation Zones input bool EnableAlerts = true; // Enable Alerts for Consolidation input color ZoneColor = clrPurple; // Color for Consolidation Zones // Global Variables datetime lastBarTime; // Track last processed bar time int bollingerHandle; // Handle for Bollinger Bands int fastATRHandle; // Handle for Fast ATR int slowATRHandle; // Handle for Slow ATR int priceATRHandle; // Handle for Price Range ATR //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { // Initialize Bollinger Bands handle bollingerHandle = iBands(_Symbol, PERIOD_CURRENT, BollingerPeriod, 0, 2.0, PRICE_CLOSE); if (bollingerHandle == INVALID_HANDLE) { Print("Failed to initialize Bollinger Bands"); return(INIT_FAILED); } // Initialize ATR handles priceATRHandle = iATR(_Symbol, PERIOD_CURRENT, PriceRangeBars); fastATRHandle = iATR(_Symbol, PERIOD_CURRENT, FastATRPeriod); slowATRHandle = iATR(_Symbol, PERIOD_CURRENT, SlowATRPeriod); if (priceATRHandle == INVALID_HANDLE || fastATRHandle == INVALID_HANDLE || slowATRHandle == INVALID_HANDLE) { Print("Failed to initialize ATR indicators"); return(INIT_FAILED); } // Set last bar time to avoid processing same bar multiple times lastBarTime = TimeCurrent(); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Release indicator handles IndicatorRelease(bollingerHandle); IndicatorRelease(priceATRHandle); IndicatorRelease(fastATRHandle); IndicatorRelease(slowATRHandle); // Clean up chart objects ObjectsDeleteAll(0, "Consolidation_"); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // Process only on new bar datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0); if (currentBarTime == lastBarTime) return; lastBarTime = currentBarTime; bool isConsolidation = false; string consolidationMethods = ""; // Get high and low for visualization double high = iHigh(_Symbol, PERIOD_CURRENT, 1); double low = iLow(_Symbol, PERIOD_CURRENT, 1); datetime startTime = iTime(_Symbol, PERIOD_CURRENT, PriceRangeBars); datetime endTime = currentBarTime; // Check Price Range Consolidation // if (UsePriceRange && IsPriceRangeConsolidation(PriceRangeBars, PriceRangeThreshold)) // { // isConsolidation = true; // consolidationMethods += "Price Range, "; // } // // Check Bollinger Bands Squeeze // if (UseBollingerSqueeze && IsBollingerSqueeze(BollingerPeriod, BollingerThreshold)) // { // isConsolidation = true; // consolidationMethods += "Bollinger Squeeze, "; // } // // Check ATR Crossover // if (UseATRCrossover && IsATRConsolidation(FastATRPeriod, SlowATRPeriod)) // { // isConsolidation = true; // consolidationMethods += "ATR Crossover, "; // } // // Check Volume Analysis // if (UseVolumeAnalysis && IsVolumeConsolidation(VolumeBars, VolumeThreshold)) // { // isConsolidation = true; // consolidationMethods += "Volume Analysis, "; // } // Output and Visualization if (isConsolidation) { string message = "Consolidation detected by: " + consolidationMethods; Print(message); if (EnableAlerts) Alert(message); if (DrawZones) DrawConsolidationZone(high, low, startTime, endTime); } else { Print("No consolidation detected"); } } //+------------------------------------------------------------------+ //| Price Range Consolidation Detection | //+------------------------------------------------------------------+ bool IsPriceRangeConsolidation(int bars, double threshold) { double rangeSum = 0.0; double high[], low[], atr[]; ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); ArraySetAsSeries(atr, true); CopyHigh(_Symbol, PERIOD_CURRENT, 1, bars, high); CopyLow(_Symbol, PERIOD_CURRENT, 1, bars, low); CopyBuffer(priceATRHandle, 0, 1, 1, atr); // Get ATR for shift 1 for (int i = 0; i < bars; i++) rangeSum += high[i] - low[i]; double avgRange = rangeSum / bars; return (avgRange < threshold * atr[0]); } //+------------------------------------------------------------------+ //| Bollinger Bands Squeeze Detection | //+------------------------------------------------------------------+ bool IsBollingerSqueeze(int period, double threshold) { double upper[], lower[], middle[]; ArraySetAsSeries(upper, true); ArraySetAsSeries(lower, true); ArraySetAsSeries(middle, true); CopyBuffer(bollingerHandle, 0, 0, 3, middle); // Middle band CopyBuffer(bollingerHandle, 1, 0, 3, upper); // Upper band CopyBuffer(bollingerHandle, 2, 0, 3, lower); // Lower band double bandwidth = (upper[1] - lower[1]) / middle[1]; return (bandwidth < threshold); } //+------------------------------------------------------------------+ //| ATR Crossover Consolidation Detection | //+------------------------------------------------------------------+ bool IsATRConsolidation(int fastPeriod, int slowPeriod) { double fastATR[], slowATR[]; ArraySetAsSeries(fastATR, true); ArraySetAsSeries(slowATR, true); CopyBuffer(fastATRHandle, 0, 1, 1, fastATR); // Fast ATR for shift 1 CopyBuffer(slowATRHandle, 0, 1, 1, slowATR); // Slow ATR for shift 1 return (fastATR[0] < slowATR[0]); } //+------------------------------------------------------------------+ //| Volume Analysis Consolidation Detection | //+------------------------------------------------------------------+ bool IsVolumeConsolidation(int bars, double threshold) { double volume[]; ArraySetAsSeries(volume, true); CopyBuffer(iVolume(_Symbol, PERIOD_CURRENT, 0), 0, 0, bars, volume); double avgVolume = 0.0; for (int i = 0; i < bars; i++) avgVolume += volume[i]; avgVolume /= bars; double currentVolume = volume[1]; return (currentVolume < threshold * avgVolume); } //+------------------------------------------------------------------+ //| Draw Consolidation Zone on Chart | //+------------------------------------------------------------------+ void DrawConsolidationZone(double high, double low, datetime start, datetime end) { string objName = "Consolidation_" + TimeToString(start); ObjectCreate(0, objName, OBJ_RECTANGLE, 0, start, high, end, low); ObjectSetInteger(0, objName, OBJPROP_COLOR, ZoneColor); ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, objName, OBJPROP_FILL, true); ObjectSetInteger(0, objName, OBJPROP_BACK, true); }