期货CTP接口C++源码与C#应用程序的对接

本文介绍了如何将上期技术公司的期货CTP接口C++源码与C#应用程序对接,以实现更方便的应用逻辑。通过C++处理与交易所的交互,而C#则负责界面和复杂业务逻辑。详细讲解了指令与回报流程,以及如何通过函数指针在C++和C#之间传递信息,实现跨语言的通信。
摘要由CSDN通过智能技术生成

大家知道,期货CTP接口是由上期技术公司提供的,它提供的源码和范例都是用C++语言写的,这在应用上有一定局限性。比如我在实盘中需要数据库,需要程序化,需要K线图,需要这样那样的功能,下单之前要做一堆一堆的事……用C++来写会是很麻烦的。但是C#不怕做这些麻烦事,C#就是用来干脏活累活的,你把界面、应用逻辑啥的都交给C#,C++就只要管好自己的一件事就行了——怎么和交易所对话,这样,工作量会小得多

实际上对大多数人来说,没有C#这样的高级语言,根本就干不了活儿。举个例子来说,我要下单,我用C++怎么下单,在命令行窗口里,输入合约代码,输入价格,输入手数……噼里啪啦一通猛敲键盘,才能把一个单子下完,是吧?但在c#界面里,只需要点一个按钮:

在这里插入图片描述
就是“挂买”这个按钮,我点一下,一瞬间,买进就完成了。在这一瞬间,程序为我干了一连串的事:

● 看看我要买的是哪个合约;
● 读取该合约最新盘口,读取预设的挂单偏移值,算出挂单价格;
● 读取默认手数;
● 准备报单,更新报单序号,记录报单信息;
● 对此单进行预检(有无自成交风险、报单序号是否合规、资金是否足够、是否在交易时间、其他方方面面是否合规);
● 是否有旧单要撤(有时需要撤完旧单再下新单,比如平仓时);
● 账户中是否有反向单需要对冲,如果需要,最终是开仓还是平仓;
● 向交易模块发单;
● 向C++模块发单;
● 向交易所报单。

就这一系列的事情,C++所做的只有最后一件,向交易所报单,也就是ReqOrderInsert。
前面的所有啰嗦事,都由C#包办了。
如果都用C++来写,工作量可想而知(实际上对大多数程序员来说是不可行的)。
虽然事情看起来多,但刚才的那一连串,是在约十毫秒内发生的。
这十毫秒的事情,即使用C#语言来写,也是很长很长的,我们把它精简一下,先不考虑什么报单记录、报单校验之类的了,假设点了按钮直接就报单,便于我们看清C#与C++的关系,那么——

