I’m facing a practical issue in MetaTrader (MQL4/MQL5) and I’d like to hear how others handle this.
I’ve built a custom indicator engine as a class, designed to be reused both in Indicators and Experts.
In normal conditions everything works fine:
- Live market → correct results
- New candles → correct updates
- Internet gaps → handled correctly
- Fresh load → correct output
So the class itself is stable and well tested.
The problem
When MetaTrader is running and the operating system goes to standby / sleep, then later resumes:
- OnInit / OnDeinit are NOT called (expected behavior)
- After resume, the class continues working as if nothing happened
- But internally it looks like calculations are done on incomplete or unstable data
- As a result, many indicators (not only ZigZag, actually most of them) produce incorrect output
- Changing the timeframe resets everything and the output becomes correct again
So clearly, after system resume, the code does not properly detect that a time gap or environment break happened.
Why this is a real issue
For indicators, a timeframe change is a temporary workaround.
But for Experts, this is dangerous:
- The visual mess is not obvious
- The EA continues trading based on wrong indicator output
- If the output is wrong, the trading logic becomes unreliable
Key limitation
Because the logic is inside a reusable class (used by both Indicator and EA):
- We do not have access to
rates_total / prev_calculated - So we can’t rely on the usual indicator lifecycle logic
- The class only receives price data and processes it
The question
What is the correct and scalable way to handle this?
Some ideas I’m considering, but none feel fully right:
- Detect OS resume indirectly (time jump) and force a full rebuild
- Use different calculation behavior when used in Indicator vs Expert
- Recalculate the full window on every new candle in EA mode
- Or something else entirely?
The concern is performance:
- Multi-symbol
- Multi-timeframe
- Many indicators
- Running inside Experts
A brute-force full rebuild on every candle doesn’t seem scalable.
Has anyone dealt with this kind of issue?
Any practical patterns or proven approaches would be really appreciated.
ex code:
#include <FxArt.Trader\CFxIndicators\CFxA_ZigZag.mqh>
CFxA_ZigZag cZ;
#include <FxArt.Trader\CFxCandlesData\CFxCandlesData.mqh>
CFxCandlesData cData;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
cData.Init(_Symbol,PERIOD_CURRENT);
cZ.Init(InpDepth,InpDeviation,InpBackstep,PERIOD_CURRENT,true,_Point);
//--- indicator buffers mapping
SetIndexBuffer(0,cZ.ZigzagPeakBuffer,INDICATOR_DATA);
SetIndexBuffer(1,cZ.ZigzagBottomBuffer,INDICATOR_DATA);
SetIndexBuffer(2,cZ.ColorBuffer,INDICATOR_COLOR_INDEX);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
cZ.OnDestroy();
cData.OnDestroy();
}
//+------------------------------------------------------------------+
//| ZigZag calculation |
//+------------------------------------------------------------------+
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[])
{
int BarsMax = rates_total;
datetime now = CFxA_IndicatorCalculationTime();
cData.Set(BarsMax);
cData.GetHigh(now);
cData.GetLow(now);
cZ.PrepareCalculation(now, BarsMax, cData.High, cData.Low);
//--- return value of prev_calculated for next call
return(rates_total);
} Thanks in advance.