Custom Expert Advisor in MT4: Build One With MQL4

Custom Expert Advisor in MT4: Build One With MQL4

develop custom a expert advisor for MT4 with the help of this guide

Key Takeaways

  • A custom MT4 EA is MQL4 code compiled into an .ex4 file. You write the rules in MetaEditor, compile with F7, and attach the EA to a chart in MetaTrader 4.
  • Write exact rules before you code. Entry, exit, position size, trade limits and when to check for signals all need to be defined in plain words first.
  • A safe EA does more than send orders. It checks for a new candle, uses a magic number, handles 5 digit pricing and sizes each trade from a fixed risk.
  • Test twice before risking real money. Run the Strategy Tester first, then a demo account, and remember that an MT4 EA will not run on MT5 without a rewrite.

To build a custom expert advisor in MT4, you write the trading rules in MQL4 inside MetaEditor, compile them into an .ex4 file, then test the EA in the MT4 Strategy Tester and on a demo account. The core of every EA is a function called OnTick that runs each time a new price arrives and decides whether to open, manage or close trades.

This guide walks through the whole process with a complete, working moving average crossover EA you can copy, compile and test. It also covers the errors beginners hit most and when coding is not the best route.

If you trade on MetaTrader 5, see our separate guide on how to create and optimize your own EA for MT5.

Three Ways to Get a Custom Expert Advisor in MT4

Route Skills needed Flexibility Main drawback
Code it yourself in MQL4 Programming basics and time to debug Unlimited; any rule you can describe Bugs in order handling can cost real money
Use an EA builder None, or very little Limited to the blocks the builder offers Generated code can be hard to read or fix
Customize a prebuilt bot None Limited to the settings exposed You cannot add rules the bot was not built for

Coding gives you full control, and it is the route this guide teaches. If you only need to change risk, symbols or trading hours on a proven strategy, customizing a prebuilt bot is faster and carries less risk of a coding mistake.

Step 1: Write Down the Rules Before You Code

An EA can only follow rules that are exact. Before opening MetaEditor, write down five things in plain words:

Rule Example used in this guide
Entry Buy when the 10 period EMA crosses above the 50 period EMA; sell on the opposite cross
Exit Fixed stop loss of 30 pips and take profit of 60 pips
Position size Risk 1% of the balance per trade
Trade limit Only one open trade per symbol at a time
When to check Once per new candle, using closed candles only

Step 2: Open MetaEditor and Create the EA File

  1. In MT4, press F4 or click the MetaEditor button in the toolbar.
  2. In MetaEditor, choose File, then New, then Expert Advisor (template), and give it a name such as MACross.
  3. Click through the wizard and finish. MetaEditor creates an .mq4 file with empty OnInit, OnDeinit and OnTick functions.

Step 3: Understand the Three Core Functions

Function When it runs What goes in it
OnInit Once, when the EA is attached to a chart Checks on inputs and any setup work
OnTick Every time a new price arrives The trading logic: signals, sizing, orders
OnDeinit Once, when the EA is removed Cleanup, such as deleting chart objects

Step 4: The Complete MQL4 Code

Replace the template with the code below. It is a full, compilable EA for MT4 that uses everything from Step 1.

#property strict

input int    FastMA         = 10;     // fast EMA period
input int    SlowMA         = 50;     // slow EMA period
input double RiskPercent    = 1.0;    // risk per trade, % of balance
input int    StopLossPips   = 30;
input int    TakeProfitPips = 60;
input int    MagicNumber    = 20261;  // identifies this EA's trades

datetime lastBarTime = 0;

int OnInit()
{
   if(FastMA >= SlowMA)
   {
      Print("FastMA must be smaller than SlowMA");
      return(INIT_PARAMETERS_INCORRECT);
   }
   return(INIT_SUCCEEDED);
}

void OnTick()
{
   // run the logic once per new candle
   if(Time[0] == lastBarTime) return;
   lastBarTime = Time[0];

   // use closed candles (shift 1 and 2) to avoid signals that repaint
   double fastNow  = iMA(NULL, 0, FastMA, 0, MODE_EMA, PRICE_CLOSE, 1);
   double fastPrev = iMA(NULL, 0, FastMA, 0, MODE_EMA, PRICE_CLOSE, 2);
   double slowNow  = iMA(NULL, 0, SlowMA, 0, MODE_EMA, PRICE_CLOSE, 1);
   double slowPrev = iMA(NULL, 0, SlowMA, 0, MODE_EMA, PRICE_CLOSE, 2);

   if(CountOpenTrades() > 0) return;

   if(fastPrev <= slowPrev && fastNow > slowNow) OpenTrade(OP_BUY);
   if(fastPrev >= slowPrev && fastNow < slowNow) OpenTrade(OP_SELL);
}

int CountOpenTrades()
{
   int count = 0;
   for(int i = OrdersTotal() - 1; i >= 0; i--)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
         if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
            count++;
   return(count);
}

double PipSize()
{
   // 5 digit and 3 digit brokers quote in fractional pips
   return((Digits == 3 || Digits == 5) ? Point * 10 : Point);
}

double LotSize()
{
   double riskMoney  = AccountBalance() * RiskPercent / 100.0;
   double tickValue  = MarketInfo(Symbol(), MODE_TICKVALUE);
   double tickSize   = MarketInfo(Symbol(), MODE_TICKSIZE);
   double lossPerLot = (StopLossPips * PipSize()) / tickSize * tickValue;
   if(lossPerLot <= 0) return(0);

   double step = MarketInfo(Symbol(), MODE_LOTSTEP);
   double lots = MathFloor((riskMoney / lossPerLot) / step) * step;
   if(lots < MarketInfo(Symbol(), MODE_MINLOT)) return(0); // too small to trade at this risk
   return(NormalizeDouble(MathMin(lots, MarketInfo(Symbol(), MODE_MAXLOT)), 2));
}

