Place this in MQL5\Indicators. MQL5 handles arrays differently, so this implementation forces ArraySetAsSeries and uses CopyBuffer to pull indicator handles smoothly without memory leaks.
Code: Select all
//+------------------------------------------------------------------+
//| Liquidity_Sweep_Risk_MT5.mq5 |
//+------------------------------------------------------------------+
#property copyright "Execution Risk Mapping"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 4
#property indicator_label1 "Upper Risk Band"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDarkGray
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
#property indicator_label2 "Lower Risk Band"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrDarkGray
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
#property indicator_label3 "Bull Sweep Risk"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrRed
#property indicator_label4 "Bear Sweep Risk"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrRed
input int InpLength = 20; // ATR & SMA Lookback
input double InpSlipMultiplier = 1.5; // Slippage Risk Multiplier
input bool InpEnableAlerts = true; // Enable Terminal Alerts
double BufferUpper[];
double BufferLower[];
double BufferBullSweep[];
double BufferBearSweep[];
int handle_atr;
int handle_sma;
datetime lastAlertTime;
int OnInit() {
SetIndexBuffer(0, BufferUpper, INDICATOR_DATA);
SetIndexBuffer(1, BufferLower, INDICATOR_DATA);
SetIndexBuffer(2, BufferBullSweep, INDICATOR_DATA);
SetIndexBuffer(3, BufferBearSweep, INDICATOR_DATA);
PlotIndexSetInteger(2, PLOT_ARROW, 233);
PlotIndexSetInteger(3, PLOT_ARROW, 234);
ArraySetAsSeries(BufferUpper, true);
ArraySetAsSeries(BufferLower, true);
ArraySetAsSeries(BufferBullSweep, true);
ArraySetAsSeries(BufferBearSweep, true);
handle_atr = iATR(_Symbol, _Period, InpLength);
handle_sma = iMA(_Symbol, _Period, InpLength, 0, MODE_SMA, PRICE_CLOSE);
if (handle_atr == INVALID_HANDLE || handle_sma == INVALID_HANDLE) {
Print("Failed to load indicator handles");
return(INIT_FAILED);
}
IndicatorSetString(INDICATOR_SHORTNAME, "Execution Risk Band");
return(INIT_SUCCEEDED);
}
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[]) {
if(rates_total < InpLength + 1) return(0);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(time, true);
int limit = rates_total - prev_calculated;
if(prev_calculated > 0) limit++;
if(limit >= rates_total) limit = rates_total - 1;
double atrArray[], smaArray[];
ArraySetAsSeries(atrArray, true);
ArraySetAsSeries(smaArray, true);
if (CopyBuffer(handle_atr, 0, 0, limit + 1, atrArray) <= 0) return(0);
if (CopyBuffer(handle_sma, 0, 0, limit + 1, smaArray) <= 0) return(0);
for (int i = limit; i >= 0 && !IsStopped(); i--) {
BufferBullSweep[i] = EMPTY_VALUE;
BufferBearSweep[i] = EMPTY_VALUE;
BufferUpper[i] = smaArray[i] + (atrArray[i] * InpSlipMultiplier);
BufferLower[i] = smaArray[i] - (atrArray[i] * InpSlipMultiplier);
if (i + InpLength < rates_total && i >= 0) {
int lowestIdx = ArrayMinimum(low, i + 1, InpLength);
int highestIdx = ArrayMaximum(high, i + 1, InpLength);
bool bullSweep = (low[i] < low[lowestIdx]) && (close[i] > open[i]);
bool bearSweep = (high[i] > high[highestIdx]) && (close[i] < open[i]);
if (bullSweep) BufferBullSweep[i] = low[i] - (atrArray[i] * 0.5);
if (bearSweep) BufferBearSweep[i] = high[i] + (atrArray[i] * 0.5);
if (i == 0 && InpEnableAlerts && (bullSweep || bearSweep) && time[0] != lastAlertTime) {
Alert("Liquidity Sweep Detected on ", _Symbol, " - LP withdrawal imminent.");
lastAlertTime = time[0];
}
}
}
return(rates_total);
}