MT5 (MQL5) Pro Implementation
This version enforces strict memory management, checks if the HTF series is synchronized before calculating, and introduces a 4-state output (Bullish, Bearish, Chop, Exhausted).
Code: Select all
//+------------------------------------------------------------------+
//| PRO_HTF_Regime_Bias.mq5 |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots 1
#property indicator_type1 DRAW_COLOR_HISTOGRAM
#property indicator_color1 clrTeal, clrMaroon, clrGray, clrGoldenrod
#property indicator_style1 STYLE_SOLID
#property indicator_width1 4
// --- Input Parameters ---
input group "Regime Parameters"
input ENUM_TIMEFRAMES InpHTF = PERIOD_D1; // Higher Timeframe
input ENUM_MA_METHOD InpMAType = MODE_EMA; // MA Type
input int InpMAPeriod = 20; // MA Period
input group "Volatility Bands"
input int InpATRPeriod = 14; // ATR Period
input double InpATRNeutral = 0.5; // Chop Zone Multiplier (e.g. 0.5)
input double InpATRExhaustion = 2.5; // Exhaustion Multiplier (e.g. 2.5)
// --- Global Variables ---
double BufferHist[];
double BufferColors[];
int handle_ma;
int handle_atr;
int OnInit() {
SetIndexBuffer(0, BufferHist, INDICATOR_DATA);
SetIndexBuffer(1, BufferColors, INDICATOR_COLOR_INDEX);
IndicatorSetString(INDICATOR_SHORTNAME, "Pro Regime Bias");
IndicatorSetInteger(INDICATOR_DIGITS, 0);
handle_ma = iMA(_Symbol, InpHTF, InpMAPeriod, 0, InpMAType, PRICE_CLOSE);
handle_atr = iATR(_Symbol, InpHTF, InpATRPeriod);
if(handle_ma == INVALID_HANDLE || handle_atr == INVALID_HANDLE) {
Print("CRITICAL ERROR: Failed to acquire indicator handles.");
return INIT_FAILED;
}
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[]) {
// 1. Check if HTF data is physically synchronized with the server
if (!SeriesInfoInteger(_Symbol, InpHTF, SERIES_SYNCHRONIZED)) {
return 0; // Return 0 forces MT5 to recalculate on the next tick once data arrives
}
int limit = prev_calculated == 0 ? 0 : prev_calculated - 1;
// Arrays for copying HTF data
double ma_arr[1], atr_arr[1], htf_close[1];
for(int i = limit; i < rates_total && !IsStopped(); i++) {
int htf_shift = iBarShift(_Symbol, InpHTF, time[i], false);
int target_shift = htf_shift + 1; // Lock to last closed bar to prevent repainting
// 2. Safely copy data; if unavailable, skip and leave blank to avoid false signals
if(CopyBuffer(handle_ma, 0, target_shift, 1, ma_arr) <= 0) continue;
if(CopyBuffer(handle_atr, 0, target_shift, 1, atr_arr) <= 0) continue;
if(CopyClose(_Symbol, InpHTF, target_shift, 1, htf_close) <= 0) continue;
double ma_val = ma_arr[0];
double atr_val = atr_arr[0];
double htf_c = htf_close[0];
// 3. Define Volatility Bands
double upper_chop = ma_val + (atr_val * InpATRNeutral);
double lower_chop = ma_val - (atr_val * InpATRNeutral);
double upper_exhaust = ma_val + (atr_val * InpATRExhaustion);
double lower_exhaust = ma_val - (atr_val * InpATRExhaustion);
BufferHist[i] = 1.0;
// 4. Regime Logic Mapping
if(htf_c > upper_exhaust || htf_c < lower_exhaust) {
BufferColors[i] = 3; // clrGoldenrod: Exhausted (High risk of liquidity sweep)
}
else if(htf_c > upper_chop) {
BufferColors[i] = 0; // clrTeal: Safe Bullish Trend
}
else if(htf_c < lower_chop) {
BufferColors[i] = 1; // clrMaroon: Safe Bearish Trend
}
else {
BufferColors[i] = 2; // clrGray: Neutral / Chop Zone
}
}
return rates_total;
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.