Unlike TradingView (which converts timezones automatically via IANA strings), MetaTrader 4 and MetaTrader 5 calculate all intraday bar times according to your broker's server time (typically UTC+2 or UTC+3). When setting the event window in the scripts below, input the hour and minute corresponding to your broker’s server clock.
MQL5 Implementation (EventStressProxy.mq5)
Save this file in your terminal's MQL5/Indicators/ directory and compile it via MetaEditor.
Code: Select all
//+------------------------------------------------------------------+
//| EventStressProxy.mq5 |
//| Liquidity Vacuum & Execution Proxy |
//+------------------------------------------------------------------+
#property copyright "Trading Risk & Liquidity Proxy"
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_label1 "Slippage Danger"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrRed
#property indicator_width1 2
//--- Inputs
input group "=== Event Window (Broker Server Time) ==="
input int InpStartHour = 15; // Window Start Hour (e.g. 15 for 15:25)
input int InpStartMinute = 25; // Window Start Minute
input int InpEndHour = 15; // Window End Hour (e.g. 15 for 15:45)
input int InpEndMinute = 45; // Window End Minute
input group "=== Volatility Stress Parameters ==="
input int InpAtrPeriod = 14; // Baseline ATR Period
input double InpStressMult = 2.5; // Stress Multiplier (Bar Range vs ATR)
input bool InpDrawZones = true; // Draw Event Background Zones
input color InpZoneColor = clrMistyRose; // Zone Shading Color
input bool InpSendAlerts = true; // Enable Terminal Alerts
//--- Buffers & Handles
double StressBuffer[];
int atrHandle;
datetime lastAlertTime = 0;
const string PREFIX = "EventStress_";
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
SetIndexBuffer(0, StressBuffer, INDICATOR_DATA);
PlotIndexSetInteger(0, PLOT_ARROW, 251); // Wingdings cross / X mark
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
atrHandle = iATR(_Symbol, _Period, InpAtrPeriod);
if(atrHandle == INVALID_HANDLE)
{
Print("Failed to create ATR handle.");
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, PREFIX);
ChartRedraw(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration 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[])
{
if(rates_total < InpAtrPeriod + 1) return(0);
int limit = prev_calculated > 0 ? prev_calculated - 1 : InpAtrPeriod;
double atrValues[];
ArraySetAsSeries(atrValues, false);
if(CopyBuffer(atrHandle, 0, 0, rates_total, atrValues) <= 0) return(0);
MqlDateTime dt;
for(int i = limit; i < rates_total; i++)
{
StressBuffer[i] = 0.0;
TimeToStruct(time[i], dt);
int currentMins = dt.hour * 60 + dt.min;
int startMins = InpStartHour * 60 + InpStartMinute;
int endMins = InpEndHour * 60 + InpEndMinute;
bool inEventWindow = (currentMins >= startMins && currentMins <= endMins);
// Draw background shading zone per day during event window
if(InpDrawZones && inEventWindow)
{
string objName = PREFIX + TimeToString(time[i], TIME_DATE) + "_" + IntegerToString(startMins);
if(ObjectFind(0, objName) < 0)
{
datetime zoneStart = time[i];
datetime zoneEnd = zoneStart + ((endMins - startMins) * 60);
ObjectCreate(0, objName, OBJ_RECTANGLE, 0, zoneStart, 0, zoneEnd, 0);
ObjectSetInteger(0, objName, OBJPROP_COLOR, InpZoneColor);
ObjectSetInteger(0, objName, OBJPROP_FILL, true);
ObjectSetInteger(0, objName, OBJPROP_BACK, true);
ObjectSetDouble(0, objName, OBJPROP_PRICE, 0, 0);
ObjectSetDouble(0, objName, OBJPROP_PRICE, 1, 200000);
}
}
// Check volatility stress ratio
double barRange = high[i] - low[i];
double baselineAtr = atrValues[i];
if(inEventWindow && (barRange > (baselineAtr * InpStressMult)))
{
StressBuffer[i] = high[i] + (baselineAtr * 0.5);
// Terminal Alert for the live forming bar
if(InpSendAlerts && i == rates_total - 1 && time[i] != lastAlertTime)
{
Alert(StringFormat("[%s] Slippage Danger: High volatility detected inside Tier-1 Event window!", _Symbol));
lastAlertTime = time[i];
}
}
}
return(rates_total);
}