MT4/5 概览 文件架构 指标 EA 脚本 安装部署 回测 MT4→MT5 避坑指南
完全实战教程 · COMPREHENSIVE TUTORIAL

MT4 / MT5
指标 · EA · 脚本
运用教程

从零到实战:自定义指标编写、EA自动交易、脚本批量操作的完整知识图谱
📐
第零章:三大组件全景图
OVERVIEW — INDICATOR vs EA vs SCRIPT

MetaTrader平台的MQL语言体系中有三类可执行程序,它们各有职责、互不替代:

维度 自定义指标 (Indicator) 智能交易 (EA) 脚本 (Script)
文件后缀 .mq4 / .mq5 .mq4 / .mq5 .mq4 / .mq5
编译后缀 .ex4 / .ex5 .ex4 / .ex5 .ex4 / .ex5
核心功能 在图表上绘制可视化信号(箭头、线段、直方图等) 根据逻辑自动开仓、平仓、修改订单 执行一次性任务后自动退出
能否下单 ❌ 不能 ✅ 可以 ✅ 可以
运行方式 持续运行,每个Tick/K线刷新 持续运行,每个Tick触发OnTick() 执行一次后自动卸载
每图表限制 可挂载多个 仅能挂1个 仅能挂1个
典型用途 MACD、RSI变体、自定义信号箭头 网格交易、趋势跟踪、马丁格尔 一键全部平仓、批量修改止损、导出数据
安装目录 MQL4(5)/Indicators/ MQL4(5)/Experts/ MQL4(5)/Scripts/
MetaTrader 平台 (MT4 / MT5) INDICATOR 指标 📊 图表绘制 🔔 弹窗/推送报警 📈 缓冲区数据输出 OnCalculate() ❌ 不能下单交易 EXPERT ADVISOR (EA) 🤖 自动开仓/平仓 📋 订单管理/修改 🛡 风控/资金管理 OnTick() / OnTimer() ✅ 完整交易能力 SCRIPT 脚本 ⚡ 一次性批量操作 🗑 一键全平/删挂单 📤 导出数据到文件 OnStart() — 执行1次 ⚡ 运行后自动退出
MT4/MT5 三大可执行组件架构图
📁
第一章:目录结构与文件架构
DIRECTORY STRUCTURE & FILE ORGANIZATION
📁 MQL4/ (或 MQL5/) 📁 Indicators/ ← 自定义指标放这里 MyIndicator.mq4 源代码 MyIndicator.ex4 编译后(自动) 📁 SubFolder/ 可建子目录分类 📁 Experts/ ← EA智能交易放这里 MyEA.mq4 EA源代码 MyEA.ex4 编译后 📁 Scripts/ ← 脚本放这里 CloseAllOrders.mq4 脚本源代码 📁 Include/ ← 公共头文件(.mqh)
MQL4 / MQL5 文件目录结构图
💡
如何快速找到目录?
在MetaTrader中点击 文件 → 打开数据文件夹(File → Open Data Folder),即可直接打开MQL4/MQL5根目录。MT5中也可在MetaEditor中点击 File → Open Data Folder
📊
第二章:自定义指标 (Indicator) 完全教程
CUSTOM INDICATOR — FULL TUTORIAL
指标是什么?

指标是纯视觉工具,它通过数学运算将价格/成交量数据转化为图表上的可视化元素(线条、箭头、柱状图、色块等),帮助交易者识别市场状态。指标不能自动下单,但可以发出弹窗/声音/推送报警。

