Sign up with our partner broker and get free XAU/USD signals. JOIN US
LIVE MT5 BUILD 5830 LAST REV 2026-05-23
SESSION -- UTC --:--
SESSIONS
SYDNEY22:00–07:00 UTC
TOKYO00:00–09:00 UTC
LONDON07:00–16:00 UTC
NEW YORK12:00–21:00 UTC

Writing your first Expert Advisor in MQL5

You do not need to be a developer to write a working Expert Advisor. You do need to understand a few core MQL5 functions and the order of operations MT5 expects. Here is the minimum viable EA, explained line by line.

PUBLISHED 2026-05-24 READING TIME 14 MIN MT5 BUILD 5830 CATEGORY TOOLS
Important: Writing an EA is the easy part. Writing an EA that makes money is hard. The walkthrough below produces a syntactically valid, functional EA. Whether the underlying strategy is profitable is a completely separate question, and the answer for most simple ideas is no.

1. What an EA actually is

An Expert Advisor (EA) is a compiled .ex5 program that MT5 runs on a chart. The EA gets called on every incoming tick and can read market data, place orders, modify orders, and close positions. It runs server-side from the broker's perspective: orders go directly from your MT5 terminal to the broker.

An EA is not an indicator. Indicators only draw on the chart; they cannot place trades. EAs can trade. Scripts are a third type: they run once on demand and then exit. EAs run continuously while attached to a chart.

2. The MQL5 lifecycle functions

Every EA has up to four special functions that MT5 calls automatically:

FunctionWhen it runsTypical use
OnInit()Once, when the EA is attached or the chart restartsInitialise variables, check inputs, set up indicators
OnDeinit()Once, when the EA is removed or the chart closesCleanup, release indicator handles
OnTick()Every incoming price update for the chart symbolStrategy logic, order management
OnTimer()Every N seconds, if you set up a timerPeriodic checks independent of ticks (less common)

For a minimal EA you only need OnInit and OnTick.

3. Opening MetaEditor

MetaEditor is the IDE for writing MQL5. Open it from MT5 with F4 or from the toolbar. Then:

  1. File → New → Expert Advisor (template).
  2. Give it a name, e.g. SimpleMA_EA. The file will be saved as SimpleMA_EA.mq5 in your MQL5/Experts folder.
  3. Click through the wizard. The default template gives you OnInit, OnDeinit, and OnTick stubs ready to fill in.

4. The example EA: moving average crossover

The strategy is intentionally simple. We will use two moving averages: a fast (10-period) and a slow (30-period). When fast crosses above slow we buy. When fast crosses below slow we sell. One position at a time. Fixed lot size for now.

Below is the complete source. We will go through it section by section.

//+------------------------------------------------------------------+
//|                                              SimpleMA_EA.mq5    |
//+------------------------------------------------------------------+
#property copyright "Educational example"
#property version   "1.00"
#property strict

#include <Trade/Trade.mqh>

// Inputs
input int    FastMA_Period = 10;
input int    SlowMA_Period = 30;
input double LotSize       = 0.01;
input int    SL_Points     = 200;   // stop loss distance in points
input int    TP_Points     = 400;   // take profit distance in points
input ulong  MagicNumber   = 20260524;

// Globals
CTrade trade;
int    fastHandle, slowHandle;

