较热55.3

MQL5基础语法入门实战经验总结

XM 推荐平台

覆盖品种全,新手友好,支持多种入金方式

CySEC(塞浦路斯) / ASIC(澳洲) / IFSC(伯利兹) · 最低入金 $5
MapleRider
MapleRider 楼主
2026-8-11 15:51:43 523 0 1分钟 新汇友(注册会员) Lv.1 主题2 帖数8 积分1250 汇币940
1楼
上周帮一个朋友调他的网格EA,发现他在MQL5里用了个老习惯——直接在OnTick里写了一大串if-else判断开仓条件,结果回测时滑点大得离谱。后来一查,问题出在他压根没用结构体管理订单状态,全凭全局变量硬扛。这玩意儿在MQL4时代还能凑合,但到了MQL5的多线程环境下,变量污染和时序错乱能把人整疯。今天就从这儿说起,聊聊MQL5基础语法里那些容易踩的坑,尤其是从MQL4转过来的朋友。
先说说最基础的事件驱动模型。MQL5里没有start()函数了,取而代之的是OnTick()、OnTrade()、OnTimer()这些。新手最容易犯的错是把所有逻辑全塞进OnTick,觉得省事。但实际跑起来你会发现,OnTick只在报价变动时触发,如果行情瞬间跳空或者流动性枯竭,你的订单状态可能还没更新就被下一根tick覆盖了。我自己的做法是拆成三层:OnTick只负责收集报价和调用信号模块,真正的开平仓逻辑放在OnTrade里,用TradeTransaction事件去监听订单状态变化。这样至少能避免80%的重复下单问题。
再聊动态数组和内存管理。MQL5的数组默认是静态的,但很多人写EA时喜欢用ArrayResize()动态扩容,结果在循环里频繁调用,导致内存碎片化严重。我吃过一次亏,跑欧美15分钟策略,回测到2018年那段波动大的行情时,EA直接崩了。后来改成预分配缓冲区,比如用ArrayResize(priceBuffer, 1000, 1000)预留空间,再配合ArraySetAsSeries()处理时间序列,性能直接提升30%。另外注意,MQL5的数组索引是从0开始,但如果你用CopyRates()拉数据,默认返回的是按时间正序排列,记得要用ArraySetAsSeries(true)反转,不然你取最新价会取到最旧的那根。
第三点,结构体和类的封装。很多MQL4老手习惯用全局变量存持仓信息,比如MagicNumber、手数、开仓价。但MQL5里订单池是动态的,你根本没法用一个固定变量去对应多个订单。我现在的做法是定义一个CTrade类,每个实例绑定一个魔术数字,内部用CPositionInfo去遍历持仓。比如这样:

  • CTrade trade; trade.SetExpertMagicNumber(20240601);
  • if(trade.Buy(0.1, _Symbol, 0, 0, 0, "网格加仓")) { Print("开仓成功,订单号", trade.ResultOrder()); }

踩过的坑是,CTrade的Buy()函数默认使用市价单,如果你没设置deviation参数,遇到点差突然扩大时会被拒单。我一般会显式设置trade.SetDeviationInPoints(20),尤其是跑黄金和镑美这种点差容易跳的品种。
最后说下自定义指标和EA的交互。很多人写EA时喜欢直接在OnInit里用iCustom()调用指标句柄,但MQL5的指标句柄是异步更新的,你必须在OnTick里用CopyBuffer()主动拉数据。我见过有人用iMA()然后直接拿Buffer[0]当最新值,结果经常滞后好几根K线。正确做法是:

  • 在OnInit里创建句柄:int maHandle = iMA(_Symbol, _Period, 14, 0, MODE_EMA, PRICE_CLOSE);
  • 在OnTick里用CopyBuffer(maHandle, 0, 0, 1, maBuffer);
  • 判断maBuffer[0]和价格的关系,注意maBuffer[0]是当前未收盘K线的值,如果你想等确认,得用maBuffer[1]。

这个细节我花了整整两天才调明白,因为回测时看起来没问题,但实盘跑起来信号经常晚半拍。
对了,还有个小技巧,用MQL5的OnDeinit清理资源,尤其是你开了文件句柄或者全局指标句柄,不释放的话长时间挂VPS会内存泄漏。我自己的EA每次跑完都会用IndicatorRelease()释放指标,再用EventSetTimer(0)关掉定时器。
说真的,MQL5比MQL4严谨太多,但只要你把事件模型和对象生命周期搞懂,写出来的EA稳定性完全不是一个级别。有没有人遇到过OrderSend()返回true但实际订单没成交的情况?我在模拟账户上碰到过两次,后来发现是没检查ResultRetcode()ResultDeal(),光看返回值不够,得确认deal ID不为0。你们怎么处理的?欢迎评论区交流。
1 回复 复制 众裁0
#1
💬
暂无回复,来抢沙发吧!
THE END
本帖内容仅供学习交流,不构成任何投资建议。外汇交易存在高风险,请谨慎参与。汇友之家合作的各家经纪商均为持有正规外汇牌照的经纪商,我们不参与经纪商的任何经营活动。经纪商在经营过程中可能出现破产清算、资不抵债、跑路或躲避责任等情况,这些问题汇友之家无法控制,亦不承诺任何经纪商资金的绝对安全。请知悉!
← 上一帖 新手求问:数据行情时挂单总被扫损,怎么破? 下一帖 → MT5和MT4的EA代码能通用吗,有人遇到过吗?