StructureX

Home › Guides › Trading bots & code

MQL5 for beginners: your first Expert Advisor, line by line

MQL5 is the language of MetaTrader 5's Expert Advisors. It looks scarier than it is. This page builds one small EA in 4 blocks — and the safety parts come before the trading part.

Beginner guide · 10-minute read · Updated 2026-10-21

What you'll build

A small Expert Advisor (EA) for MetaTrader 5 that:

  1. Waits for a new candle, so it decides once per candle, not on every price tick.
  2. Checks a simple rule: a fast EMA crossing above a slow one on the last finished candle.
  3. Sizes the trade so a stop-out costs about 1% of the account.
  4. Sends the order with a stop and a target attached.
  5. Stops trading for the day after a 2% drop.

The rule is deliberately plain. The point is the structure, not the signal. A crossing average is not an edge by itself.

Example code for learning — test it on paper first; it is not a ready-made trading system.

Before you start

New to EAs? Read MetaTrader Expert Advisor basics first.

Block 1: Settings and setup

#include <Trade/Trade.mqh>
input int    FastPeriod      = 9;     // fast EMA length
input int    SlowPeriod      = 21;    // slow EMA length
input double RiskPercent     = 1.0;   // risk per trade, % of equity
input int    StopPoints      = 300;   // stop distance, in points
input double MaxDailyLossPct = 2.0;   // no new trades after this daily drop
CTrade   trade;
int      fastHandle, slowHandle;
datetime lastBar = 0;
double   dayStartEquity = 0;
int      lastDay = -1;
int OnInit()
{
   fastHandle = iMA(_Symbol, _Period, FastPeriod, 0, MODE_EMA, PRICE_CLOSE);
   slowHandle = iMA(_Symbol, _Period, SlowPeriod, 0, MODE_EMA, PRICE_CLOSE);
   if(fastHandle == INVALID_HANDLE || slowHandle == INVALID_HANDLE)
      return(INIT_FAILED);
   return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
   IndicatorRelease(fastHandle);
   IndicatorRelease(slowHandle);
}

In plain words:

A point is the smallest price step for the symbol. On a 5-digit EUR/USD quote, 300 points = 30 pips. Check your symbol — points differ between markets.

Block 2: Size from the stop

double LotsForRisk(double stopDistance)
{
   double riskMoney = AccountInfoDouble(ACCOUNT_EQUITY) * RiskPercent / 100.0;
   double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
   double tickSize  = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   double step      = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
   double minLot    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
   double maxLot    = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   if(tickValue <= 0 || tickSize <= 0 || step <= 0)
      return(0);
   double lossPerLot = stopDistance / tickSize * tickValue;
   double lots = MathFloor(riskMoney / lossPerLot / step) * step;
   if(lots < minLot)
      return(0);
   int digits = (int)MathRound(-MathLog10(step));
   return(NormalizeDouble(MathMin(lots, maxLot), digits));
}

In plain words:

Example: 10,000 equity, 1% risk = 100. If 1 lot loses 300 at the stop, 100 ÷ 300 = 0.333, rounded down to 0.33 lots. A math example, not a promise — a gap past the stop or a wider spread can cost more. Check it with our lot size calculator.

Block 3: The daily loss limit

bool DailyLimitHit()
{
   MqlDateTime now;
   TimeToStruct(TimeCurrent(), now);
   if(now.day_of_year != lastDay)
   {
      lastDay = now.day_of_year;
      dayStartEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   }
   return(AccountInfoDouble(ACCOUNT_EQUITY) <= dayStartEquity * (1.0 - MaxDailyLossPct / 100.0));
}

In plain words: when a new day starts (by the broker's server clock), remember the equity. After that, if equity falls 2% or more below that number, answer "yes, the limit is hit". The trading block checks this first and does nothing if it's true.

This is a kill switch written into the code. The other kill switch is the Algo Trading button on the toolbar — know where it is. See daily loss limit.

Block 4: The trading rule

void OnTick()
{
   if(DailyLimitHit())
      return;
   datetime barTime = iTime(_Symbol, _Period, 0);
   if(barTime == lastBar)
      return;
   lastBar = barTime;
   double fast[], slow[];
   ArraySetAsSeries(fast, true);
   ArraySetAsSeries(slow, true);
   if(CopyBuffer(fastHandle, 0, 1, 2, fast) < 2 || CopyBuffer(slowHandle, 0, 1, 2, slow) < 2)
      return;
   bool crossedUp = fast[1] <= slow[1] && fast[0] > slow[0];
   if(!crossedUp || PositionSelect(_Symbol))
      return;
   double ask    = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double stop   = NormalizeDouble(ask - StopPoints * _Point, _Digits);
   double target = NormalizeDouble(ask + 2 * StopPoints * _Point, _Digits);
   double lots   = LotsForRisk(StopPoints * _Point);
   if(lots <= 0)
   {
      Print("Stop too wide for the risk limit. Skipped.");
      return;
   }
   if(trade.Buy(lots, _Symbol, ask, stop, target))
      Print("Buy sent: ", lots, " lots, stop ", stop, ", target ", target);
   else
      Print("Buy failed: ", trade.ResultRetcode(), " ", trade.ResultRetcodeDescription());
}

Line by line, in plain words:

Compile, test, then demo

  1. Click Compile in MetaEditor. Fix any errors it lists (usually a missing semicolon or bracket).
  2. Open the Strategy Tester in MetaTrader 5, pick your EA, a symbol and a long date range, and run it.
  3. Read the trades, not just the final number: the longest losing streak and the deepest Drawdown.
  4. Run it on a demo account for weeks. See paper trading a bot.

Two test traps: overfitting (tuning the settings until the past looks perfect — then it fails on new data) and unrealistic fills (ignoring Spread and Slippage). A Strategy Tester result is hypothetical. Losses are always possible.

This EA is a skeleton, not a strategy. It shows the safe structure: decide on finished candles, size from the stop, attach the stop, cap the day, log everything. The rule inside is yours to replace with one you've written and tested.

What this EA doesn't do (yet)

More ideas: trading bot risk controls and common trading bot mistakes.

Questions

Is MQL5 hard to learn?

It's harder than Python because it's strict like C++, with types, semicolons and brackets. But a small EA is under 100 lines, and MetaEditor shows errors with line numbers.

What is the difference between MQL4 and MQL5?

MQL4 runs on MetaTrader 4 and MQL5 on MetaTrader 5. They look similar, but trading functions and indicator handling differ, so code has to be rewritten to move between them.

How do I backtest an Expert Advisor in MT5?

Compile it in MetaEditor, open the Strategy Tester in MetaTrader 5, choose the EA, symbol, dates and modelling mode, then run it and read the report and trade list.

Can I learn MQL5 without knowing how to code?

Yes, but start small: copy one block, compile it, change one input, compile again. Learning the basic ideas in a simpler language like Python first can also help.

Want the next step? We'll walk you through it.

Four free lessons by email, one every few days — each with a 10-minute exercise on a real chart.

Send Me the Free Lessons 4 short emails · No spam · Unsubscribe anytime

Or see the whole method, step by step:

See What’s Inside the Course Try everything free first. Decide when you're ready. · Open the free chart tool (works in the TradingView phone app)

One chart idea a day, in plain English. Follow along:

Follow on XFollow on TradingView