期货的订单类型和外汇不一样,国内期货交易所只有限价单和市价单。

限价单就是比如交易者报限价单4000做多螺纹钢,则交易所只会在4000或4000以下撮合该多单,所以如果能成交,成交价格只会在4000或4000以下。

比如交易者报限价单8000做空苹果,则交易所只会在8000或8000以上撮合该空单,所以如果能成交,成交价格只会在8000或8000以上。

也就是说限价单会在交易者指定的价格上成交,超出了该价格则不成交。

本例子演示了EA如何报限价单做多,成交后10秒平仓。

EA是通过调用mt5ctp.dll进行期货交易,所以EA需要先引用mt5ctp.dll,该DLL头文件mt5ctp.mqh在\MQL5\Include目录下。

#property copyright "www.wewin28.com 1145412@qq.com"
#property version   "1.1"
#include <mt5ctp.mqh>   //引用MT5CTP头文件

EA获取当前图表的合约。对于非主连合约如rb2209可以通过Symbol()属性获得当前图表的合约,但对于主连合约如rb9999,则需要通过SYMBOL_ISIN属性获得主连合约现在对应的合约(rb2301),当主连合约rb9999随着时间发生换月后,通过SYMBOL_ISIN属性得到的合约就会自动变为rb2305。使用后者的写法可以让EA在主连合约和非主连合约的图表上都能获得当前图表的合约。

通过SYMBOL_EXCHANGE属性获得该合约对应的交易所, 如获得rb2301所属的交易所SHFE(上期所)。

通过SYMBOL_DIGITS属性获得该合约的小数后位数,如螺纹钢是0,股指是1。

splitCommma是代表逗号。

string symbol=SymbolInfoString(Symbol(), SYMBOL_ISIN); //获取合约(如果是主力合约的话取对应的合约) get symbol
string exchange=SymbolInfoString(symbol, SYMBOL_EXCHANGE); //该品种的交易所 get exchange
long digits=SymbolInfoInteger(symbol, SYMBOL_DIGITS);  //该品种价格的小数位数  get decimal
ushort splitCommma=StringGetCharacter(",",0);         //逗号 comma

定义报单时间全局变量entryTime,用来判断是否已经报单。定义仓位全局变量,如果pos等于0就是空仓,如果大于0就是持仓。eaOrderRef是EA报单编号,作用类似外汇EA的魔术号码。

datetime entryTime=D'1970.01.01 00:00';    //报单时间全局变量 send order datetime
int pos=0;  //EA仓位全局变量  position
long eaOrderRef=0;   //EA报单编号全局变量  magic number

如果还没有报单和空仓就报单,先取得当前最新的MqlTick结构体:获得现在的格林威治时间,将格林威治时间转成北京时间,获得3个小时之前的时间(比如当前是12点就是9点),将之前3个小时以来的全部跳复制到ticks[]数组(MqlTick结构体)访问ticks[]数组的最后一个元素,即获得并返回最新价格的MqlTick结构体。

MqlTick getLastMQLTick()
{datetime gmt=TimeGMT();   datetime chinaCurrentDatetime=(datetime)(gmt+8*60*60);               //格林威治时间ulong last3HourMinute=(long)(chinaCurrentDatetime-60*60*3)*1000;     //将格林威治时间转成北京时间  convert GMT time to Beijing timeMqlTick ticks[]; MqlTick lastTick;int copyTick=CopyTicks(symbol,ticks,COPY_TICKS_ALL,last3HourMinute,30000); if(copyTick>=0){int tickCount=ArraySize(ticks);if(tickCount>0){lastTick=ticks[tickCount-1];        }else{printf("tick count 0");}}   else{printf("copyTick 0");}return lastTick;
}

通过最新的MqlTick结构体取得最新成交价,设置报单手数1手,调用mt5ctp.dll getOrderRefCTP函数生成EA报单编号并保存在eaOrderRef变量,CTP对报单编号格式有格式要求,不能像外汇EA的魔术号码可随意自行指定, 否则报单会失败,所以EA需先调用getOrderRefCTP函数生成EA报单编号再报单。

