Python回测跑通却实盘不成交,MT5的order_send返回值到底怎么读?

新帖
登录发帖
XM 推荐平台

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

CySEC(塞浦路斯) / ASIC(澳洲) / IFSC(伯利兹) · 最低入金 $5
MountainBreeze
MountainBreeze 楼主 2 小时前 浏览 6 回复 0 阅读 1 分钟
Lv.1 新手汇友 等级 Lv.1 主题 1 帖数 15 积分 1436 汇币 1171
1楼
说实话,我一开始也以为order_send返回个True就万事大吉了,直到有次用Python写的欧美突破策略在模拟盘跑得好好的,挂上VPS实盘之后一晚上没成交一单,日志里全是retcode=10009或者10004,我才意识到自己根本没搞懂MT5这套返回结构。
先说个反常识的事:回测跑通跟实盘能不能成交,中间隔的不是策略逻辑,而是你对order_send返回字典的理解深度。策略测试器里撮合引擎是理想化的,它默认你的请求格式没问题、点差恒定、滑点忽略。可实盘上,光是request里几个字段填错,单子连服务器都到不了。
我踩的第一个坑是type_filling没设对。MT5的成交模式分FOK、IOC、Return几种,不同经纪商支持的还不一样。我那个账户只支持IOC,但Python里默认填的是FOK,结果order_send返回的retcode直接是10030(不支持的填充类型)。后来我每次下单前先调symbol_info里的filling_mode,按返回值动态匹配,这个问题才算解决。
第二个坑更隐蔽——price字段在TRADE_ACTION_DEAL下必须填当前市价,但如果你用市价单还传了跟市场偏离太大的价格,服务器会返回10015(无效价格)。我当时的逻辑是取最新tick的ask,但VPS延迟加上点差波动,等请求发到服务器时价格已经变了。解决办法是在request里把price设成0.0,让服务器用市价成交,或者用TRADE_ACTION_PENDING挂单。
下面是我现在排查order_send返回值的固定流程,分享出来供参考:
  • 第一步,打印完整返回字典,别只看retcode。重点看comment字段,很多时候它比retcode更直接,比如“Invalid volume”或者“Market closed”。
  • 第二步,对照retcode表逐项排除。10009是成交完成,10008是请求已接收,10004是请求被拒绝——注意10004后面通常跟着更具体的comment。
  • 第三步,检查request里的volume是否符合该品种的volume_min和volume_step。欧美最小0.01手,但有些账户黄金最小0.1,填错了直接10014。
  • 第四步,确认symbol名称大小写和经纪商后缀。我用的那个平台欧美要写成EURUSD.a,少了后缀返回10013。
  • 第五步,如果是平仓,position字段必须填持仓ticket,不是订单ticket,这俩搞混了会返回10013。

还有个细节容易被忽略:order_send返回成功只代表请求被服务器接受了,不代表已经成交。市价单在快速行情里可能部分成交或者延迟成交,你得再用order_check或者监听OnTradeTransaction来确认最终状态。我现在的做法是下完单等200毫秒,再查一次positions_get看持仓有没有更新。
另外提醒一下用Python跑MT5的朋友,MetaTrader5这个库必须在有MT5终端的环境里跑,VPS上如果同时开了多个终端实例,initialize的时候要指定具体路径,不然可能连到错误的终端上,order_send返回的retcode看着正常但实际单子下到了另一个账户。
说到再说其实这些报错代码本身不复杂,复杂的是我们总带着回测时的思维惯性,觉得逻辑对了就该成交。市场不会骗人,但API会——它只是忠实地告诉你哪里没填对。你们在实盘里遇到过哪些奇怪的retcode?尤其是那种comment里啥也不说、就给你个10004的,一起聊聊排查思路。
0 回复 众裁0 复制
#1
💬
暂无回复,来抢沙发吧!
THE END
本帖内容仅供学习交流,不构成任何投资建议。外汇交易存在高风险,请谨慎参与。
← 上一帖 VPS延迟30ms却频繁断线,MT5日志里这条报错谁见过