void OpenTrade(int type)
{
   double lots = LotSize();
   if(lots <= 0) { Print("Lot size below broker minimum, trade skipped"); return; }

   double pip   = PipSize();
   double price = (type == OP_BUY) ? Ask : Bid;
   double sl    = (type == OP_BUY) ? price - StopLossPips * pip   : price + StopLossPips * pip;
   double tp    = (type == OP_BUY) ? price + TakeProfitPips * pip : price - TakeProfitPips * pip;

   int ticket = OrderSend(Symbol(), type, lots, price, 3,
                          NormalizeDouble(sl, Digits), NormalizeDouble(tp, Digits),
                          "MA cross", MagicNumber, 0, clrNONE);
   if(ticket < 0) Print("OrderSend failed, error ", GetLastError());
}

Step 5: What Each Part of the Code Does

  • Inputs. Everything a trader may want to change sits at the top, so it can be adjusted in the EA’s Inputs tab without editing code.
  • New candle check. Comparing Time[0] with the last stored time stops the EA from firing the same signal on every tick.
  • Closed candles. Reading the moving averages at shift 1 and 2 means the signal is based on finished candles that will not change.
  • Magic number. CountOpenTrades only counts trades with this EA’s magic number, so it ignores manual trades and other EAs on the same account.
  • Pip size. Most brokers quote EUR/USD with 5 digits, where one pip equals 10 points; PipSize handles both cases.
  • Risk based lot size. LotSize turns 1% of the balance into a lot size using the stop distance, and skips the trade if the result is below the broker’s minimum lot rather than quietly taking more risk.

Worked example: what LotSize returns

On a $5,000 account trading EUR/USD, 1% risk is $50. A 30 pip stop on one standard lot costs about $300, so the EA opens $50 ÷ $300 = 0.166, rounded down to 0.16 lots.

Step 6: Compile and Fix Errors

Press F7 or click Compile in MetaEditor. The Errors tab at the bottom lists every problem with a line number; fix them from the top, since one early error often causes several later ones.

A common beginner mistake is copying code from a web page that turned straight quotes into curly quotes. MQL4 only accepts plain straight quotes around text, so retype them if the compiler complains.

Step 7: Test Your Custom Expert Advisor in MT4

Open the Strategy Tester with Ctrl+R, select your EA, the symbol and the timeframe, and choose Every tick as the model. Run it once with visual mode on to watch the EA open and close trades on the chart; it is the fastest way to spot logic errors.

Then read the report for maximum drawdown, profit factor and the number of trades, not just the final balance. Our guide on how to backtest an Expert Advisor on MetaTrader 4 covers settings and data quality in more detail.

A backtest is only the first filter. Run the EA on a demo account for a few weeks before any live use, since real spreads, slippage and broker rules behave differently from the tester.

Common MQL4 Errors and How to Fix Them

Error code What it means Usual fix
130 Invalid stops Stop loss or take profit is too close to price; check MODE_STOPLEVEL and widen it
131 Invalid trade volume Lot size is below the minimum or not a multiple of the lot step; normalize it
134 Not enough money Lot size too large for the free margin; lower risk or leverage
138 Requote Price moved before execution; refresh prices and retry, or raise slippage slightly
4109 Trade not allowed Allow live trading is unticked or AutoTrading is off

Some brokers reject a market order that already carries a stop loss and take profit. If you see error 130 on every trade, send the order with both set to 0, then add them with OrderModify once the trade is open. The official MQL4 reference for OrderSend lists every parameter and its rules.

Will an MT4 EA Run on MT5?

No. MT4 uses MQL4 and MT5 uses MQL5, and the two handle orders differently, so an MT4 EA has to be rewritten to run on MT5. If you plan to trade on both platforms, decide early which one to code for.

When Customizing a Prebuilt Bot Makes More Sense

Coding is worth it when you need a rule nobody else offers. If what you really need is a proven strategy with your own risk, symbols and trading hours, customizing a prebuilt bot saves weeks of coding and debugging.

XAUBOT is our own platform, so weigh this accordingly. You start from a prebuilt bot, pick from more than 10 fixed entry strategies and the Scalp or Multi Level method, set your risk and drawdown limits, and download an EA that runs on both MetaTrader 4 and MT5. You cannot add your own indicators, which is the tradeoff for not writing code.

You can try it free for 15 days on a demo account; see the forex trading bot page for details.

Custom Expert Advisor Questions

Is MQL4 hard to learn?

If you know any C style language, MQL4 will feel familiar. Complete beginners can write a simple EA within a few weeks, but reliable order handling and error checking take longer to get right.

Do I need to keep MT4 open for my EA to trade?

Yes. The EA only runs while the MT4 terminal is open and connected, so many traders use a VPS. Our guide to MT4 bot trading covers setup and the common reasons a bot stops trading.

Can I run my EA on more than one chart?

Yes. Give each copy a different magic number so the EAs do not count or close each other’s trades.

Is a profitable backtest enough to go live?

No. Backtests are built with hindsight and simplified costs. Forward test on a demo account first and keep risk per trade small when you do go live.

Before You Run Your EA With Real Money

A coding mistake in an EA can open the wrong size, skip a stop loss or trade far more often than planned. Test every change on demo first, start live with the smallest size your broker allows, and never trade money you cannot afford to lose.

A practical next step: copy the code above into MetaEditor, compile it, and run it in the Strategy Tester on EUR/USD H1. Then change one input at a time and watch how the results move.

5/5 - (1 vote)

Further Reading

Leave a Reply

Your email address will not be published. Required fields are marked *

Share Post

Contents