EA调用mt5ctp.dll sendOrderLimit函数发送限价报单,其中第一个参数是合约,第二个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_BUY_ORDER(代表多单),第三个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_OPEN_POSITION(代表开仓),第四个参数是报单的价格,第五个参数是报单的手数,第六个参数是EA报单编号,第七个参数是mt5ctp.mqh头文件中定义的枚举ENUM_CTP_ACCOUNT_SPECULATION(代表开户的期货账号是投机)。

void OnTick()
{if(entryTime==D'1970.01.01 00:00'){if(pos==0)        //空仓{      MqlTick mqlTick=getLastMQLTick();   //取得当前最新价格的结构体 get latest price structdouble ask=mqlTick.ask;      //取得卖一价 get askint vol=1;                   //手数 quantityeaOrderRef=getOrderRefCTP(); //生成EA报单编号 generate EA magic numberif(ask!=0){int res=sendOrderLimit(symbol, ENUM_CTP_BUY_ORDER, ENUM_CTP_OPEN_POSITION, ask, vol, (string)eaOrderRef, ENUM_CTP_ACCOUNT_SPECULATION);   //对手价多开 send order with ask//0 代表报单成功  local send order ok //-1 表示网络连接失败  network disconect//-2,表示未处理请求超过许可数  request too much  //-3,表示每秒发送请求数超过许可数  request too fast within one secondif(res==0) {}   else     //打印同步返回的错误 print send order local error{printf("sendOrderLimit error %d", res);}}             }entryTime=TimeCurrent();              //保存报单时间防止重复报单 record time      //Sleep(10000);}

请注意sendOrderLimit函数调用后会同步返回本地电脑发送报单请求的结果,0是本地电脑向交易所成功发送报单,-1是网络连接失败,-2是未处理请求超过许可数,-3是每秒发送请求数超过许可数。但即使sendOrderLimit函数返回0(即完成下图中的1和2),也不代表已经成功在交易所挂单,还需要等待交易所异步返回对EA报单的撮合结果即报单回调和成交回调(即下图中的3)。


MQL期货发出的MQL图表事件ID都是3000,EA需要在OnChartEvent函数中只处理ID是3000的事件。

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{if(id==3000)     //只处理MT5 CTP的chart event process MT5 CTP event only{      

EA通过OnChartEvent函数的sparam参数获得图表事件中的交易所报单回调。

报单回调是一个字符串,格式如下:

OnRtnOrder, 交易所, 合约, EA报单编号, CTP报单编号, 多空, 开平, 报单状态枚举, 报单状态信息, 报单价格, 报单手数, 成交手数, 报单时间, 撤单时间,FrontID,SessionID,e

EA通过OnChartEvent函数的sparam参数获得MQL图表事件中的交易所报单回调。把sparam对应的字符串按逗号拆分后保存到字符数组chartEvents[]。

因为在OnChartEvent函数中ID是3000的事件包括了各种的交易所回调(如报单回调,成交回调,撤单回调,错误回调,仓位回调,资金回调), 所以EA需要先根据chartEvents[0]="OnRtnOrder"筛选出其中的报单回调。

void OnChartEvent(const int id,const long &lparam,const double &dparam,const string &sparam)
{if(id==3000)     //只处理MT5 CTP的chart event process MT5 CTP event only{      //printf(sparam);string chartEvents[];     int n=StringSplit(sparam,splitCommma,chartEvents);   //CTP成交回调中的各个数据用逗号分隔 callback string split by commaif(n>0){string eventType=chartEvents[0];                     //报单回调 send order callbackif(eventType=="OnRtnOrder")               //CTP报单回调 send order callback{

chartEvents数组的第4个元素是EA报单编号。如果有多个EA同时在不同的图表上运行并报单,本图表的OnChartEvent也会接收到其他图表上的EA产生的报单回调,在上面EA已经生成并记录了EA本次报单编号在eaOrderRef变量中,所以只有报单回调中的EA报单编号等于eaOrderRef变量才是本EA本次报单的回调(作用类似于外汇EA中的魔术号码)。

//报单回调 send order callbackif(eventType=="OnRtnOrder")               //CTP报单回调 send order callback{//0OnRtnOrder,1交易所,2合约,3EA报单编号,4CTP服务器报单编号,5多空,6开平,7报单状态枚举,8报单状态信息,9报单价格,10报单手数,11成交手数,12报单时间,13撤单时间,FrontID,SessionID,eprintf(sparam);string exchange3=chartEvents[1];       //交易所exchange  string symbol2=chartEvents[2];         //合约symbol        string orderRef=chartEvents[3];        //EA报单编号 magic number            if(orderRef==(string)eaOrderRef)       //如果CTP成交回调中的EA报单编号是本EA的报单编号 is my EA order{          

EA获得报单回调中的交易所、合约、EA报单编号、CTP报单编号、报单是做多或做空、报单是开仓或平仓,获得报单价格,报单手数,报单成交手数,报单时间,撤单时间和交易所对这次报单的撮合结果。

 string eventType=chartEvents[0];                     //报单回调 send order callbackif(eventType=="OnRtnOrder")               //CTP报单回调 send order callback{//0OnRtnOrder,1交易所,2合约,3EA报单编号,4CTP服务器报单编号,5多空,6开平,7报单状态枚举,8报单状态信息,9报单价格,10报单手数,11成交手数,12报单时间,13撤单时间,FrontID,SessionID,eprintf(sparam);string exchange3=chartEvents[1];       //交易所exchange  string symbol2=chartEvents[2];         //合约symbol        string orderRef=chartEvents[3];        //EA报单编号 magic number            if(orderRef==(string)eaOrderRef)       //如果CTP成交回调中的EA报单编号是本EA的报单编号 is my EA order{         string orderSysId=chartEvents[4];   //CTP服务器报单编号                       string buySellEnum=chartEvents[5];  //多空     string combOffsetFlag=chartEvents[6];    //开平               string orderStatusEnum=chartEvents[7];    //报单状态枚举                                                                                  string statusMsg=chartEvents[8];    //报单状态信息double price=(double)chartEvents[9];   //报单价格                                        string priceWithDigital=DoubleToString(price, (int)digits);string vol=chartEvents[10];        //报单手数string fillVol=chartEvents[11];    //成交手数 string orderTime=chartEvents[12];    //报单时间                          string orderCancelTime=chartEvents[13];   //撤单时间}}

如果报单成交了,EA接着会收到交易所的成交回报。

成交回调是一个字符串,格式如下:

OnRtnTrade, 交易所, 合约, EA报单编号, CTP报单编号, 成交编号, 多空, 开平, 成交价格, 成交手数, 成交时间,e

因为在OnChartEvent函数中ID是3000的事件包括了交易所的各种回调(如报单回调,成交回调,撤单回调,错误回调,仓位回调,资金回调), 所以EA需要先根据chartEvents[0]="OnRtnTrade"找出其中的成交回调。

EA取得成交回调中的EA报单编号。如果有多个EA同时在不同的图表上运行并报单,本图表的OnChartEvent也会接收到其他图表上的EA产生的成交回调,在第40行eaOrderRef变量已经记录了这次报单的编号,所以成交回调中的EA报单编号等于该变量才是本EA本次报单的成交回调(作用类似于外汇EA中的魔术号码)。

EAj就可以获得成交回调中的交易所、合约、CTP报单编号、CTP成交编号、报单是做多还是做空、报单是开仓还是平仓)、报单的成交价格、报单的成交手数、报单成交时间。

然后根据报单成交回调计算EA多空仓位。

   //成交回调 order fill callback if(eventType=="OnRtnTrade")                //CTP成交回调 order fille callback{//0OnRtnTrade,1交易所,2合约,3EA报单编号,4CTP服务器报单编号,5成交编号,6多空,7开平,8成交价格,9成交手数,10成交时间,eprintf(sparam);string orderRef=chartEvents[3];         //EA报单编号 magicif(orderRef==(string)eaOrderRef)        //如果CTP成交回调中的EA报单编号是本EA的报单编号就记录仓位 my EA order get filled{string exchange2=chartEvents[1];       //CTP成交回调中的交易所 exchangestring symbol2=chartEvents[2];       //CTP成交回调中的合约 instrument of callbackstring orderSysId=chartEvents[4];       //CTP成交回调中的CTP报单编号string fillId=chartEvents[5];       //CTP成交回调中的成交编号 filled Idstring buySellEnum=chartEvents[6];   //CTP成交回调中的多/空  buy/sell string openCloseEnum=chartEvents[7]; //CTP成交回调中的开平  0=开仓   1=平仓  2=强平  3=平今  4=平昨  5=强减  6=本地强平                double price=(double)chartEvents[8]; //成交价格  filled price               string buySell="";string vol=chartEvents[9];           //成交手数  filled quantityif(buySellEnum=="0")                 //0=多   1=空            {pos+=(int)vol;}else                                       {pos-=(int)vol;}string tradeTime=chartEvents[10];     //成交时间  filled datetime//printf("%s %s %s %s %s手 %s", symbol2, buySell, openClose, DoubleToString(price, (int)digits), vol, tradeTime);  //打印报单回调 print place order callback}}   

如果交易所拒绝了EA的报单, EA通过报单错误回调获得该报单被拒绝的原因。

//报单错误回调  cancel order error callback        if(eventType=="OnErrRtnOrderInsert")               //CTP报单错误回调 fail to place order callback{//0OnErrRtnOrderAction,1交易所,2合约,3EA报单编号,4CTP服务器报单编号,5操作标志,6价格,7错误编号,8错误信息,eprintf(sparam);string errorId=chartEvents[1];                  //报单错误编号 error IDstring errorMsg=chartEvents[2];                 //报单错误信息 error messagestring exchange2=chartEvents[3];                //交易所 exchangestring symbol2=chartEvents[4];                   //合约  instrumentstring orderRef=chartEvents[5];                 //EA报单编号  magic numberstring buySell=chartEvents[6];                  //多空 buy sellstring combOffsetFlag=chartEvents[7];           //开平 open closestring limitPrice=chartEvents[8];               //报单价格 pricestring volumeTotalOriginal=chartEvents[9];      //报单手数 quantitystring combHedgeFlag=chartEvents[10];           //账号是投资还是套保 string timeCondition=chartEvents[11];           //报单有效期 1=立即完成,否则撤销 2=本节有效   3=当日有效   4=指定日期前有效   5=撤销前有效  6=集合竞价有效string volumeCondition=chartEvents[12];         //报单成交量类型  1=任何数量   2=最小数量  3=全部数量       string contingentCondition=chartEvents[13];     //报单触发条件 1=立即  2=止损  3=预埋单string stopPrice=chartEvents[14];               //报单报单止损价string minVolume=chartEvents[15];               //最小成交量   printf("报单错误 fail to place order");}

持仓10秒后买一价报限价空单平仓,平仓程序和开仓同理。

 if(pos!=0)   //持仓10秒后限价平仓  close position in 10 seconds by limit order{if(TimeCurrent()-entryTime>10){     MqlTick mqlTick=getLastMQLTick();    //取得当前最新价格的结构体 get latest price structdouble bid=mqlTick.bid;  //取得买一价 get bideaOrderRef=getOrderRefCTP(); //生成EA报单编号 generate EA magic numberint res=0;if(bid!=0){if(exchange=="SHFE" || exchange=="INE")  //上期所和能源中心区分平今仓昨仓{res=sendOrderLimit(symbol, ENUM_CTP_SELL_ORDER, ENUM_CTP_CLOSE_POSITION_TODAY, bid, pos, (string)eaOrderRef, ENUM_CTP_ACCOUNT_SPECULATION);}else   //其他交易所不用区分平今仓还是平昨仓{res=sendOrderLimit(symbol, ENUM_CTP_SELL_ORDER, ENUM_CTP_CLOSE_POSITION, bid, pos, (string)eaOrderRef, ENUM_CTP_ACCOUNT_SPECULATION);}//0 代表报单成功 local send order ok //-1 表示网络连接失败  network disconect//-2,表示未处理请求超过许可数  request too much  //-3,表示每秒发送请求数超过许可数 request too fast within one secondif(res!=0)   //打印同步返回的错误{printf("sendOrderLimit error %d", res);}        }}   }  

MT5 EA交易期货-限价单开仓平仓相关推荐

  1. MT5 EA交易期货-市价单开仓平仓

    该例子演示了EA如何报期货市价单开仓,开仓后10秒钟报市价单平仓. 在外汇交易里没有市价单,而期货交易有市价单, 市价单报单时不指定价格,让交易所自行成交,就是做多无论多贵都买,做空无论多便宜都卖,不 ...

  2. MT5 EA交易期货-挂单撤单

    本例子演示在买一价往上10个跳的价格上挂空单, 挂单后10秒后撤单. 与外汇交易不同,为了防止盘口愰骗,各交易所都将频繁撤单列入异常交易管理规范请注意. EA是通过调用mt5ctp.dll进行期货交易 ...

  3. MT5 EA交易期货-EA编程接口

    为什么MT5可以交易期货? 如下图MT5 EA是通过调用mt5ctp.dll接口函数进行期货交易的.该DLL在MQL5\Libraries目录下.外汇EA只需要修改报单部分的程序即可使用在期货上面. ...

  4. MT5 EA交易期货-报单部分成交

    期货的交易机制会出现报单部分成交的情况. EA是通过调用mt5ctp.dll进行期货交易,该DLL提供了接口函数可以指定如何处理报单部分成交的情况, 开发者可以根据自己的策略去选择如何处理不同的报单部 ...

  5. MT5 EA交易期货-查询资金

    本例子演示了EA如何获得期货账号下的权益.手续费.占用保证金.平仓盈亏.持仓盈亏和可用资金. EA是通过调用mt5ctp.dll进行期货交易,所以EA需要先引用mt5ctp.dll,该DLL头文件mt ...

  6. MT5 EA交易期货-盘口

    MT5期货里提供了上期所和能源中心的五档盘口(卖5,卖4,卖3,卖2,卖1,买1,买2,买3,买4,买5),中金所.大商所和郑商所的一档盘口(卖1,买1),这样我们就可以开发基于盘口的策略了. 下面的 ...

  7. 期货ctp基础知识(合约,开仓,平仓,做多,做空,保证金,手续费)

    期货ctp教程地址:期货ctp教程 合约 期货买卖的是合约,股票买卖的是股票 做多和做空 2.1. 做多 你就是买入看涨,所以买这个动作对应的指令就是"买开仓" 当你赚了或者止损的 ...

  8. MT4/MT5 EA 回测价格模式OHLC之坑

    EA 回测的价格模式已MT5为例有 1.每次报价 2.每个点基于实时点 3.1分钟OHLC 4.仅使用开价 5.科学计算 每次报价和每个点基于实时点如果电脑不是服务器配置基本无法回测. 所以一般回测经 ...

  9. python网格交易_网格交易(期货)

    网格交易(期货) 分享 阅读 30668 更新 2020-12-03 15:44:39 网格交易法(期货) 1. 原理 什么是网格交易法? 网格交易法是一种利用行情震荡进行获利的策略.在标的价格不断震 ...

最新文章

  1. 我和freelancer不得不说的故事5 --- 心理落差
  2. java md5算法,JAVA实现MD5算法
  3. Web的系统测试方法 (转载)
  4. 2011年最新使用CSS3实现各种独特悬浮效果的教程
  5. 轻量高效!清华智能计算实验室开源基于PyTorch的视频 (图片) 去模糊框架SimDeblur
  6. Split和正则表达式的区别
  7. [转] 在 Mac OS X 下编译 Objective-C 运行时
  8. JavaScript模拟call和apply的实现
  9. TWaver HTML5 + Node.js + express + socket.io + redis(五)
  10. 公众号回复单个图文消息
  11. 使用L2TPV3桥接---FR-TO-PPP
  12. 零基础必看的Linux入门教程 (AcWing)
  13. 【信息论】如何彻底理解信息和熵?
  14. Excel宏的基本逻辑语句
  15. linux php 编程 pdf 百度云,Linux下的Perl编程 pdf版
  16. c++常对象和常成员函数详解
  17. 快速计算平方根数(约翰·卡马克)
  18. cppunit在vs2019上的配置和使用【Win10】【详细】
  19. 如何使用爬虫与JieBa库制作词云
  20. SSO - 我们为何需要单点登录系统

热门文章

  1. Vmware WorkStation的三种联网方式
  2. 汇编语言的预习和复习
  3. 最新网易云课堂用户研究员微专业(价值2598)
  4. 记一次Android视频播放器开发
  5. 用在生产中的裸金属Ironic
  6. grads 相关系数_era interim说明文件
  7. Seo:秒排建站(三)主机推荐补充讲解
  8. 51 Nod 1563——坐标轴上的最大团
  9. Vanilla SGD
  10. bmijava_Java程序来计算体重指数(BMI)