指标生命周期
OnInit()
初始化
OnCalculate()
每Tick循环
OnDeinit()
卸载清理
MT4 指标最小模板
MQL4 SimpleMA_MT4.mq4
//+------------------------------------------------------------------+ //| 一个最简单的均线指标模板 | //+------------------------------------------------------------------+ #property indicator_chart_window // 显示在主图(非副图) #property indicator_buffers 1 // 1条线 #property indicator_color1 clrDodgerBlue #property indicator_width1 2 // 输入参数(用户可在属性面板调整) input int MA_Period = 20; // 均线周期 // 指标缓冲区 double MA_Buffer[]; //--- 初始化 int OnInit() { SetIndexBuffer(0, MA_Buffer); // 绑定缓冲区 SetIndexStyle(0, DRAW_LINE); // 画线模式 SetIndexLabel(0, "MA(" + IntegerToString(MA_Period) + ")"); return(INIT_SUCCEEDED); } //--- 核心计算(每个新Tick触发) int OnCalculate(const int rates_total, const int prev_calculated, ...) { int start = (prev_calculated > 0) ? prev_calculated - 1 : MA_Period; for(int i = start; i < rates_total; i++) { double sum = 0; for(int j = 0; j < MA_Period; j++) sum += Close[rates_total - 1 - i + j]; // MT4旧式索引 MA_Buffer[i] = sum / MA_Period; } return(rates_total); }
MT5 指标模板(对比差异)
MQL5 SimpleMA_MT5.mq5
#property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 // ★ MT5必须声明plots数 #property indicator_label1 "MA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrDodgerBlue #property indicator_width1 2 input int MA_Period = 20; double MA_Buffer[]; int handleMA; // ★ MT5用句柄 int OnInit() { SetIndexBuffer(0, MA_Buffer, INDICATOR_DATA); // ★ 第三参数 handleMA = iMA(_Symbol, PERIOD_CURRENT, MA_Period, 0, MODE_SMA, PRICE_CLOSE); // ★ 内置指标句柄 return(INIT_SUCCEEDED); } int OnCalculate(const int rates_total, const int prev_calculated, ...) { // ★ MT5直接从句柄拷贝数据,无需手算 CopyBuffer(handleMA, 0, 0, rates_total, MA_Buffer); return(rates_total); } void OnDeinit(const int reason) { IndicatorRelease(handleMA); // ★ 释放句柄 }
MT4 vs MT5 关键差异:MT5必须声明 indicator_plots,使用 SetIndexBuffer(idx, buf, INDICATOR_DATA) 三参数形式,内置指标通过句柄 (handle) 访问而非直接函数调用,且缓冲区索引方向为正序(0=最旧)而非MT4的倒序。
指标绘制模式一览
绘制模式效果典型应用
DRAW_LINE连续折线均线、布林带中轨
DRAW_HISTOGRAM零轴柱状图MACD柱、成交量
DRAW_ARROW独立箭头/符号买卖信号标记
DRAW_SECTION折线连接(跳过空值)ZigZag指标
DRAW_NONE不绘制(仅数据输出)给EA提供数据
DRAW_FILLING MT5两线间填色一目均衡表云层
DRAW_COLOR_LINE MT5逐段变色线趋势颜色线
DRAW_CANDLES MT5自定义蜡烛平均K线(Heikin Ashi)
🤖
第三章:EA智能交易 (Expert Advisor) 完全教程
EXPERT ADVISOR — FULL TUTORIAL
EA是什么?

EA是自动交易机器人。它可以独立监控市场、判断条件、自动下单、管理仓位、设置止损止盈——完全不需要人工干预。EA是MQL体系中唯一能持续自动交易的组件。

EA生命周期 & 事件模型
OnInit()
初始化
OnTick()
每个报价
OnTimer()
定时器(可选)
OnDeinit()
卸载

OnTick() 是EA的心脏——每次价格变动都会触发一次。你的全部交易逻辑都写在这个函数里。

