MT5 Expert Advisor Development: Complete Developer's Guide
Everything about MT5 Expert Advisor development in 2026 — MQL5 architecture, event handlers, order management, risk controls, backtesting, and deployment.

MT5 Expert Advisor Development: Complete Developer's Guide
MetaTrader 5 Expert Advisors are automated trading programs that run inside the MT5 terminal. They handle market analysis, signal generation, order placement, and position management without manual intervention. This guide covers the full development lifecycle — from architecture to deployment.
EA Structure and Event Handlers
An MT5 EA is an MQL5 program with specific event handlers that the terminal calls at defined times:
// Complete MT5 EA structure
#property copyright "Viprasol Tech"
#property version "2.00"
#property strict
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
// Input parameters
input group "=== Strategy ==="
input int InpFastMA = 10; // Fast MA Period
input int InpSlowMA = 50; // Slow MA Period
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1;
input group "=== Risk Management ==="
input double InpRiskPct = 1.0; // Risk per trade (% of balance)
input double InpStopLoss = 50; // Stop loss (pips)
input double InpTakeProfit = 100; // Take profit (pips)
input int InpMaxTrades = 3; // Max simultaneous positions
input group "=== Prop Firm Compliance ==="
input double InpMaxDailyLoss = 5.0; // Max daily loss %
input double InpMaxDrawdown = 10.0; // Max total drawdown %
input bool InpPropMode = false; // Enable prop firm rules
// Global objects
CTrade trade;
CPositionInfo posInfo;
// Global state
double g_AccountHighWater = 0;
double g_DayStartBalance = 0;
datetime g_LastDay = 0;
//+------------------------------------------------------------------+
int OnInit() {
// Validate inputs
if (InpFastMA >= InpSlowMA) {
Print("ERROR: Fast MA must be less than Slow MA");
return INIT_PARAMETERS_INCORRECT;
}
// Configure trade object
trade.SetExpertMagicNumber(123456); // Unique identifier for this EA's trades
trade.SetSlippage(30); // 3 pips slippage tolerance
trade.SetTypeFilling(ORDER_FILLING_IOC);
// Initialise state
g_AccountHighWater = AccountInfoDouble(ACCOUNT_BALANCE);
g_DayStartBalance = AccountInfoDouble(ACCOUNT_BALANCE);
g_LastDay = TimeCurrent();
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnTick() {
// 1. Check risk limits first — always
if (!RiskChecksPass()) return;
// 2. Only process on new bar (avoid multiple signals per bar)
static datetime lastBar = 0;
datetime currentBar = iTime(_Symbol, InpTimeframe, 0);
if (currentBar == lastBar) return;
lastBar = currentBar;
// 3. Get signal
int signal = GetSignal();
if (signal == 0) return;
// 4. Check if we can open new position
int openPositions = CountMyPositions();
if (openPositions >= InpMaxTrades) return;
// 5. Check we don't already have a position in this direction
if (HasPositionInDirection(signal)) return;
// 6. Calculate lot size based on risk
double lots = CalculateLotSize(InpStopLoss, InpRiskPct);
if (lots <= 0) return;
// 7. Open trade
if (signal > 0) OpenBuy(lots);
if (signal < 0) OpenSell(lots);
}
//+------------------------------------------------------------------+
int GetSignal() {
double fastMA_0 = iMA(_Symbol, InpTimeframe, InpFastMA, 0, MODE_EMA, PRICE_CLOSE, 0);
double fastMA_1 = iMA(_Symbol, InpTimeframe, InpFastMA, 0, MODE_EMA, PRICE_CLOSE, 1);
double slowMA_0 = iMA(_Symbol, InpTimeframe, InpSlowMA, 0, MODE_EMA, PRICE_CLOSE, 0);
double slowMA_1 = iMA(_Symbol, InpTimeframe, InpSlowMA, 0, MODE_EMA, PRICE_CLOSE, 1);
// Bullish crossover
if (fastMA_1 <= slowMA_1 && fastMA_0 > slowMA_0) return 1;
// Bearish crossover
if (fastMA_1 >= slowMA_1 && fastMA_0 < slowMA_0) return -1;
return 0;
}
//+------------------------------------------------------------------+
bool RiskChecksPass() {
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double equity = AccountInfoDouble(ACCOUNT_EQUITY);
// Update daily state
MqlDateTime today;
TimeToStruct(TimeCurrent(), today);
MqlDateTime lastDayStruct;
TimeToStruct(g_LastDay, lastDayStruct);
if (today.day != lastDayStruct.day) {
g_DayStartBalance = balance;
g_LastDay = TimeCurrent();
}
// Update high water mark
if (balance > g_AccountHighWater) g_AccountHighWater = balance;
// Check daily loss limit (prop firm critical)
if (InpPropMode) {
double dailyLoss = (g_DayStartBalance - equity) / g_DayStartBalance * 100;
if (dailyLoss >= InpMaxDailyLoss) {
Print("Daily loss limit reached: ", dailyLoss, "%");
CloseAllPositions();
return false;
}
// Check total drawdown
double totalDrawdown = (g_AccountHighWater - equity) / g_AccountHighWater * 100;
if (totalDrawdown >= InpMaxDrawdown) {
Print("Max drawdown reached: ", totalDrawdown, "%");
CloseAllPositions();
return false;
}
}
return true;
}
//+------------------------------------------------------------------+
double CalculateLotSize(double stopLossPips, double riskPct) {
double balance = AccountInfoDouble(ACCOUNT_BALANCE);
double riskAmount = balance * riskPct / 100.0;
double pipValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double pipValueNorm = pipValue / tickSize * _Point;
double lots = riskAmount / (stopLossPips * pipValueNorm * 10);
double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
lots = MathFloor(lots / lotStep) * lotStep;
return MathMax(minLot, MathMin(maxLot, lots));
}
Backtesting Best Practices
Run backtests in MT5 Strategy Tester with:
- Every tick based on real ticks — most accurate
- At least 5 years of history
- Multiple currency pairs — strategy should work across pairs, not just EURUSD
- Walk-forward optimisation — optimise on 70% of data, test on remaining 30%
- Monte Carlo simulation — randomise trade order to test equity curve robustness
Watch for: results that are suspiciously good (>80% win rate, unrealistic Sharpe ratio), strategies that only work on one pair, and forward-test results that diverge heavily from backtest.
🤖 Can This Strategy Be Automated?
In 2026, top traders run custom EAs — not manual charts. We build MT4/MT5 Expert Advisors that execute your exact strategy 24/7, pass prop firm challenges, and eliminate emotional decisions.
- Runs 24/7 — no screen time, no missed entries
- Prop-firm compliant (FTMO, MFF, TFT drawdown rules)
- MyFXBook-verified backtest results included
- From strategy brief to live EA in 2–4 weeks
Deployment Checklist
Before going live:
- Forward test on demo account for minimum 30 trades
- Verify lot size calculation across different account currencies
- Test with news filter during high-impact events
- Verify prop firm compliance layer if applicable
- Set up MyFXBook verification
- VPS with < 20ms latency to broker
Need a professional MT5 EA built to your strategy? Viprasol builds MQL5 Expert Advisors with MyFXBook-verified results. Contact us.
See also: AI Forex Trading Bot Guide · Algorithmic Trading Trends 2026
About the Author
Viprasol Tech Team
Custom Software Development Specialists
The Viprasol Tech team specialises in algorithmic trading software, AI agent systems, and SaaS development. With 100+ projects delivered across MT4/MT5 EAs, fintech platforms, and production AI systems, the team brings deep technical experience to every engagement. Based in India, serving clients globally.
Ready to Automate Your Trading?
Get a custom Expert Advisor built by professionals with verified MyFXBook results.
Free consultation • No commitment • Response within 24 hours
Need a custom EA or trading bot built?
We specialise in MT4/MT5 Expert Advisor development — prop-firm compliant, forward-tested before live, MyFXBook verifiable. 5.0★ Upwork, 100% Job Success, 100+ projects shipped.