MQL4 runtime lifecycle

MQL4 event handlers by program type

The MT4 runtime recognizes an event handler by its exact name, return type, and parameters. Expert Advisors use OnInit, OnDeinit, OnTick, and optionally OnTimer; scripts use OnStart; custom indicators use OnCalculate and can also use timer and chart events.

Open the Coding Agent, then choose MQL4 from the language menu.

EventLifecycleEA.mq4.mq4
#property strict

input int TimerSeconds = 5;

int OnInit()
  {
   if(TimerSeconds < 1)
      return(INIT_PARAMETERS_INCORRECT);

   if(!EventSetTimer(TimerSeconds))
     {
      Print("EventSetTimer failed. Error ", GetLastError());
      return(INIT_FAILED);
     }

   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   EventKillTimer();
   Print("Deinitialized. Reason ", reason);
  }

void OnTick()
  {
   Print("New tick at ", TimeToString(TimeCurrent(), TIME_SECONDS));
  }

void OnTimer()
  {
   Print("Timer event at ", TimeToString(TimeCurrent(), TIME_SECONDS));
  }
  • Handler signatures must match exactly
  • OnTick belongs to Expert Advisors
  • OnStart belongs to scripts
  • Release timers in OnDeinit

Program type determines available events

The terminal generates NewTick events only for Expert Advisors. A function named OnTick inside a script or custom indicator does not turn that program into an EA. Scripts receive Start and custom indicators receive Calculate events.

Initialization and deinitialization handlers describe lifecycle boundaries. They are the right places to validate inputs, allocate or release resources, subscribe to timers, and explain why the program stopped.

HandlerProgram typeEvent
OnStartScriptOne script run
OnTickExpert AdvisorNew quote for the chart symbol
OnCalculateCustom indicatorIndicator calculation
OnTimerEA or indicatorSubscribed timer interval

Return values control initialization

An int OnInit can return ENUM_INIT_RETCODE values. With strict compilation, a nonzero initialization result signals failure and triggers deinitialization. This lets invalid inputs stop before trading or indicator calculation begins.

OnDeinit must use the documented void signature with one const int reason parameter. A different return type or parameter list is not a valid handler even if the function name looks correct.

  • Validate parameters before subscribing to events
  • Create one timer subscription per program
  • Release timer and object resources in OnDeinit
  • Keep slow network or file work away from frequent tick paths

Events are serialized per MQL4 program

A slow handler delays later work for the same program. Timer frequency is not a promise that a long-running task will execute concurrently or catch every missed interval.

Keep handlers short, store only the state they need, and make repeated events idempotent where possible. Trading actions also need guards against sending the same request on several ticks.

Review the complete example

This Expert Advisor validates its timer interval in OnInit, subscribes once, receives tick and timer events separately, and removes the timer during deinitialization.

The example does not trade. Event timing, terminal shutdown, reconnects, and duplicate-action guards still require runtime tests.

EventLifecycleEA.mq4.mq4
#property strict

input int TimerSeconds = 5;

int OnInit()
  {
   if(TimerSeconds < 1)
      return(INIT_PARAMETERS_INCORRECT);

   if(!EventSetTimer(TimerSeconds))
     {
      Print("EventSetTimer failed. Error ", GetLastError());
      return(INIT_FAILED);
     }

   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   EventKillTimer();
   Print("Deinitialized. Reason ", reason);
  }

void OnTick()
  {
   Print("New tick at ", TimeToString(TimeCurrent(), TIME_SECONDS));
  }

void OnTimer()
  {
   Print("Timer event at ", TimeToString(TimeCurrent(), TIME_SECONDS));
  }
Where Pineify fits

Move from the rule to editable MQL4 source

Pineify can generate or revise one self-contained .mq4 file with MQL4-specific reference context. Its independent static checker returns MetaEditor diagnostics so you can repair source issues before testing in your own MT4 environment.

Open MQL4 Coding Agent

Static diagnostics do not prove runtime behavior, backtest results, broker compatibility, or live-trading safety.

Pineify MQL4 Coding Agent with MQL4 selected and an editable MetaTrader 4 code artifact

A practical workflow

  1. 1

    Choose the program type

    Map the requirement to an EA, script, or custom indicator.

  2. 2

    Copy the exact signature

    Use the documented return type and parameters for each required event.

  3. 3

    Own the lifecycle

    Allocate and subscribe in OnInit, then release the same resources in OnDeinit.

  4. 4

    Test event timing

    Compile and observe tick, timer, chart, and shutdown behavior in the target terminal.

Frequently asked questions

Why is OnTick not running in my MQL4 indicator?

NewTick events are generated for Expert Advisors, not custom indicators or scripts.

Can an MQL4 script use OnInit?

A script can initialize through OnInit, but its main execution event is OnStart.

What should OnInit return?

An int OnInit commonly returns INIT_SUCCEEDED, INIT_FAILED, or INIT_PARAMETERS_INCORRECT. The effect of nonzero results is defined for strict compilation.

Do I need EventKillTimer?

Yes. A program that subscribed with EventSetTimer should remove that timer in OnDeinit.

Can OnTimer replace OnTick?

It can schedule periodic work, but it is a different event source and does not provide one callback for each market tick.

Last verified against the linked official references on . Compile and test the final source in the MetaTrader 4 build, broker, symbol, and account environment you plan to use.

Continue with one reviewable MQL4 file

Define the requirement, inspect the generated source, repair diagnostics, and test the behavior in your own MT4 environment.

Open Coding Agent