MT4 EA 最小交易模板
MQL4 SimpleEA_MT4.mq4
//+------------------------------------------------------------------+ //| 均线交叉EA模板 — MT4 | //+------------------------------------------------------------------+ input double LotSize = 0.01; // 手数 input int FastMA = 9; // 快线周期 input int SlowMA = 21; // 慢线周期 input int StopLoss = 50; // 止损点数 input int TakeProfit = 100; // 止盈点数 input int MagicNumber = 20260412; // 魔术号(识别本EA订单) void OnTick() { // 1. 计算均线值 double fast_now = iMA(NULL, 0, FastMA, 0, MODE_EMA, PRICE_CLOSE, 1); double fast_prev = iMA(NULL, 0, FastMA, 0, MODE_EMA, PRICE_CLOSE, 2); double slow_now = iMA(NULL, 0, SlowMA, 0, MODE_EMA, PRICE_CLOSE, 1); double slow_prev = iMA(NULL, 0, SlowMA, 0, MODE_EMA, PRICE_CLOSE, 2); // 2. 检查是否已有持仓 int total = OrdersTotal(); bool hasPosition = false; for(int i = 0; i < total; i++) { if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol()) { hasPosition = true; break; } } if(hasPosition) return; // 已有仓位则不再开仓 // 3. 金叉 → 做多 if(fast_prev <= slow_prev && fast_now > slow_now) { double sl = Ask - StopLoss * Point; double tp = Ask + TakeProfit * Point; OrderSend(Symbol(), OP_BUY, LotSize, Ask, 3, sl, tp, "MA Cross Buy", MagicNumber, 0, clrGreen); } // 4. 死叉 → 做空 if(fast_prev >= slow_prev && fast_now < slow_now) { double sl = Bid + StopLoss * Point; double tp = Bid - TakeProfit * Point; OrderSend(Symbol(), OP_SELL, LotSize, Bid, 3, sl, tp, "MA Cross Sell", MagicNumber, 0, clrRed); } }
MT5 EA 模板(订单系统差异巨大)
MQL5 SimpleEA_MT5.mq5
#include <Trade/Trade.mqh> // ★ MT5标准交易库 input double LotSize = 0.01; input int FastMA = 9; input int SlowMA = 21; input int SL_Points = 50; input int TP_Points = 100; input ulong MagicNum = 20260412; CTrade trade; // ★ 交易对象 int hFast, hSlow; // ★ 指标句柄 int OnInit() { trade.SetExpertMagicNumber(MagicNum); hFast = iMA(_Symbol, PERIOD_CURRENT, FastMA, 0, MODE_EMA, PRICE_CLOSE); hSlow = iMA(_Symbol, PERIOD_CURRENT, SlowMA, 0, MODE_EMA, PRICE_CLOSE); return(INIT_SUCCEEDED); } void OnTick() { // ★ MT5通过CopyBuffer获取指标数据 double fast[], slow[]; CopyBuffer(hFast, 0, 1, 2, fast); // 取[1]和[2]两根K线的值 CopyBuffer(hSlow, 0, 1, 2, slow); // ★ MT5用PositionsTotal()检查持仓 if(PositionsTotal() > 0) return; double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double pt = SymbolInfoDouble(_Symbol, SYMBOL_POINT); // 金叉做多 if(fast[0] <= slow[0] && fast[1] > slow[1]) trade.Buy(LotSize, _Symbol, ask, ask - SL_Points * pt, ask + TP_Points * pt, "MA Cross"); // 死叉做空 if(fast[0] >= slow[0] && fast[1] < slow[1]) trade.Sell(LotSize, _Symbol, bid, bid + SL_Points * pt, bid - TP_Points * pt, "MA Cross"); }
MT5订单系统重构:MT4用 OrderSend() 一个函数搞定一切;MT5用 CTrade 交易类(或 OrderSend(MqlTradeRequest) 结构体)。MT5区分挂单(pending orders)持仓(positions)——这是最大的迁移陷阱。
OnTick() 新报价到达 ① 读取指标数据 ② 检查开仓条件 ③ 检查平仓条件 条件满足 ✅ 不满足 → 等待 ④ 执行交易指令 OrderSend / trade.Buy ⑤ 风控检查 SL/TP/日损限额/仓位管理 等待下一个 Tick ↺
EA OnTick() 事件循环流程图
第四章:脚本 (Script) 完全教程
SCRIPT — ONE-SHOT AUTOMATION
脚本是什么?

脚本是一次性执行的程序——拖到图表上 → 运行 → 完成任务 → 自动退出。不会像指标和EA那样持续运行。最常见的用途是"一键全平"、"批量修改止损"、"导出交易记录"等应急/批量操作。