//+------------------------------------------------------------------+
int OnInit()
{
   trade.SetExpertMagicNumber(MagicNumber);
   fastHandle = iMA(_Symbol, _Period, FastMA_Period, 0, MODE_EMA, PRICE_CLOSE);
   slowHandle = iMA(_Symbol, _Period, SlowMA_Period, 0, MODE_EMA, PRICE_CLOSE);

   if(fastHandle == INVALID_HANDLE || slowHandle == INVALID_HANDLE)
   {
      Print("Failed to create MA indicators");
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   IndicatorRelease(fastHandle);
   IndicatorRelease(slowHandle);
}

//+------------------------------------------------------------------+
void OnTick()
{
   // Only act on a new bar
   static datetime lastBar = 0;
   datetime currentBar = iTime(_Symbol, _Period, 0);
   if(currentBar == lastBar) return;
   lastBar = currentBar;

   // Get last two values of each MA
   double fast[2], slow[2];
   if(CopyBuffer(fastHandle, 0, 1, 2, fast) < 2) return;
   if(CopyBuffer(slowHandle, 0, 1, 2, slow) < 2) return;

   // fast[0] = bar that just closed, fast[1] = bar before that
   bool crossUp   = (fast[1] <= slow[1]) && (fast[0] > slow[0]);
   bool crossDown = (fast[1] >= slow[1]) && (fast[0] < slow[0]);

   // Check for existing position
   bool hasPosition = PositionSelect(_Symbol);

   if(crossUp && !hasPosition)
   {
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      double sl  = ask - SL_Points * _Point;
      double tp  = ask + TP_Points * _Point;
      trade.Buy(LotSize, _Symbol, ask, sl, tp, "MA cross long");
   }
   else if(crossDown && !hasPosition)
   {
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double sl  = bid + SL_Points * _Point;
      double tp  = bid - TP_Points * _Point;
      trade.Sell(LotSize, _Symbol, bid, sl, tp, "MA cross short");
   }
}

5. Walking through the code

5.1 The header and include

#property strict turns on stricter compile checking. Always include it.

#include <Trade/Trade.mqh> imports the standard trading library. This gives us the CTrade class which wraps the low-level order send functions into clean methods like trade.Buy() and trade.Sell().

5.2 Inputs

The input keyword exposes a variable in the EA settings dialog when the user attaches the EA. This means you can change parameters without recompiling. Use inputs for anything you might want to optimise or tweak.

5.3 OnInit

We set the magic number on the trade object. The magic number is a tag attached to every order our EA sends. It lets us identify which positions belong to this EA versus other EAs or manual trades. Use a unique value per EA per chart.

iMA() creates an indicator handle. Note that in MQL5 we do not get values directly from iMA; we get a handle that we use later with CopyBuffer to read values. If iMA returns INVALID_HANDLE, something is wrong (out of memory or invalid parameters) and we abort initialisation.

5.4 OnTick logic

The first block ensures we only run our logic once per closed bar. Without this guard, OnTick() would fire every tick and we would trade many times within the same bar. The static lastBar variable persists between ticks.

CopyBuffer(handle, buffer, start, count, array) reads indicator values. We pass start=1 to skip the still-forming current bar and count=2 to get the last two closed bars.

The crossover detection compares two consecutive bars. If the fast MA was below or equal to the slow MA on bar [1] and is now above on bar [0], that is a cross up. The opposite for cross down.

5.5 Order sending

trade.Buy() and trade.Sell() send market orders. The CTrade class handles the order request structure, the deal_id and order_id tracking, and the return code checking. If you tried to do this manually with OrderSend() you would write 20 more lines.

6. Compiling and running

In MetaEditor press F7 or click Compile. If there are errors they appear in the Errors tab at the bottom. Common first-time errors:

  • 'iMA' - undeclared identifier. You forgot to specify the right MQL5 imports or used an MQL4 function name.
  • cannot convert. Type mismatch. Common when mixing int and double.
  • not all control paths return a value. Your function says it returns something but a code path falls through without returning.

Once compiled cleanly, switch to MT5. Open the Navigator (Ctrl+N), expand Expert Advisors, find your EA, drag it onto a chart. The settings dialog appears. Enable the "Allow Algo Trading" checkbox. Click OK. Your EA is now running.

7. The Strategy Tester

Before running an EA on a real account, backtest it. View → Strategy Tester (Ctrl+R). Select your EA, the symbol, the timeframe, and a date range. Choose modelling quality (Every tick based on real ticks is the gold standard for FX). Click Start.

The tester runs the EA against historical data and produces a report: net profit, drawdown, profit factor, number of trades. Common first-EA outcomes:

  • The EA does almost no trades. Your entry conditions are too restrictive.
  • The EA bleeds money slowly. Your edge does not exceed your trading costs (spread, commission, slippage).
  • The EA looks great on one period and terrible on another. Your strategy is curve-fit.

8. Risk management essentials

The example EA uses fixed stop loss and take profit distances in points. This is the simplest possible risk model. For anything beyond educational testing you want:

  • Volatility-adjusted stops. Use ATR to size your stop loss relative to current market volatility. A fixed 200-point stop is too tight in volatile sessions and too wide in quiet ones.
  • Risk-based position sizing. Instead of a fixed 0.01 lot, calculate the lot size that puts a fixed percentage of account equity at risk for the given stop distance.
  • Maximum daily loss circuit breaker. If the EA loses more than X% in one day, stop trading for the rest of the day.
  • Maximum drawdown halt. If equity drawdown from peak exceeds Y%, disable trading entirely until manually re-enabled.

9. Common beginner mistakes

MistakeWhat goes wrong
Trading on every tick instead of every closed barHundreds of duplicate orders, signals firing then reversing within seconds
Forgetting magic numbersEA closes positions opened by other EAs or by you manually
Hardcoding lot size, then running on a small accountMargin call on first trade
Not checking SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE)EA tries to trade a symbol that is in close-only mode (weekends, holidays, restricted hours)
Ignoring slippage and partial fillsReal-account performance diverges from backtest
Optimising on the same data you tested onIn-sample overfitting. Performance collapses on new data.

10. Where to go next

Once your first EA compiles and runs in the tester, the natural progression is:

  1. Add proper risk-based position sizing using AccountInfoDouble(ACCOUNT_EQUITY) and SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE).
  2. Replace fixed stops with ATR-based stops using a second indicator handle for ATR.
  3. Add a trailing stop using trade.PositionModify().
  4. Add filters: only trade certain hours, only trade if a higher timeframe trend agrees, only trade if spread is below a threshold.
  5. Run walk-forward optimisation rather than full-period optimisation to test robustness.

The MQL5 documentation at the official MetaQuotes site is dense but complete. The CodeBase section has thousands of open-source EAs you can read to learn idioms and patterns.

FAQ

Do I need to know C++ to write MQL5?

MQL5 syntax is C++-like but you can write functional EAs knowing only the basics: variables, if/else, loops, functions. Object-oriented features (classes, inheritance) are available but not required for simple EAs.

Can I run multiple EAs on the same account?

Yes, as long as each EA uses a different magic number and they are not contradicting each other on the same symbol. Each EA must be attached to its own chart.

How long does it take to write a profitable EA?

Writing one takes hours. Making it profitable takes months or years and most attempts fail. The hard part is not coding; it is finding an edge that survives real market conditions.

Can I sell my EA on the MQL5 Market?

Yes, MetaQuotes runs a marketplace where you can sell EAs to other MT5 users. There is a review process and revenue share. Most sellers earn very little; a few sellers earn substantial income from well-marketed products with consistent performance.

Will my EA work the same on a different broker?

Mostly yes, but expect small differences. Symbol naming varies (XAUUSD vs GOLD vs XAU/USD). Tick size and minimum lot may differ. Execution speed and slippage characteristics depend on the broker server.

// FOR EA DEVELOPERS

Manual trade ideas to validate against

We post real trade ideas to test your EAs against. Useful as an independent reference when evaluating whether your EA is performing rationally. Free for partner-broker clients.

See the signals →
FREE WITH PARTNER BROKER · disclosure