从入门到精通,系统化的 MT4/MT5 EA 开发学习路径
MQL (MetaQuotes Language) 是 MetaQuotes 公司为 MT4/MT5 平台开发的专用编程语言,用于编写 EA(交易机器人)、自定义指标和脚本。
自动交易机器人,可执行开仓、平仓、止损止盈等操作
自定义技术指标,在图表上显示独特的分析线和信号
一次性执行的脚本,用于批量操作或特定任务
通过DLL调用外部C/C++函数,扩展MQL能力边界
| 特性 | MQL4 (MT4) | MQL5 (MT5) |
|---|---|---|
| 订单模型 | 单订单系统 | 持仓+订单双系统 |
| 执行模式 | OnTick 事件驱动 | OnTick + 多事件模型 |
| 面向对象 | 部分支持 | 完整OOP支持 |
| 回测引擎 | 单线程 | 多线程遗传算法 |
| 市场深度 | 有限 | 完整DOM支持 |
MetaEditor 是 MT4/MT5 内置的集成开发环境,无需额外安装。
从交易商官网下载并安装 MetaTrader 客户端
在 MT 菜单中点击 工具 → MetaQuotes 语言编辑器,或按 F4 快捷键
在 Navigator 面板右键 → 新建 → 选择 EA/指标/脚本 → 按向导完成
让我们编写一个最简单的EA,在图表上打印信息。
//+------------------------------------------------------------------+
//| First_EA.mq4 |
//| Copyright 2024, 晓辉编程 eafxtech.com |
//| https://www.eafxtech.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, 晓辉编程"
#property link "https://www.eafxtech.com"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("EA 已加载: ", Symbol(), " - ", Period());
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
Print("EA 已卸载");
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
double bid = Bid;
double ask = Ask;
int spread = (int)((ask - bid) / Point);
Comment("Bid=", bid, " Ask=", ask, " 点差=", spread);
}
//+------------------------------------------------------------------+
MQL 是强类型语言,变量使用前必须声明类型。
| 类型 | 说明 | 示例 |
|---|---|---|
| int | 32位整数 | int count = 10; |
| double | 双精度浮点数 | double price = 1.23456; |
| bool | 布尔值 true/false | bool isLong = true; |
| string | 字符串 | string name = "EURUSD"; |
| datetime | 日期时间 | datetime now = TimeCurrent(); |
| color | 颜色 | color c = clrRed; |
MQL 支持标准的条件判断和循环结构。
double rsi = iRSI(_Symbol, _Period, 14, PRICE_CLOSE, 0);
if (rsi > 70)
{
Print("超买区域, RSI=", rsi);
}
else if (rsi < 30)
{
Print("超卖区域, RSI=", rsi);
}
else
{
Print("中性区域");
}
// 计算最近10根K线的收盘价均值
double sum = 0;
for (int i = 0; i < 10; i++)
{
sum += Close[i];
}
double avg = sum / 10;
函数是MQL程序的基本构建块,支持传值和传引用。
// 计算移动平均线
double CalcMA(int period, int shift)
{
double sum = 0;
for (int i = shift; i < shift + period; i++)
{
sum += Close[i];
}
return sum / period;
}
// 使用引用参数返回多个值
void GetTradeInfo(int &orders, double &profit)
{
orders = OrdersTotal();
profit = AccountProfit();
}
MQL 支持一维和多维数组,数组索引从0开始。
// 一维数组
double prices[100];
// 二维数组
double matrix[10][10];
// 动态数组 (MQL5)
double dynamicArray[];
ArrayResize(dynamicArray, 100);
// 数组排序
double arr[] = {5, 2, 8, 1, 9};
ArraySort(arr); // 升序排序
通过内置函数获取账户余额、净值、保证金等信息。
| 函数 | 说明 |
|---|---|
| AccountBalance() | 账户余额 |
| AccountEquity() | 账户净值 (余额+浮动盈亏) |
| AccountProfit() | 浮动盈亏 |
| AccountFreeMargin() | 可用保证金 |
| AccountMargin() | 已用保证金 |
| AccountLeverage() | 杠杆倍数 |
| AccountCurrency() | 账户币种 |
MQL4 使用订单编号系统,每张订单有唯一的 ticket 号。
OrderSend 是 MQL4 中下单的核心函数。
// 市价买入示例
int ticket = OrderSend(
Symbol(), // 交易品种
OP_BUY, // 订单类型
0.1, // 手数
Ask, // 开仓价格
3, // 滑点(点)
Bid - 50*Point, // 止损价
Ask + 100*Point, // 止盈价
"My EA Order", // 订单注释
0, // 魔术号
0, // 订单有效期
clrGreen // 箭头颜色
);
if (ticket > 0)
{
Print("下单成功, 订单号: ", ticket);
}
else
{
Print("下单失败, 错误码: ", GetLastError());
}
风控是EA的生命线,必须在开仓前计算好仓位和止损。
// 基于百分比风险计算手数
double CalcLotSize(double stopLossPoints)
{
double riskAmount = AccountBalance() * 0.02;
double valuePerPoint = 10 * 0.01 / 0.0001;
double lotSize = riskAmount / (stopLossPoints * valuePerPoint);
lotSize = NormalizeDouble(lotSize, 2);
double minLot = MarketInfo(_Symbol, MODE_MINLOT);
double maxLot = MarketInfo(_Symbol, MODE_MAXLOT);
lotSize = MathMax(minLot, MathMin(maxLot, lotSize));
return lotSize;
}
高级EA通常需要监控多个品种,捕捉跨品种交易机会。
// 遍历所有交易品种
void ScanAllSymbols()
{
int total = SymbolsTotal(true);
for (int i = 0; i < total; i++)
{
string symbol = SymbolName(i, true);
double spread = SymbolInfoDouble(symbol, SYMBOL_SPREAD);
double vol = CalcVolatility(symbol, 20);
if (vol > 0.01 && spread < 20)
{
Print("关注品种: ", symbol, " 波动率: ", vol);
}
}
}
EA运行效率直接影响实盘表现,尤其是高频策略。
Print() 和 Comment() 是 MQL 调试最常用的工具。
| 方法 | 用途 | 注意事项 |
|---|---|---|
| Print() | 输出到日志 | 支持字符串+数字混合 |
| Comment() | 图表左上角显示 | 实时更新,方便观察变量 |
| Alert() | 弹窗提示 | 触发重要事件时使用 |
| MessageBox() | 模态对话框 | 会暂停EA执行 |
| GetLastError() | 获取错误码 | 交易失败后立即调用 |
良好的代码风格是团队协作和长期维护的基础。
成熟的EA开发中常用的架构模式。
信号生成和订单执行解耦,便于独立测试和替换策略
用枚举管理交易状态:等待信号→挂单→持仓→平仓
所有开仓请求先过风控层,统一校验手数、止损、风险限额
独立模块收集交易统计,输出CSV用于分析和复盘
新手最容易踩的坑,提前避坑少走弯路。
访问 iBarShift 或价格数组前,务必检查 Bars 数量是否足够
实盘点差波动大,滑点设太小会导致频繁下单失败,建议设 30-50 点
iMA 等指标第0根K线值会变化,策略信号应使用第1根及以后的K线
Point 在五位数平台是 0.00001,止损计算要用 _Digits 判断
OrderSelect 后必须检查返回值,遍历订单时注意索引变化