//+------------------------------------------------------------------+ //| OrderBlockDetector.mq5 | //| Copyright 2023, Your Name | //| https://www.mql5.com/en/users/yourusername | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, Your Name" #property link "https://www.mql5.com/en/users/yourusername" #property version "1.00" #property indicator_chart_window #property indicator_buffers 2 #property indicator_plots 2 //--- Indicator buffers // double UpBuffer[]; #property indicator_label1 "Up" #property indicator_type1 DRAW_ARROW #property indicator_color1 clrAqua #property indicator_width1 1 // double DownBuffer[]; #property indicator_label2 "Down" #property indicator_type2 DRAW_ARROW #property indicator_color2 clrMagenta #property indicator_width2 1 //--- Input parameters input int VolumeThreshold = 100; // Minimum volume to consider a block valid input int BlockSize = 20; // Number of bars in a block input double PriceChangeThreshold = 0.01; // Minimum price change percentage //+------------------------------------------------------------------+ //| Initialization function | //+------------------------------------------------------------------+ int OnInit() { // SetIndexBuffer(0, UpBuffer, INDICATOR_DATA); // PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0); PlotIndexSetInteger(0, PLOT_ARROW, 159); // SetIndexBuffer(1, DownBuffer, INDICATOR_DATA); // PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, 0); PlotIndexSetInteger(1, PLOT_ARROW, 159); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { // Clean up resources if necessary } //+------------------------------------------------------------------+ //| Calculation function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // Initialize buffers ArrayInitialize(UpBuffer, EMPTY_VALUE); ArrayInitialize(DownBuffer, EMPTY_VALUE); // Define the starting point for calculations int limit = MathMin(rates_total - prev_calculated, rates_total - BlockSize); // Loop through bars to detect valid order blocks for (int i = 0; i < limit; i++) { bool isUpBlock = false; bool isDownBlock = false; // Check volume in the block double totalVolume = 0; double startPrice = open[i]; double endPrice = close[i + BlockSize - 1]; // Calculate total volume for the block for (int j = 0; j < BlockSize && i + j < rates_total; j++) { totalVolume += (double)tick_volume[i + j]; } // Check if the block meets the volume threshold if (totalVolume >= VolumeThreshold) { // // Calculate price change percentage double priceChange = MathAbs((endPrice - startPrice) / startPrice) * 100; if (priceChange >= PriceChangeThreshold) { // if (endPrice > startPrice) isUpBlock = true; else if (endPrice < startPrice) isDownBlock = true; } } // Mark the block as valid if (isUpBlock) { UpBuffer[i] = high[i]; DownBuffer[i] = EMPTY_VALUE; } else if (isDownBlock) { DownBuffer[i] = low[i]; UpBuffer[i] = EMPTY_VALUE; } } return(rates_total); } //+------------------------------------------------------------------+