C#中的代码是:

        ///C++所输出的dll的位置
        const string dllPath = @"CTP_se.dll";
        ///引用C++中的下单函数(在C++中,下单的入口是函数“_ReqOrderInsert”
        [DllImport(dllPath, EntryPoint = "_ReqOrderInsert")]
        ///C#的下单函数,“extern”标签决定了它要按照上一句话的规定引用C++中的函数“_ReqOrderInsert”
        static extern void ReqOrderInsert(
        char[] BrokerID, //经纪公司代码(字符串,必填)
        char[] InvestorID, //投资者代码(字符串,必填)
        char[] InstrumentID, //合约代码(字符串,必填)
        char[] ExchangeID, //交易所代码(字符串,必填)
        char[] OrderRef, //报单引用(字符串,必填)
        char[] UserID, //用户代码(字符串,不需要就填“null”)
        int OrderPriceType, //报单价格条件(必填,1为任意价,2为限价,3为最优价,4为最新价,
            //5为最新价浮动上浮1个ticks,6为最新价浮动上浮2个ticks,7为最新价浮动上浮3个ticks,8为卖一价,
            //9为卖一价浮动上浮1个ticks,10为卖一价浮动上浮2个ticks,11为卖一价浮动上浮3个ticks,12为买一价,
            //13为买一价浮动上浮1个ticks,14为买一价浮动上浮2个ticks,15为买一价浮动上浮3个ticks,16为五档价)
        int Direction, //买卖方向(1为买 ,-1为卖)
        int CombOffsetFlag, //组合开平标志(必填,1为开,0为平,-1为平今,-2为平昨,-3为强平,-4为强减,-5为本地强平)
        int CombHedgeFlag, //组合投机套保标志(必填,0为投机,1为套利,2为套保)
        double LimitPrice, //价格(实数,必填)
        int VolumeTotalOriginal, //手数(必填)
        int TimeCondition, //有效期类型(必填,1为立即完成,否则撤销,2为本节有效,3为当日有效,一般填3
            //4为指定日期前有效,5为撤销前有效,6为集合竞价有效)
        char[] GTDDate, //GTD日期(字符串,不需要就填“null”)
        int VolumeCondition, //成交量类型(必填,1为任何数量 ,2为最小数量 ,3为全部数量,一般填1)
        int MinVolume, //最小成交量(必填)
        int ContingentCondition, //触发条件(必填,1为立即,2为止损,3为止赢,4为预埋单,一般填1
            //5为最新价大于条件价,6为最新价大于等于条件价,7为最新价小于条件价,8为最新价小于等于条件价,
            //9为卖一价大于条件价,10为卖一价大于等于条件价,11为卖一价小于条件价,12为卖一价小于等于条件价,
            //13为买一价大于条件价,14为买一价大于等于条件价,15为买一价小于条件价,16为买一价小于等于条件价)
        double StopPrice, //止损价(实数,不需要就填“0”)
        int ForceCloseReason, //强平原因(必填,0为非强平 ,1为资金不足 ,2为客户超仓 ,一般填0
            //3为会员超仓 ,4为持仓非整数倍 ,5为违规 ,6为其它 ,7为自然人临近交割 )
        int IsAutoSuspend, //自动挂起标志(整数,必填,一般填0,表示不自动挂起)
        char[] BusinessUnit, //业务单元(字符串,不需要就填“null”)
        int RequestID, //请求编号(整数,不需要就填“Int32.MinValue”)
        int UserForceClose, //用户强评标志(整数,必填,一般填0,表示否)
        int IsSwapOrder, //互换单标志(整数,不需要就填“Int32.MinValue”)
        int tdClientI //交易通讯线程序号
        );
        private void 挂买按钮_Click(object sender, EventArgs e)
        {
   
            string brokerID = "9999";
            string userID = "071988";
            string insID = "ni2003";
            string exchangeID = "SHFE";
            string ordID = "10000";
            int direction = 1;
            int oc = 1;
            double price = 108590;
            int lot = 1;
            int tdClientI = 0;
            ReqOrderInsert(brokerID.ToCharArray(), userID.ToCharArray(), insID.ToCharArray(), exchangeID.ToCharArray(), ordID.ToCharArray(), null,
                            2, direction, oc, 0, price, lot, 3, null, 1, 1, 1, 0, 0, 0, null, Int32.MinValue, 0, Int32.MinValue, tdClientI);
        }

而在C++中,与上述C#功能对接的函数,名叫“_ReqOrderInsert”:

///C++内部的报单函数
int ReqOrderInsert(CThostFtdcInputOrderField* pInputOrder, int tdClientI) {
   
	string str_ref(pInputOrder->OrderRef);
	string insID(pInputOrder->InstrumentID);
	logWithTimeBUI(tdClientI, insID, "尝试报单 ordID." + str_ref);
	tdApiList
OpenQuant内盘期货插件 ## 目的 将OpenQuant与国内的CTP进行对接,让OpenQuant直接能交易国内期货 ## 设计思路 1. 利用了本开源项目的C-CTP接口,与CSharp-CTP接口 2. C-CTP、CSharp-CTP都以dll方式调用 3. 本插件同时支持QuantDeveloper、OpenQuant2和OpenQuant3(以下分别简称QD、OQ2和OQ3),只要进行再编译即可 4. 为了支持查询合约列表功能,不使用OpenQuant接口,而是使用更底层的SmartQuant接口 ## 如何安装使用 1. 找到SmartQuant接口插件目录C:\Program Files\SmartQuant Ltd\OpenQuant\Framework\bin\ 2. 复制QuantBox.OQ.CTP.dll这个SQ插件,确保此插件的版本正确 3. 找到OpenQuant接口插件目录C:\Program Files\SmartQuant Ltd\OpenQuant\Bin\ 4. 复制thostmduserapi.dll、thosttraderapi.dll两个CTP的dll到此目录 5. 复制QuantBox.C2CTP.dll、QuantBox.CSharp2CTP.dll、QuantBox.Helper.CTP.dll、NLog.dll到此目录 6. 复制CTP.nlog到此目录,或自己修改此文件 7. 找到软件的插件配置文件C:\Documents and Settings\Administrator\Application Data\SmartQuant Ltd\OpenQuant\Framework\ini\framework.xml 8. 添加``到对应位置 9. 如何使用请查看插件的使用说明 ## 如何开发 1. 确保你的C-CTP接口的dll、CSharp-CTP接口等都是最新的 3. 修改引用中有关SmartQuant类库的地址,使用你目标OQ中下的dll 4. 修改.NET框架要使用的版本,QD使用2.0,OQ2使用3.5,OQ3使用4.0 5. 修改dll生成的目录,具体请参考如何安装。 6. 调试只能使用附加到进程,建议学习并使用远程调试 7. 如果插件完全无法加载,请找到对应的log文件,查看日志。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值