Create MQL5 Expert Advisor Without Coding: Beginner's Complete Guide
You can start an MQL5 Expert Advisor with a wizard, a visual builder, or a coding assistant without writing every line yourself. You still need an explicit strategy specification, source review, compilation, and behavior tests. This guide distinguishes those routes and supplies an educational EMA example to inspect; it does not promise a deployed or profitable robot at the end of the page.
Choose a creation route
For a standard-library strategy, open MetaEditor File → New and choose Expert Advisor (generate), then select supported signal, money-management, and trailing modules. Expert Advisor (template) only creates the starting structure.
For a visual builder, check that its rules express your required event timing and that its current plan exports to MT5. For an AI assistant, specify EA versus indicator, completed bars versus ticks, and what to do after a failed trade request.
Review an explicit specification
Write a short acceptance list before generating: signal inputs and timing, position limit, stop and target calculation, sizing method, and behavior after missing data or a restart. Ask the assistant to list dependencies and assumptions.
Start with a signal-only version that logs completed-bar timestamps. Compare those values with the chart before adding orders. This is a suggested testing method, not a claimed benchmark result.
Compile and test the actual file
Save EA source in MQL5/Experts and compile in MetaEditor. In Pineify, explicitly request a syntax check and inspect its result; source generation is a separate operation.
Use MT5 Strategy Tester to compare logs with your specification, then assess separate data and a demo account. Keep the source and settings for each run. Changing input values can alter risk and execution behavior even when you do not edit code.
Implementation details & mechanics
Core implementation pattern
The example is an EA saved under MQL5/Experts. At a new chart bar, it checks a crossover on the two completed EMA bars and compares the current entry quote with the last completed trend SMA. It allows at most one matching symbol/magic position. The settings illustrate periods and fixed-volume orders, not optimized parameters; the quote-based trend filter can differ from a completed-close filter.
Error handling & safety rules
The example requests fixed SL/TP distances and has no crossover exit, trailing stop, news filter, or daily loss limit. Distances use the conventional 3/5-digit forex pip conversion, not a universal contract unit. Review volume steps, tick sizes, stops, and FOK filling support. It checks the server result but cannot guarantee execution or isolate other strategies sharing a netting position.
MQL5 Code Implementation
//+------------------------------------------------------------------+
//| NoCodeStarterEA.mq5 |
//| Teaching example for inspecting generated EA behavior |
//| Demonstrates the classic Moving-Average crossover pattern that |
//| This is not evidence of any particular builder output. |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property link "https://pineify.app"
#property version "1.00"
#property strict
//--- Input parameters (the "settings" users tweak without coding)
input int FastPeriod = 9; // Fast MA period
input int SlowPeriod = 21; // Slow MA period
input int MAPeriod = 200; // Trend filter MA period
input double LotSize = 0.10; // Trade volume in lots
input int StopLossPips = 40; // Stop loss in pips
input int TakeProfitPips = 80; // Take profit in pips
input int MagicNumber = 202600; // Unique EA identifier
input string TradeComment = "NoCodeEA"; // Order comment
//--- Indicator handles
int handleFast = INVALID_HANDLE;
int handleSlow = INVALID_HANDLE;
int handleTrend = INVALID_HANDLE;
//--- Buffers
double fastBuf[];
double slowBuf[];
double trendBuf[];
//+------------------------------------------------------------------+
//| Expert initialisation — runs once when EA is attached |
//+------------------------------------------------------------------+
int OnInit()
{
if(FastPeriod <= 0 || SlowPeriod <= FastPeriod || MAPeriod <= 0 ||
LotSize <= 0 || StopLossPips <= 0 || TakeProfitPips <= 0 || MagicNumber < 0)
return INIT_PARAMETERS_INCORRECT;
//--- Create indicator handles
handleFast = iMA(_Symbol, PERIOD_CURRENT, FastPeriod, 0, MODE_EMA, PRICE_CLOSE);
handleSlow = iMA(_Symbol, PERIOD_CURRENT, SlowPeriod, 0, MODE_EMA, PRICE_CLOSE);
handleTrend = iMA(_Symbol, PERIOD_CURRENT, MAPeriod, 0, MODE_SMA, PRICE_CLOSE);
if(handleFast == INVALID_HANDLE || handleSlow == INVALID_HANDLE || handleTrend == INVALID_HANDLE)
{
Print("ERROR: Failed to create indicator handles.");
return INIT_FAILED;
}
//--- Set buffer as series (newest value at index 0)
ArraySetAsSeries(fastBuf, true);
ArraySetAsSeries(slowBuf, true);
ArraySetAsSeries(trendBuf, true);
Print("NoCodeStarterEA initialised on ", _Symbol,
" | Fast=", FastPeriod, " Slow=", SlowPeriod);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization — runs once when EA is removed |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release indicator handles to free memory
if(handleFast != INVALID_HANDLE) IndicatorRelease(handleFast);
if(handleSlow != INVALID_HANDLE) IndicatorRelease(handleSlow);
if(handleTrend != INVALID_HANDLE) IndicatorRelease(handleTrend);
Print("NoCodeStarterEA removed. Reason code: ", reason);
}
//+------------------------------------------------------------------+
//| Helper — count open positions for this EA on this symbol |
//+------------------------------------------------------------------+
int CountPositions(ENUM_POSITION_TYPE posType)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) == _Symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber &&
PositionGetInteger(POSITION_TYPE) == posType)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Helper — send a market order |
//+------------------------------------------------------------------+
bool SendOrder(ENUM_ORDER_TYPE orderType, double volume)
{
MqlTradeRequest request = {};
MqlTradeResult result = {};
double price = (orderType == ORDER_TYPE_BUY)
? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
double pip = (digits == 3 || digits == 5) ? 10 * point : point;
double slDist = StopLossPips * pip;
double tpDist = TakeProfitPips * pip;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = volume;
request.type = orderType;
request.price = NormalizeDouble(price, digits);
request.deviation = 5;
request.magic = MagicNumber;
request.comment = TradeComment;
request.type_filling = ORDER_FILLING_FOK;
if(orderType == ORDER_TYPE_BUY)
{
request.sl = NormalizeDouble(price - slDist, digits);
request.tp = NormalizeDouble(price + tpDist, digits);
}
else
{
request.sl = NormalizeDouble(price + slDist, digits);
request.tp = NormalizeDouble(price - tpDist, digits);
}
bool sent = OrderSend(request, result);
if(!sent || result.retcode != TRADE_RETCODE_DONE)
Print("OrderSend failed. Retcode=", result.retcode, " Comment=", result.comment);
return sent && result.retcode == TRADE_RETCODE_DONE;
}
//+------------------------------------------------------------------+
//| Main tick function — EA logic runs here on every price tick |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Only act on a newly closed bar (once per bar logic)
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
if(currentBarTime <= 0 || currentBarTime == lastBarTime) return;
//--- Copy latest two values from each indicator buffer
if(CopyBuffer(handleFast, 0, 0, 3, fastBuf) < 3) return;
if(CopyBuffer(handleSlow, 0, 0, 3, slowBuf) < 3) return;
if(CopyBuffer(handleTrend, 0, 0, 3, trendBuf) < 3) return;
lastBarTime = currentBarTime;
if(CountPositions(POSITION_TYPE_BUY) + CountPositions(POSITION_TYPE_SELL) > 0) return;
//--- Current and previous bar values
double fastNow = fastBuf[1];
double fastPrev = fastBuf[2];
double slowNow = slowBuf[1];
double slowPrev = slowBuf[2];
double trendNow = trendBuf[1];
double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
//--- Bullish crossover: fast crosses above slow while price above trend MA
bool bullCross = (fastPrev <= slowPrev) && (fastNow > slowNow) && (askPrice > trendNow);
//--- Bearish crossover: fast crosses below slow while price below trend MA
bool bearCross = (fastPrev >= slowPrev) && (fastNow < slowNow) && (bidPrice < trendNow);
//--- Enter long if no existing buy
if(bullCross && CountPositions(POSITION_TYPE_BUY) == 0)
{
Print("BUY signal: Fast=", fastNow, " Slow=", slowNow, " Trend=", trendNow);
SendOrder(ORDER_TYPE_BUY, LotSize);
}
//--- Enter short if no existing sell
if(bearCross && CountPositions(POSITION_TYPE_SELL) == 0)
{
Print("SELL signal: Fast=", fastNow, " Slow=", slowNow, " Trend=", trendNow);
SendOrder(ORDER_TYPE_SELL, LotSize);
}
}
//+------------------------------------------------------------------+Copy this code into MetaEditor, save it in your MQL5 folder (Experts, Scripts, or Include), and compile with F7.
Generate custom MQL5 code with Pineify AI
Describe the trade execution, indicator calculations, risk management, or data processing logic you need. Pineify generates editable MQL5 source code. Review its logic, request a syntax check, and compile and test the final file in MetaEditor.
Pine Script vs MQL5: Same Strategy, Different Platforms
| Aspect | Pine Script (TradingView) | MQL5 (MetaTrader 5) |
|---|---|---|
| Execution | Series evaluated on chart updates | Event handlers with explicit buffers |
| Deployment | Runs in TradingView with alerts | Runs in the MT5 terminal or on a VPS |
| Broker access | Strategy orders are simulated; live automation needs a separate integration | Direct broker connectivity |
| Backtesting | Strategy Tester for strategy scripts | Strategy Tester for Expert Advisors |
| Code complexity | Simpler, functional syntax | C++-like, more powerful |
The calculation can be implemented on either platform, but the runtime model and buffer APIs differ.
Frequently Asked Questions
Related MQL5 pages
Technical references
Risk and testing note
These educational examples require independent compilation and testing. A compile pass or an illustrative setting does not establish execution correctness or profitability. Any reported performance must be supported by reproducible data and test settings; past results do not predict future returns. Trading involves significant risk of loss. This content is not financial advice.