OnInit, OnTick, OnDeinit, OnCalculate — MQL5 does not run top to bottom. It waits for events.
Beginner7 min readBeginner → AdvancedLesson 02 / 17
Try it in MetaEditor
An EA skeleton that prints its own lifecycle
Save as MQL5/Experts/Lesson2Skeleton.mq5. Attach it to a chart, then change timeframes, remove it, and recompile — watch how the OnDeinit reason code changes.
//+------------------------------------------------------------------+
//| Lesson 2 - EA lifecycle: OnInit / OnTick / OnDeinit |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version "1.00"
int OnInit()
{
Print("OnInit: attached to ", _Symbol, " on ", EnumToString((ENUM_TIMEFRAMES)_Period));
Print("Digits = ", _Digits, " Point = ", DoubleToString(_Point, _Digits));
Print("Bars available = ", Bars(_Symbol, _Period));
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
// 0 = removed from chart, 1 = recompiled, 2 = symbol/timeframe changed,
// 3 = chart closed, 4 = terminal shutdown, 5 = account changed, ...
Print("OnDeinit. Reason code: ", reason);
}
void OnTick()
{
static int tickCount = 0;
tickCount++;
// Print every 200 ticks so the log stays readable.
if(tickCount % 200 == 0)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
Print("Ticks seen: ", tickCount,
" bid = ", DoubleToString(bid, _Digits),
" time = ", TimeToString(TimeCurrent(), TIME_SECONDS));
}
}
To run it
1. Open MetaEditor from MT5 (press F4), and pick the folder this program belongs in — Experts, Indicators, or Scripts.
2. Create a new file, paste this over it, then press F7 to compile. Fix anything the Errors tab reports.
3. Back in MT5, drag it onto a chart — or open the Strategy Tester if it is an Expert Advisor.
Terminal drives you, not the other way round
A Pine script re-executes on every bar and the runtime figures out the rest. MQL5 inverts this: the terminal calls specific functions when specific things happen. If you put logic outside those functions, it never runs.
OnInit() — once, when the program is attached or the terminal starts. Create indicator handles here. Return INIT_SUCCEEDED or INIT_FAILED.
OnTick() — every price tick (EAs only).
OnCalculate() — on data change (indicators only).
OnDeinit(reason) — on removal. Release handles and kill timers here.
OnStart() — once, for scripts.
Why OnDeinit is not optional
Every indicator handle you create consumes memory until you release it. In backtests the terminal creates and destroys your EA thousands of times; leak a handle each time and the tester slows to a crawl or dies. Treat OnInit and OnDeinit as a matched pair — whatever you create in one, destroy in the other.
Predefined variables you will use constantly
_Symbol — the symbol the program is attached to, as a string.
_Period — the chart timeframe, as an ENUM_TIMEFRAMES.
_Digits — decimal places for the symbol. Always normalise prices to this.
_Point — the smallest price increment (one point). Not necessarily one tick — see Part 3.
What to watch in this lesson
Attach this EA to a chart and watch the Experts tab. Ticks arrive far more often than bars — on a liquid CFD during London you may see dozens per second. That is why EAs almost always gate their logic on "new bar" rather than acting on every tick. You will build that gate in Part 3.
What you just did
Lesson 02 of 17 in MetaTrader 5 MQL5 for CFD Traders. When you have run the examples or read the section, tick it off and move to the next lesson.