MT5 EA交易期货-挂单撤单
该例子的源代码在"EA交易" -> "Examples"下,本例子演示在买一价往上10个跳的价格上挂空单, 挂单10秒后撤单。
与外汇交易不同,为了防止盘口愰骗,各交易所都将频繁撤单列入异常交易管理规范请注意。

EA是通过调用mt5ctp.dll进行期货交易,所以EA需要先引用mt5ctp.dll,该DLL的头文件mt5ctp.mqh在\MQL5\Include目录下。
对于非主连合约如rb2209可以通过Symbol()属性获得当前图表的合约,但对于主连合约如rb9999,则需要通过SYMBOL_ISIN属性获得主连合约现在对应的合约(rb2301),当主连合约rb9999随着时间发生换月后,通过SYMBOL_ISIN属性得到的合约就会自动变为rb2305。使用后者的写法可以让EA在主连合约和非主连合约的图表上都能获得当前图表的合约。
通过SYMBOL_EXCHANGE属性获得该合约对应的交易所, 如获得rb2301所属的交易所SHFE即上期所。
通过SYMBOL_TRADE_TICK_SIZE属性获得该合约每一跳的大小,如螺纹钢是1,股指期货是0.2。
定义了几个全局变量:
orderSysId是用来保存CTP挂单回调中的CTP订单编号,这个变量在之后的撤单中需要使用。
eaOrderRef是EA报单编号,作用类似外汇EA的魔术号码。
placeOrderDateTime是记录挂单成功的时间,该时间过了10秒后会撤单。
orders是记录当前挂单的数量。
splitCommma是代表逗号。
如果当前没有挂单,就发送报单:
先获得最新买一价,将报单价格定位买一价+10个跳,报单手数1手。
调用mt5ctp.dll getOrderRefCTP函数生成EA报单编号并保存在eaOrderRef变量,期货交易所对报单编号格式有规定,不能像外汇EA的魔术号码可随意自行指定, 否则报单会失败,所以EA需先调用mt5ctp.dll的getOrderRefCTP函数生成EA报单编号再报单。
调用mt5ctp.dll sendOrderLimit函数发送限价报单,其中第一个参数是合约,第二个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_SELL_ORDER(代表空单),第三个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_OPEN_POSITION(代表开仓),第四个参数是报单的价格,第五个参数是报单的手数,第六个参数是EA报单编号,第七个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_ACCOUNT_SPECULATION(代表开户的期货账号是投机)。
sendOrderLimit函数调用后会同步返回本地电脑发送报单请求的结果,0是本地电脑向交易所成功发送报单,-1是网络连接失败,-2是未处理请求超过许可数,-3是每秒发送请求数超过许可数。但即使sendOrderLimit函数返回0(只是完成了下图中1和2),也不代表已经成功在交易所挂单,还需要等待交易所异步返回对EA报单的撮合结果即报单回调和成交回调(即下图3)。这与外汇交易有不同,更多请看交易所异步回调。
MT5通过mt5ctp.dll得到交易所对该报单的处理结果(即报单回调),然后把报单回调作为MQL图表事件发送给打开的全部图表,EA 通过MQL图表事件响应函数OnChartEvent得到这些回调(即下图4)。

期货图表事件的ID都是3000,EA需要在OnChartEvent函数中只处理ID是3000的事件。
报单回调是一个字符串,格式如下:
OnRtnOrder, 交易所, 合约, EA报单编号, CTP报单编号, 多空, 开平, 报单状态枚举, 报单状态信息, 报单价格, 报单手数, 成交手数, 报单时间, 撤单时间,FrontID,SessionID,e
EA通过OnChartEvent函数的sparam参数获得图表事件中的交易所报单回调。把sparam对应的字符串按逗号拆分后保存到字符数组chartEvents[]。因为在OnChartEvent函数中ID是3000的事件包括了各种的交易所回调(如报单回调,成交回调,撤单回调,错误回调,仓位回调,资金回调), 所以EA需要先根据chartEvents[0]="OnRtnOrder"筛选出其中的报单回调。
chartEvents数组的第4个元素是EA报单编号。如果有多个EA同时在不同的图表上运行并报单,本图表的OnChartEvent也会接收到其他图表上的EA产生的报单回调,之前EA已经生成并记录了本次报单编号在eaOrderRef变量中,所以只有报单回调中的EA报单编号等于eaOrderRef变量才是本EA的报单回调(作用类似于外汇EA中的魔术号码)。
EA获得报单回调中的CTP报单编号,报单做多或做空,报单开仓或平仓,和交易所对这次报单的撮合结果。
当交易所撮合结果是3(未成交还在队列中)或 4(未成交不在队列中),就是挂单成功了,记录当前挂单的数量为1,并记录成功挂单的时间。
当交易所撮合结果是5(撤单),就是撤单成功了。
挂单成功10秒后会撤销这个挂单,调用mt5ctp.dll的cancelOrderCTP函数进行撤单,其中第一个参数是该合约属于的交易所,第二个参数是合约,第三个参数是CTP报单编号。
cancelOrderCTP函数调用后会同步返回本地电脑处理撤单请求的结果,0是本地向交易所成功发送撤单,-1是网络连接失败,-2是未处理请求超过许可数,-3是表示每秒发送请求数超过许可数。但即使cancelOrderCTP函数返回0(只是完成了1和2),也不代表已经成功在交易所撤单,还需要等待交易所异步返回对撤单的处理结果即撤单回调(即下图3),MT5通过mt5ctp.dll得到交易所的撤单回调,并把撤单回调作为MQL图表事件发送给全部图表,EA 通过MQL图表事件响应函数OnChartEvent得到这些回调(即下图4)。如何取得和处理撤单回调与上面处理报单回调同理。
