MQL5 编程入门:程序类型、事件模型与下单
从零理解 MQL5——三类程序、事件驱动骨架、自定义指标与 EA 下单的完整最小范式。
一、MQL5 是什么
MQL5(MetaQuotes Language 5)是 MT5 平台的专属编程语言,用于写 EA、自定义指标、脚本和函数库。它语法接近 C++,支持类、结构体、数组、事件处理,但运行在交易终端的沙箱里,不能直接操作文件系统和网络(除规定接口)。理解「它是 C++ 风格 + 交易专用」能少走很多弯路。
和 MQL4 相比,MQL5 是事件驱动、支持多线程(测试器里可并行优化)、区分持仓(Position)/订单(Order)/成交(Deal) 三类对象。这个区分是新手最大的认知门槛。
二、程序结构:事件函数
EA 的核心是一组事件处理函数:OnInit(初始化,建句柄、读参数)、OnDeinit(退出,释放资源)、OnTick(每来一个 tick 触发,放主逻辑)、OnTrade(成交/持仓变化时触发)。指标则是 OnCalculate(每根 K 线数据更新时触发)。程序不是顺序执行的脚本,而是「等事件来,再响应」。
int OnInit() { /* 建句柄、初始化 */ return INIT_SUCCEEDED; }
void OnTick() { /* 主逻辑:算信号、下单 */ }
void OnDeinit(const int reason) { /* 释放句柄 */ }
三、持仓 / 订单 / 成交 三对象
MQL5 把交易拆成三个清晰对象:Order 是你发出的指令(挂着的或已成交的),Deal 是实际发生的成交记录,Position 是当前持有的净仓位。查持仓用 PositionsTotal / PositionGetInteger,查历史订单用 HistorySelect + OrdersHistoryTotal。混淆这三者是取数错误的根源。
最常被问的是「我当前持了多少」。答案是看 Position(净仓位),而不是 Order。MQL5 的持仓是净额制(同一品种一个 Position),这和 MQL4 的锁仓制不同,写加仓逻辑时要特别注意。
四、数据类型与数组
MQL5 有 int/double/string/bool/datetime/color 等类型,数组默认是动态的可用 ArrayResize 调整。时间序列(如收盘价)用 double& price[] 这种带 & 的引用数组接收,由终端填充。写循环处理 K 线时,索引 0 是最新一根,越往里越旧——这个倒序容易搞反。
五、类与标准库
MQL5 支持面向对象,标准库已封装好常用组件:CTrade(下单)、CIndicators(指标)、CFile(文件)、CChart(图表操作)等。熟练使用标准库能省掉大量重复代码,也避免自己写出有 bug 的底层逻辑。
六、常见新手坑
- 索引 0 是最新 K 线,循环方向别写反
- 持仓是净额制,加仓逻辑不同于 MQL4
- 数组要先 ArrayResize 或由其自动扩容再写入
- 事件函数里别写死循环,会卡死终端
- 浮点比较要用容差,不能直接 ==
七、调试入门
最朴素的调试是 Print() 打印变量、Comment() 在图上显示状态;更复杂可用 __LINE__、GetLastError() 定位;测试器里开可视化模式能边跑边看。养成「先打印再假设」的习惯,比盯着代码空想高效得多。
八、事件驱动的思维转换
从脚本思维转到事件思维,是学 MQL5 最大的坎:你不再「从头跑到尾」,而是「等 tick 来调我」。好处是终端只在有事时唤醒你的代码,效率高;代价是你必须自己维护状态——例如「是否已开仓」「上一次信号值是多少」,不能假设变量在两次 OnTick 之间保持你以为的值。把状态显式存进全局变量或文件,是事件编程的基本功。