Understanding event driven programming on tick in expert advisor
In algorithmic trading, your Expert Advisor (EA) lives and breathes through events. Among those events, the arrival of a new market tick is one of the most important. This is why event driven programming on tick in expert advisor design is such a powerful concept. Instead of constantly looping and checking prices, your EA simply waits for the server to inform it that “something changed” — a new tick came in — and then reacts instantly.
In MetaTrader platforms (MT4 and MT5), this behavior is implemented with the OnTick() function. Every time the broker sends a price update for the symbol where the EA is attached, OnTick() is called. Inside this function, you decide what your EA will do: update indicators, check entry rules, modify stops, or close positions. Thinking of your EA as a system that reacts to ticks instead of one that constantly polls the market makes your design more efficient, cleaner, and easier to maintain.
When you understand this event-driven model, you also start thinking in terms of what should happen when a tick arrives instead of just “what is the current price.” That mental shift is what separates quick experimental scripts from robust professional-grade trading robots.
What Is Event-Driven Programming in Trading Platforms?
Event-driven programming is a style where your code reacts to events rather than running in a continuous, manual loop. In trading platforms, these events usually come from the market or from the platform itself. Typical events include:
- A new tick arrives for a symbol
- A timer fires after a certain number of seconds
- A trade is opened, modified, or closed
- The EA is initialized or removed from the chart
From procedural scripts to reactive EAs
In a simple procedural script, you might write a for loop that cycles through data, calculates something, and then exits. That’s fine for one-time tasks. But markets are continuous; they don’t stop. If you tried to loop forever inside an EA, you’d freeze the terminal.
Event-driven EAs remove this problem. The trading platform is responsible for waiting and listening to the server. When something interesting happens, it calls your event handler, such as OnInit(), OnTick(), or OnDeinit().
Core idea: reacting to market and platform events
The core idea is: Don’t pull; let the platform push.
You don’t ask the market “Do we have a new price?” thousands of times per second. Instead, the platform says “Here’s a new price,” and your EA reacts.
This changes the way you design logic. You split your code into parts:
- Initialization logic (runs once when EA starts)
- Per-tick logic (runs every time a tick arrives)
- Cleanup logic (runs when EA stops)
The Role of the OnTick Event in MetaTrader Expert Advisors
OnTick() is the heart of real-time trading decisions. It gets called automatically each time the price for the chart symbol updates.
How OnTick works under the hood in MT4 and MT5
In MT4 and MT5, the trading server streams quotes to your terminal. Each quote is a tick: a combination of bid, ask, and possibly volume information. When a tick for the symbol hits your terminal, MetaTrader:
- Updates the chart data
- Calls the
OnTick()function for every EA attached to that symbol’s chart
Inside OnTick(), you can:
- Read
Bid,Ask,SymbolInfoDouble(), oriClose()for indicator values - Evaluate your trade entry or exit rules
- Send trade orders or modify existing ones
For reference, the official MetaQuotes documentation explains the event-handling model and OnTick() function details.
(Note: For a deeper dive into the latest official docs, you can search “MetaTrader MQL4 OnTick reference” on the MetaQuotes site.)
Difference between OnTick, OnTimer, and other events
- OnTick: Triggered when a new tick arrives. Perfect for tick-based logic and scalping.
- OnTimer: Triggered at fixed time intervals (e.g., every second or every minute). Great for scheduled checks.
- OnChartEvent: Triggered by UI actions such as mouse clicks or key presses on the chart.
- OnInit / OnDeinit: Triggered when the EA is loaded or removed.
You often combine OnTick with OnTimer to balance responsiveness and CPU usage.
When ticks really arrive: liquidity, spreads, and brokers
Ticks don’t arrive at perfectly regular intervals. Their frequency depends on:
- Market liquidity
- Time of day (session open vs quiet hours)
- Broker’s quote feed
During high volatility, OnTick() can fire many times per second. During low liquidity, you might wait several seconds or more between ticks. Your EA logic must handle both extremes gracefully.
Setting Up a Basic Expert Advisor with OnTick Logic
Project structure: initialization, tick handling, and deinitialization
A typical EA structure in MQL4/MQL5 looks like this:
int OnInit()
{
// Load settings, indicators, and variables
return(INIT_SUCCEEDED);
}
void OnTick()
{
// Main trading logic triggered on every tick
}
void OnDeinit(const int reason)
{
// Cleanup resources
}
You might also add a OnTimer() function if you want periodic tasks.
A simple moving average OnTick example
Let’s imagine a basic strategy:
- Buy when fast MA crosses above slow MA
- Sell when fast MA crosses below slow MA
On every tick, you’ll:
- Get the latest values of fast and slow moving averages
- Check whether a crossover just happened
- Check if there’s already a position
- Open a new trade or modify an existing one
Pseudocode walkthrough for beginners
Here’s a simplified pseudocode:
OnTick:
read fastMA and slowMA for current and previous bar
if no open trades:
if fastMA crosses above slowMA:
open Buy
else if fastMA crosses below slowMA:
open Sell
else:
manage existing trade:
move stop loss
close trade if target hit or condition met
This is a classic example of event-driven logic: You only act when a tick forces the code to run.
Designing an Event-Driven Architecture Inside Your EA
Separating input, decision, and execution layers
A clean EA design separates:
- Input layer – Reads prices, indicators, account data.
- Decision layer – Applies rules to decide whether to buy, sell, hold, or modify orders.
- Execution layer – Sends trade orders, sets stop loss/take profit, and logs actions.
You can implement this using separate functions:
void OnTick()
{
UpdateMarketData();
TradeSignal signal = MakeDecision();
ExecuteSignal(signal);
}
This separation makes your EA easier to test and maintain.
Using state machines for trade management
A state machine tracks where your strategy is in its life cycle. Example states:
STATE_WAITING_FOR_ENTRYSTATE_POSITION_OPENSTATE_TRAIL_STOPSTATE_EXITING
On every tick, the EA:
- Reads the current state
- Checks conditions
- Moves to a new state if needed
This prevents messy “spaghetti code” with lots of nested if statements.
Handling multiple symbols and timeframes from one OnTick
Even though OnTick() is tied to one chart symbol, your logic can:
- Read prices from other symbols with functions like
iClose()orSymbolInfoTick() - Use different timeframes (M1, M15, H1, etc.) inside the same EA
However, you must be careful with performance. Reading heavy indicators for many symbols each tick can slow down your terminal.
Efficient Data Handling on Every Tick
Caching indicators and prices to avoid recalculation overload
Recalculating indicators on every tick from scratch is expensive. Techniques to improve efficiency:
- Only recalc when a new bar appears, not on every tick.
- Cache indicator handles or arrays so you don’t rebuild them.
- Use static variables to remember previous values across ticks.
Debouncing ticks and checking for new bars
A common trick is to detect when a new candle opens:
static datetime lastBarTime;
datetime currentBarTime = iTime(Symbol(), PERIOD_CURRENT, 0);
if (currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
// New bar logic here
}
With this pattern, you can:
- Run heavy calculations once per bar
- Still use
OnTick()for real-time trade execution and management
Memory management and performance considerations
- Avoid large dynamic arrays that grow without limit.
- Release indicator handles in
OnDeinit(). - Keep loops small and simple within
OnTick().
This keeps your EA responsive, even in fast markets.
Risk Management in an OnTick-Driven EA
Position sizing logic triggered on tick events
Your lot size often depends on:
- Account balance or equity
- Risk-per-trade percentage
- Stop-loss distance in pips
On each tick, when you detect an entry signal, you can compute the appropriate lot size just before sending the order.
Spread, slippage, and volatility filters in real time
Event-driven EAs can quickly react to changing market conditions:
- Check current spread and skip trades if it’s too wide.
- Watch volatility and avoid entries near big news events.
- Limit slippage by using
slippageparameters or by validating fills.
Safeguards: maximum loss, trade limits, and emergency stops
Your OnTick() logic should also guard against disaster:
- Stop trading when daily or weekly loss exceeds a limit.
- Limit the number of open trades per symbol or per direction.
- Implement an “emergency close” if the account equity drops too low.
Testing and Debugging OnTick Logic
Using the Strategy Tester to simulate ticks
Backtesting lets you see how your OnTick() logic behaves with historical data. You can:
- Choose different modeling types (e.g., “Every tick” vs “Open prices only”)
- Run through months of data in minutes
- Visualize trades on the chart to check timing and logic
Logging, alerts, and commented messages for debugging
Within OnTick(), log important information:
Print("New tick: Bid=", Bid, " Ask=", Ask, " Time=", TimeCurrent());
Use Comment() to display real-time info on the chart. During development, add temporary logs for:
- Signals triggered
- Orders sent or rejected
- State changes in your strategy
Common OnTick pitfalls and how to avoid them
Common mistakes include:
- Opening multiple trades on a single signal because you don’t check for existing positions.
- Using heavy loops that freeze the terminal in fast markets.
- Ignoring spread or slippage, leading to poor execution.
A disciplined event-driven design helps you sidestep these issues.
Advanced Patterns for event driven programming on tick in expert advisor
Event queues and internal message passing
Inside one EA, you can emulate a mini-event system:
- Producer functions detect certain conditions and push “messages” into a queue (e.g., “ENTRY_BUY”, “EXIT_SELL”).
- Consumer functions read messages from the queue and execute trading actions.
This pattern keeps your OnTick() body small and clear.
Combining OnTick with timers for hybrid control
Using OnTimer() alongside OnTick() lets you:
- Perform heavy analytics or logging every X seconds in
OnTimer() - Keep
OnTick()light, focusing on trade execution and quick checks
This hybrid model balances performance and responsiveness.
Modularizing code with classes and libraries
You can package:
- Order-handling routines into a trading class
- Indicator calculations into helper functions
- Risk management rules into a separate module
This modularity makes large EAs more maintainable and reusable.
Real-World Use Cases of OnTick-Based Expert Advisors
Scalping systems that rely on every micro-movement
Scalpers often trade on M1 or even tick-based logic. For them, every incoming tick is a potential opportunity. Their OnTick() functions:
- Constantly monitor spread and liquidity
- Enter and exit trades quickly to capture a few pips
- Use tight stop losses and careful position sizing
Swing trading EAs that need bar-close logic
Swing traders are more interested in candle closes than individual ticks. Their event-driven design often uses:
OnTick()only to detect new bars- Indicators and signals calculated once per bar
- Orders triggered immediately at bar open or close
Portfolio EAs monitoring multiple markets
Portfolio EAs read data from several symbols and timeframes. They use OnTick() on one chart as a central “dispatcher”:
- Pulling data from multiple symbols
- Evaluating correlation and diversification rules
- Executing trades across the portfolio
Security, Stability, and Fail-Safe Design
Handling platform restarts and disconnections
Real-world trading isn’t perfect. Your terminal might restart, or your connection may drop. A robust EA:
- Saves important state information using global variables or files
- Reconstructs its state in
OnInit()after a restart - Double-checks open orders and positions before acting
Defensive coding: validation and error handling
Defensive practices include:
- Checking the result of every trade request
- Validating symbol, lot size, and stop levels before sending orders
- Handling error codes gracefully instead of just failing silently
Keeping your EA safe from “runaway” logic
“Runaway” logic happens when your EA opens many trades or loops endlessly because of a bug. Prevent this by:
- Limiting the number of trades per time period
- Adding timeouts to certain states
- Logging unusual behaviors for review
FAQs About OnTick and Event-Driven Expert Advisors
FAQ 1 – What happens if no ticks arrive?
If no ticks arrive for a symbol, OnTick() is simply not called. Your EA appears “idle.” This often happens when:
- The market is closed (weekends, holidays)
- The symbol is illiquid or rarely traded
You can use OnTimer() to perform periodic checks during quiet times if needed.
FAQ 2 – Why are my OnTick trades delayed or skipped?
Delays or missed trades can be due to:
- High CPU load from heavy calculations inside
OnTick() - Network latency between your terminal and the broker’s server
- Broker-side execution delays
Optimizing the code and reducing unnecessary work per tick helps a lot.
FAQ 3 – How many calculations should I do per tick?
There’s no fixed number, but as a rule of thumb:
- Keep computations as light as possible.
- Run heavy indicator calculations only once per bar or on timers.
- Test performance in the Strategy Tester and in a demo account.
FAQ 4 – Can I simulate tick events in backtesting?
Yes. In MetaTrader’s Strategy Tester, use “Every tick” modeling mode to simulate tick-by-tick logic. This mode allows your OnTick() function to behave similarly to live trading, though modeling quality depends on historical tick data.
FAQ 5 – How is OnTick different from OnCalculate in indicators?
OnTick()belongs to Expert Advisors and is used for trading decisions.OnCalculate()belongs to indicators and is used to calculate indicator values on chart data.
They are both event-driven, but they apply to different types of programs.
FAQ 6 – Should I use one EA per symbol or one multi-symbol EA?
Both approaches are valid:
- One EA per symbol is simpler to design and debug.
- One multi-symbol EA centralizes logic and can coordinate a portfolio, but is more complex.
Choose based on your strategy’s complexity and your coding comfort level.
Conclusion: Building Reliable, Event-Driven Trading Systems
We’ve walked through how OnTick() functions as the heartbeat of your trading robot, why event-driven design matters, and how to structure your EA for clarity, performance, and safety. When you embrace event driven programming on tick in expert advisor design, you’re no longer just reacting to price changes in an ad-hoc way. Instead, you’re building a structured, maintainable, and professional trading system.
By separating data input, decision logic, and trade execution, you keep your EA clean and testable. By using caching, new-bar detection, and hybrid OnTick/OnTimer models, you maintain speed even in heavy markets. And by adding strong risk management, defensive coding, and fail-safes, you protect both your account and your peace of mind.