131 lines
8.7 KiB
Plaintext
131 lines
8.7 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| 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);
|
|
}
|
|
//+------------------------------------------------------------------+ |