游客发表

mql5编程

发帖时间:2026-10-17 05:11:00

打开MetaEditor,新建一个.mq5文件,你会看到OnInit、OnDeinit、OnTick三个函数骨架。这就是MQL5的全部起点。别被C++-like的语法吓到,它比C++简单得多——没有指针运算,没有模板元编程,内存管理基本交给平台。但它的能力边界比MQL4宽了整整一圈:多线程回测、面向对象、事件驱动、自定义指标句柄,这些在MQL4里要么没有要么残缺。

我最早写MQL4的时候,习惯把所有逻辑塞进OnTick里,用一堆全局变量传来传去。迁到MQL5后第一次被编译器教做人:OrderSend的参数从7个变成了11个,而且必须用MqlTradeRequest结构体。当时觉得麻烦,后来才明白这种设计的好处——请求和结果分离,异步执行,出错时能精确知道是哪个字段的问题。

指标调用方式的根本改变

MQL5不再支持iMA、iRSI这类直接返回数值的函数。取而代之的是先创建指标句柄,再用CopyBuffer取数据。这个变化让很多人不适应,但它解决了一个老问题:MQL4里每次调用iMA都会重新计算一遍指标,EA跑久了CPU直接拉满。MQL5的句柄机制只计算一次,后续都是读缓存。

int handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE); double buf[]; ArraySetAsSeries(buf, true); CopyBuffer(handle, 0, 0, 3, buf);

注意ArraySetAsSeries这行。不设的话,buf[0]是最老的数据而不是最新的。这个坑我踩过不止一次,回测结果和实盘对不上,查了半天才发现是数组顺序问题。

订单系统的重构

MQL5把订单(Order)和持仓(Position)彻底分开了。在MQL4里你下一单,它就变成一个订单,平仓就是关闭这个订单。MQL5不是这样:你发一个市价单请求,平台先创建一个订单,订单成交后生成一个持仓,订单本身消失。听起来绕,但这是Netting和Hedging账户模式统一处理的前提。

查持仓用PositionsTotal()和PositionGetSymbol(),查挂单用OrdersTotal()和OrderGetTicket()。两套API不能混用。我曾经写过一个函数想同时遍历持仓和挂单,结果在Hedging账户上跑得好好的,换到Netting账户直接乱套——因为Netting模式下同品种只有一个持仓,逻辑完全不一样。

CTrade类:省事但别全信

标准库里的CTrade封装了大部分交易操作,PositionOpen、PositionClose、Buy、Sell,用起来确实快。但它默认的滑点设置是0,在真实账户上可能反复拒单。我一般会手动设一下:

CTrade trade; trade.SetDeviationInPoints(10); trade.SetTypeFilling(ORDER_FILLING_FOK);

Filling模式尤其要注意。不同经纪商支持的模式不同,有的只支持FOK,有的只支持IOC。设错了OrderSend直接返回TRADE_RETCODE_INVALID_FILL,连报错信息都不告诉你具体哪里错了。

调试和回测的实用技巧

Print和Comment是最常用的调试手段,但Print在回测模式下输出量大了会严重拖慢速度。我的做法是用一个全局的调试开关,只在需要的时候打开。另外,OnTick里不要写文件操作,回测时每次tick都写盘,跑一年数据能写到你怀疑人生。

策略测试器里有个被低估的功能:自定义符号。你可以导入外部数据生成自己的K线,测试一些在标准品种上没法验证的想法。我试过用tick数据合成4小时线跑均线策略,结果和直接跑4小时图差别不小——因为合成时的tick聚合方式和经纪商的服务器端聚合不完全一致。

MQL5的学习曲线确实比MQL4陡,但一旦过了那个坎,你会发现很多在MQL4里需要绕路解决的问题,在MQL5里有了正规的解法。事件驱动、面向对象、多线程回测,这些不是花架子,是写复杂策略时真正省时间的东西。

    热门排行

    友情链接