AI MQL5 Code Generator: Generate Expert Advisors with AI (2026)
Turn a written trading specification into editable MQL5 source, then review it in MetaEditor. This guide uses a dual-MA example to explain handles, closed-bar data and trade-result checks. AI output still needs compilation, broker-specific validation and testing; generating an EA is not evidence that it is profitable or ready for live trading.
Implementation details & mechanics
Core implementation pattern
The teaching EA compares two completed bars of a fast and slow moving average and requests a trade on a crossover. CopyBuffer writes older copied values first in these static arrays: index 0 is bar 2 and index 1 is bar 1. The sample uses fixed lots and IOC filling, so symbol volume steps, stop distances and supported filling modes must be checked for the selected broker.
Error handling & safety rules
On an opposite crossover the example requests closure of positions matching its symbol and magic number, then requests the new direction. This is not an atomic reversal: a rejected or partial close requires reconciliation before further trading. Compile and test on a demo account; shared magic numbers, netting accounts and simultaneous charts need an explicit ownership policy.
MQL5 Code Implementation
//+------------------------------------------------------------------+
//| AI_MA_Crossover_Demo.mq5 |
//| Teaching example — reviewable dual-MA Expert Advisor scaffold|
//| Demonstrates the boilerplate structure an AI tool produces. |
//| NOT a production strategy — review and test before live use. |
//+------------------------------------------------------------------+
#property copyright "Pineify.app"
#property link "https://pineify.app"
#property version "1.00"
#property strict
//--- Input parameters (AI generator exposes these as user controls)
input int FastMAPeriod = 10; // Fast MA period
input int SlowMAPeriod = 30; // Slow MA period
input ENUM_MA_METHOD MAMethod = MODE_EMA; // MA smoothing method
input double LotSize = 0.1; // Trade volume in lots
input int MagicNumber = 202600; // Unique EA identifier
input int Slippage = 3; // Max allowed slippage (points)
input double StopLossPips = 50.0; // Stop loss in pips
input double TakeProfitPips = 100.0; // Take profit in pips
//--- Global handles and state
int g_fastMAHandle = INVALID_HANDLE;
int g_slowMAHandle = INVALID_HANDLE;
double g_point = 0.0;
//+------------------------------------------------------------------+
//| Expert initialisation |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Validate period inputs
if(FastMAPeriod >= SlowMAPeriod)
{
Print("ERROR: FastMAPeriod must be less than SlowMAPeriod.");
return INIT_PARAMETERS_INCORRECT;
}
//--- Create indicator handles (MQL5 handle-based pattern)
g_fastMAHandle = iMA(_Symbol, _Period, FastMAPeriod, 0, MAMethod, PRICE_CLOSE);
g_slowMAHandle = iMA(_Symbol, _Period, SlowMAPeriod, 0, MAMethod, PRICE_CLOSE);
if(g_fastMAHandle == INVALID_HANDLE || g_slowMAHandle == INVALID_HANDLE)
{
Print("ERROR: Failed to create MA indicator handles.");
return INIT_FAILED;
}
//--- Cache point size for pip calculations
g_point = _Point;
if(_Digits == 3 || _Digits == 5)
g_point *= 10; // Normalise to a full pip for 3/5-digit brokers
Print("AI_MA_Crossover_Demo initialised on ", _Symbol,
" | Fast MA: ", FastMAPeriod, " | Slow MA: ", SlowMAPeriod);
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Release indicator handles to free terminal resources
if(g_fastMAHandle != INVALID_HANDLE)
IndicatorRelease(g_fastMAHandle);
if(g_slowMAHandle != INVALID_HANDLE)
IndicatorRelease(g_slowMAHandle);
Print("AI_MA_Crossover_Demo removed. Reason code: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick handler |
//+------------------------------------------------------------------+
void OnTick()
{
//--- Only act on a new bar to avoid repeated signals on the same candle
static datetime s_lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, _Period, 0);
if(currentBarTime == s_lastBarTime)
return;
s_lastBarTime = currentBarTime;
//--- Copy closed bars 2 and 1; static arrays store the older value first
double fastMA[2], slowMA[2];
if(CopyBuffer(g_fastMAHandle, 0, 1, 2, fastMA) < 2 ||
CopyBuffer(g_slowMAHandle, 0, 1, 2, slowMA) < 2)
{
Print("WARNING: Insufficient indicator data on ", _Symbol);
return;
}
//--- Detect crossover direction
bool bullishCross = (fastMA[0] <= slowMA[0]) && (fastMA[1] > slowMA[1]);
bool bearishCross = (fastMA[0] >= slowMA[0]) && (fastMA[1] < slowMA[1]);
//--- Close opposing position then open a new one on crossover
if(bullishCross)
{
ClosePositions(ORDER_TYPE_SELL);
OpenPosition(ORDER_TYPE_BUY);
}
else if(bearishCross)
{
ClosePositions(ORDER_TYPE_BUY);
OpenPosition(ORDER_TYPE_SELL);
}
}
//+------------------------------------------------------------------+
//| Open a market position with SL and TP |
//+------------------------------------------------------------------+
void OpenPosition(ENUM_ORDER_TYPE orderType)
{
//--- Avoid duplicate positions managed by this EA
if(CountPositions(orderType) > 0)
return;
MqlTradeRequest request = {};
MqlTradeResult result = {};
double price = (orderType == ORDER_TYPE_BUY)
? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl = (orderType == ORDER_TYPE_BUY)
? price - StopLossPips * g_point
: price + StopLossPips * g_point;
double tp = (orderType == ORDER_TYPE_BUY)
? price + TakeProfitPips * g_point
: price - TakeProfitPips * g_point;
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = LotSize;
request.type = orderType;
request.price = price;
request.sl = NormalizeDouble(sl, _Digits);
request.tp = NormalizeDouble(tp, _Digits);
request.deviation = Slippage;
request.magic = MagicNumber;
request.comment = "AI_MA_Cross";
request.type_filling = ORDER_FILLING_IOC;
if(!OrderSend(request, result) ||
(result.retcode != TRADE_RETCODE_DONE && result.retcode != TRADE_RETCODE_DONE_PARTIAL))
Print("OrderSend failed: ", result.retcode, " — ", result.comment);
else
Print("Position opened: ", EnumToString(orderType),
" @ ", price, " | Ticket: ", result.order);
}
//+------------------------------------------------------------------+
//| Close all positions of a given type managed by this EA |
//+------------------------------------------------------------------+
void ClosePositions(ENUM_ORDER_TYPE typeToClose)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE) != typeToClose) continue;
MqlTradeRequest req = {};
MqlTradeResult res = {};
req.action = TRADE_ACTION_DEAL;
req.symbol = _Symbol;
req.volume = PositionGetDouble(POSITION_VOLUME);
req.position = ticket;
req.type = (typeToClose == ORDER_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
req.price = (req.type == ORDER_TYPE_SELL)
? SymbolInfoDouble(_Symbol, SYMBOL_BID)
: SymbolInfoDouble(_Symbol, SYMBOL_ASK);
req.deviation = Slippage;
req.magic = MagicNumber;
req.type_filling = ORDER_FILLING_IOC;
if(!OrderSend(req, res) ||
(res.retcode != TRADE_RETCODE_DONE && res.retcode != TRADE_RETCODE_DONE_PARTIAL))
Print("Close failed: ticket=", ticket, " retcode=", res.retcode);
}
}
//+------------------------------------------------------------------+
//| Count open positions of a given type for this EA |
//+------------------------------------------------------------------+
int CountPositions(ENUM_ORDER_TYPE orderType)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != MagicNumber) continue;
if((ENUM_ORDER_TYPE)PositionGetInteger(POSITION_TYPE) == orderType) count++;
}
return count;
}
//+------------------------------------------------------------------+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.