经典脚本:一键平仓所有订单 (MT4)
MQL4 · SCRIPT CloseAll_MT4.mq4
//+------------------------------------------------------------------+ //| 一键平仓所有订单 | //+------------------------------------------------------------------+ #property script_show_inputs // 运行前弹出参数对话框 input bool CloseMarket = true; // 平仓市价单? input bool DeletePending = true; // 删除挂单? void OnStart() // ★ 脚本只有OnStart()! { int closed = 0, deleted = 0; // 倒序遍历(重要!正序会跳过订单) for(int i = OrdersTotal() - 1; i >= 0; i--) { if(!OrderSelect(i, SELECT_BY_POS)) continue; // 平仓市价单 if(CloseMarket && (OrderType() == OP_BUY || OrderType() == OP_SELL)) { double price = (OrderType() == OP_BUY) ? Bid : Ask; if(OrderClose(OrderTicket(), OrderLots(), price, 3)) closed++; } // 删除挂单 if(DeletePending && OrderType() > OP_SELL) { if(OrderDelete(OrderTicket())) deleted++; } } Alert("完成: 平仓 " + closed + " 单, 删除挂单 " + deleted + " 个"); } // OnStart结束 → 脚本自动卸载
MT5版本 — 一键平仓
MQL5 · SCRIPT CloseAll_MT5.mq5
#include <Trade/Trade.mqh> #property script_show_inputs input bool ClosePositions = true; input bool DeleteOrders = true; void OnStart() { CTrade trade; int closed = 0, deleted = 0; // ★ MT5: 持仓和挂单是分开的! // 平仓 if(ClosePositions) { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(trade.PositionClose(ticket)) closed++; } } // 删除挂单 if(DeleteOrders) { for(int i = OrdersTotal() - 1; i >= 0; i--) { ulong ticket = OrderGetTicket(i); if(trade.OrderDelete(ticket)) deleted++; } } Alert("Done: Closed " + closed + ", Deleted " + deleted); }
💡
脚本使用技巧:可以在MT4/MT5中为脚本绑定快捷键。进入 工具 → 自定义 → 键盘快捷键,将"一键平仓"脚本绑定到如 Ctrl+Shift+X,实现紧急一键清仓。
🔧
第五章:安装与部署全流程
INSTALLATION & DEPLOYMENT GUIDE
指标安装步骤
复制文件:.mq4/.mq5 文件复制到对应目录。MT4: MQL4/Indicators/;MT5: MQL5/Indicators/。可通过 文件 → 打开数据文件夹 快速定位。
编译:打开MetaEditor(按F4),找到你的文件,按 F7 或点击编译按钮。确认底部输出栏显示 0 errors。编译成功后会生成 .ex4/.ex5 文件。
刷新导航栏:回到MT主界面,在左侧"导航器"面板的"指标"文件夹上 右键 → 刷新。你的指标应该出现在列表中。
挂载到图表:双击指标名或将其拖拽到图表上。在弹出的属性对话框中调整参数,点击确定。指标即开始运行。
EA安装步骤(额外关键设置!)
复制 & 编译:文件放入 MQL4/Experts/(或MQL5/Experts/),在MetaEditor中编译(F7)。
挂载到图表:从导航器的"Expert Advisors"中拖拽到图表上。
⚠ 启用自动交易:这是新手最容易遗漏的步骤!点击工具栏上的 "自动交易"按钮(AutoTrading),确保按钮变为绿色。同时在EA属性的"通用"页签中勾选 "允许实时交易"(Allow live trading)。
确认运行:图表右上角应显示一个笑脸😊图标。如果是哭脸😞,说明EA未被允许交易——回去检查第3步。
双重开关!EA要正常交易需要两个开关同时打开:①工具栏的"AutoTrading"全局开关(绿色);②EA属性中的"Allow live trading"(勾选)。任缺其一EA都无法下单。
✅ EA正常运行状态 工具栏: AutoTrading = 🟢 EA属性: Allow Trading = ☑ 😊 笑脸图标 ❌ EA被禁用状态 工具栏: AutoTrading = 🔴 或 EA属性: Allow Trading = ☐ 😞 哭脸图标(不能下单!)
EA运行状态对照
🔬
第六章:策略测试器(回测)
STRATEGY TESTER & BACKTESTING
回测流程
打开策略测试器:Ctrl+R 或菜单 查看 → 策略测试器
选择EA:在"Expert Advisor"下拉框中选择你的EA。
设定参数:选择品种、时间周期(如M1)、测试区间(起止日期)、初始资金、点差模型。
选择测试模式:
· 每个Tick(Every tick)— 最精确,最慢
· 控制点(Control points)— 中等精度
· 仅开盘价(Open prices only)— 最快,仅适合基于K线收盘逻辑的策略
运行 & 分析:点击"开始"。完成后查看结果(Results)图表(Graph)报告(Report)标签页。
回测报告关键指标解读
指标含义合格标准
Total Net Profit净利润> 0(基本要求)
Profit Factor盈亏比 = 总盈利/总亏损> 1.5 为良好
Max Drawdown最大回撤(峰值到谷值的最大跌幅)< 20% 为可控
Total Trades总交易次数> 100 才有统计意义
Win Rate胜率取决于盈亏比(低胜率+高盈亏比也可盈利)
Expected Payoff每笔交易的期望收益> 0 且 > 点差成本
Sharpe Ratio MT5风险调整后收益> 1.0 为优秀
MT4 vs MT5 回测引擎差异:MT4策略测试器仅支持单品种、单线程,数据质量依赖经纪商。MT5策略测试器支持多品种多线程真实Tick数据前瞻分析(Forward Testing)MQL5 Cloud Network分布式优化——回测速度和精度远超MT4。
🔄
第七章:MT4 → MT5 迁移速查表
MT4 TO MT5 MIGRATION CHEAT SHEET
功能MT4 (MQL4)MT5 (MQL5)
下单 OrderSend(...) CTrade::Buy() / Sell()
OrderSend(MqlTradeRequest)
遍历持仓 OrdersTotal() + OrderSelect() PositionsTotal() + PositionGetTicket()
遍历挂单 同上(OrderType()>OP_SELL) OrdersTotal() + OrderGetTicket()
内置指标调用 iMA(sym,tf,period,...,shift) 直接返回值 int h = iMA(...) 返回句柄
+CopyBuffer(h,...) 获取值
价格数据 Open[], Close[], High[], Low[] 全局数组(倒序,0=当前) OnCalculate()参数传入(正序,0=最旧)
获取Ask/Bid Ask, Bid 全局变量 SymbolInfoDouble(_Symbol, SYMBOL_ASK/BID)
指标缓冲区 SetIndexBuffer(idx, buf) SetIndexBuffer(idx, buf, INDICATOR_DATA)
plots声明 不需要 #property indicator_plots N 必须声明
对冲 天然支持(同品种可多空同时持仓) 需开启Hedging账户模式(非默认的Netting)
策略测试器 单线程,单品种 多线程,多品种,真实Tick,云优化
🚨
第八章:常见陷阱与避坑指南
COMMON PITFALLS & GOTCHAS
TOP 10 新手致命错误
#错误后果正确做法
1忘记开AutoTrading开关EA静默不下单每次开机第一件事:检查绿色按钮
2正序遍历订单并平仓跳过一半订单始终倒序遍历:for(i=Total-1; i>=0; i--)
3不用MagicNumberEA误操作其他EA的订单每个EA分配唯一的MagicNumber
4在指标中调用OrderSend编译报错或崩溃指标只能画图和报警,下单逻辑写在EA中
5MT5用MT4语法下单编译失败MT5必须用CTrade类或MqlTradeRequest结构
6不检查OrderSend返回值下单失败无感知始终检查返回值并记录GetLastError()
7回测用"仅开盘价"模式测试剥头皮EA回测结果严重失真剥头皮策略必须用"每个Tick"模式
8在OnCalculate()中用Sleep()界面冻结指标中禁止用Sleep/MessageBox等阻塞函数
9不释放MT5指标句柄内存泄漏OnDeinit()中调用IndicatorRelease(handle)
10直接在实盘跑未经回测的EA资金灾难先回测 → 再模拟盘 → 最后小资金实盘
推荐的EA上线流程
编写代码
MetaEditor
回测验证
策略测试器
模拟盘
Demo 30天+
小资金实盘
最小手数
逐步加仓
风控优先
💡
终极建议:所有策略必须先在模拟盘上运行至少30天,经历各种市场状态后,再考虑以最小手数上实盘。模拟盘的目的不是看能赚多少钱,而是发现代码中隐藏的Bug——因为实盘的Bug价格是用真金白银来支付的。