A beginner-friendly explanation of what an Expert Advisor is, how MetaTrader runs it through OnInit and OnTick, how EAs differ from indicators and scripts, what the .mq4/.mq5 and .ex4/.ex5 file types mean, and how to install one. This article is educational only and is not financial advice; automated trading involves a real risk of loss, so always use a stop-loss and test on a demo account first.
An Expert Advisor (EA) is a small program that lives inside the MetaTrader platform and can watch the market and place or manage trades for you, following rules you decide in advance. When people ask what is an expert advisor, the shortest honest answer is: it is a trading robot for MetaTrader. You write down a strategy as code once, attach it to a chart, and from then on the platform runs that logic automatically on live prices without you clicking anything.
Think of it like a very literal assistant. It never gets bored, never forgets the rules, and never "feels" like breaking them. That is its strength and also its danger. If your rules are sensible, it applies them consistently. If your rules have a hole in them, the EA will fall through that hole thousands of times without noticing. An EA does not have judgment or a sense of self-preservation. It does exactly what the code says, tick after tick.
An important myth to kill early: an EA is not a money machine, and nobody can promise you what one will earn. Anyone selling a "guaranteed profitable" robot is selling you a story. A well-built EA is simply a way to execute a defined strategy consistently. Whether that strategy makes or loses money depends on the strategy, the market, your risk settings, and factors outside your control. This guide is educational only, it is not financial advice, and automated trading carries a real risk of loss.
You do not press "go" on an EA in a loop the way you might run a normal program. Instead, MetaTrader calls specific functions in your EA when specific things happen. These are called event handlers, and for a beginner three of them cover almost everything.
Here is the smallest honest sketch of that lifecycle in MQL5. Notice it does nothing risky — it just shows when each function fires:
5
// MQL5 — the lifecycle of an EA (no trading yet, just the skeleton)
input double InpLots = 0.10; // lot size from an input, never a hidden literal
int OnInit()
{
Print("EA loaded on ", _Symbol, " ", EnumToString((ENUM_TIMEFRAMES)_Period));
return(INIT_SUCCEEDED); // tell MetaTrader setup is OK
}
void OnTick()
{
// Runs on every price update. Your logic goes here.
// We deliberately do nothing yet.
}
void OnDeinit(const int reason)
{
Print("EA removed, reason code = ", reason);
}The key mental shift for a beginner is this: you are not writing a program that runs top to bottom and stops. You are writing reactions to events. MetaTrader owns the clock. Your job is to answer clearly each time it asks "the price just moved — what now?"
MetaTrader can run three kinds of MQL programs, and beginners mix them up constantly. Knowing the difference saves you real confusion.
OnTick(), and is the only one of the three that can open, modify, and close trades automatically.A simple way to remember it: an indicator informs, a script does one chore, and an EA trades. There is also a visible platform difference. Only an EA responds to the AutoTrading (also called "Algo Trading" in MT5) button in the toolbar. If that button is off, or if "Allow Algo Trading" is unticked in the EA's settings, your EA will sit on the chart and place nothing — a very common first-day head-scratcher.
You will often use them together. An indicator paints the picture, and your EA reads the same indicator values in code to make a decision. The chart drawing and the EA's calculation are separate things, though. An EA does not "see" the arrows an indicator draws; it recalculates the numbers itself, usually through an indicator handle and a buffer copy.
When you download or write an EA you will meet four file extensions, and the distinction is simple once someone says it plainly.
.mq4 is for MetaTrader 4, .mq5 is for MetaTrader 5. You can open these in the MetaEditor and read or change them..ex4/.ex5; it is the source after it has been turned into an executable by pressing Compile in MetaEditor.The relationship is one-way. Source compiles into an executable: .mq5 → .ex5, .mq4 → .ex4. You cannot reliably turn a compiled .ex5 back into readable source, which is exactly why many commercial EAs are sold as .ex4/.ex5 only — the seller is hiding the strategy. That is worth pausing on. If you are handed only a compiled file, you cannot see what it does. You are trusting a black box with a trading account. Whenever you can, get the source so you (or someone you trust) can read the actual rules.
One dialect warning, because it trips people up: MQL4 and MQL5 are related but not interchangeable. An .mq4 file will not compile in a pure MT5 project, and code written for one platform's trading functions will not run on the other. When you look at example code, always check which platform it targets before you paste it anywhere.
Installing an EA is mostly a copy-and-refresh exercise. Here is the beginner path for MetaTrader 5 (MT4 is the same idea, just MQL4 instead of MQL5).
Before any of this touches real money, switch your account dropdown to a demo account. A demo runs on live prices with fake money, so you can watch the EA behave for days or weeks with nothing at stake. Also open the Strategy Tester (View → Strategy Tester) to replay the EA over historical data first — it is a low-cost way to catch an EA that behaves nothing like you expected. Past behaviour in the tester is not a promise of future results, but it is far better than finding out live.
The strategy inside an EA matters less, at the start, than the guardrails around it. An EA can send hundreds of orders while you sleep. If those orders have no protection, a single bad run can do serious damage before you ever look at the screen. Two habits protect you more than any clever entry signal.
First: every market order must carry a real, non-zero stop-loss. A stop-loss is the price at which the trade is automatically closed to cap the loss on that position. "I'll add it later" is how accounts get hurt. The stop goes on with the order, in the same call. Second: verify that the order actually worked. Sending an order is a request, not a guarantee — the broker can reject it. A careful EA checks the result and reacts instead of assuming success.
Here is a minimal MQL5 buy that follows the rules a safe EA lives by: it only acts on a new bar, checks whether a position already exists, sizes the lot from an input, reads a confirmed signal from the last closed bar through a proper indicator handle, attaches a real stop-loss and take-profit, tags the order with a unique magic number, and verifies the result.
5
// MQL5 — a single, safety-first buy. Educational example only.
#include <Trade/Trade.mqh>
CTrade trade;
input double InpLots = 0.10; // lot size from input, not a hidden literal
input int InpSL_Pts = 300; // stop-loss distance in points (non-zero)
input int InpTP_Pts = 600; // take-profit distance in points
input ulong InpMagic = 20240517;// unique, non-zero magic number
input int InpMaPeriod = 50; // MA period
int g_maHandle = INVALID_HANDLE; // indicator HANDLE, created once
int OnInit()
{
trade.SetExpertMagicNumber(InpMagic);
// iMA() returns a HANDLE in MQL5, not a value. Create it once here.
g_maHandle = iMA(_Symbol, _Period, InpMaPeriod, 0, MODE_SMA, PRICE_CLOSE);
if(g_maHandle == INVALID_HANDLE)
{
Print("Failed to create MA handle.");
return(INIT_FAILED); // refuse to run if setup fails
}
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
if(g_maHandle != INVALID_HANDLE)
IndicatorRelease(g_maHandle); // clean up the handle
}
void OnTick()
{
// 1) Gate to a NEW BAR so we act once per bar, not on every tick.
static datetime lastBar = 0;
datetime thisBar = iTime(_Symbol, _Period, 0);
if(thisBar == lastBar) return;
lastBar = thisBar;
// 2) Do not stack trades: skip if we already hold this symbol.
if(PositionSelect(_Symbol)) return;
// 3) Read the MA value at the last CLOSED bar (shift 1) via CopyBuffer.
double maBuf[];
if(CopyBuffer(g_maHandle, 0, 1, 1, maBuf) != 1) return; // no data yet
double maPrev = maBuf[0];
// 4) Read a CONFIRMED close from the last CLOSED bar (shift 1), not shift 0.
double closePrev = iClose(_Symbol, _Period, 1);
if(closePrev <= 0.0) return;
// 5) Example rule: only illustrating structure, not a recommendation.
bool wantBuy = (closePrev > maPrev);
if(!wantBuy) return;
// 6) Build a REAL stop-loss and take-profit around the ask.
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double sl = ask - InpSL_Pts * point; // non-zero stop-loss
double tp = ask + InpTP_Pts * point;
// 7) Send it, then VERIFY the result instead of assuming success.
if(trade.Buy(InpLots, _Symbol, ask, sl, tp, "demo-test"))
{
if(trade.ResultRetcode() == TRADE_RETCODE_DONE)
Print("Buy placed and confirmed.");
else
Print("Not filled. Retcode: ", trade.ResultRetcode());
}
else
Print("Order send failed. Retcode: ", trade.ResultRetcode());
}Every line above is a habit worth keeping: new-bar gating stops the EA from firing on every tick, reading the MA and close at shift 1 avoids acting on a candle that has not finished forming, the stop-loss is real and non-zero, and the result is checked before you trust it. If reading an unfamiliar EA to confirm it does these things feels daunting, that is exactly the kind of check a tool like ForexCodes' EA Auditor is built to help with. But whatever you use, the rule underneath does not change: test on a demo account until you genuinely understand how the EA behaves, and never skip the stop-loss. This is educational content, not financial advice, and trading involves a real risk of loss.
Educational only — not financial advice. Trading involves substantial risk of loss.