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

大家知道,期货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
  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
好的,我可以为您提供一个期货CTP交易下单的C demo。您需要安装CTP API并正确配置环境后,使用以下代码即可进行期货下单: ``` #include <stdio.h> #include <string.h> #include <Windows.h> #include "ThostFtdcTraderApi.h" class CTraderSpi : public CThostFtdcTraderSpi { public: virtual void OnFrontConnected() { printf(">>> Front connected.\n"); CThostFtdcReqUserLoginField req; memset(&req, 0, sizeof(req)); strcpy(req.BrokerID, "经纪商代码"); strcpy(req.UserID, "投资者账户"); strcpy(req.Password, "用户密码"); m_pTraderApi->ReqUserLogin(&req, 0); } virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { if (pRspInfo != NULL && pRspInfo->ErrorID != 0) { printf(">>> Error: login failed, errno = %d, err msg = %s.\n", pRspInfo->ErrorID, pRspInfo->ErrorMsg); return; } printf(">>> Login success.\n"); CThostFtdcInputOrderField req; memset(&req, 0, sizeof(req)); strcpy(req.BrokerID, "经纪商代码"); strcpy(req.InvestorID, "投资者账户"); strcpy(req.InstrumentID, "期货合约代码"); strcpy(req.UserID, "投资者账户"); req.Direction = THOST_FTDC_D_Buy; req.OffsetFlag = THOST_FTDC_OF_Open; req.LimitPrice = 5000; req.VolumeTotalOriginal = 1; req.OrderPriceType = THOST_FTDC_OPT_LimitPrice; req.TimeCondition = THOST_FTDC_TC_GFD; req.VolumeCondition = THOST_FTDC_VC_AV; req.MinVolume = 1; req.ContingentCondition = THOST_FTDC_CC_Immediately; req.ForceCloseReason = THOST_FTDC_FCC_NotForceClose; req.IsAutoSuspend = 0; m_pTraderApi->ReqOrderInsert(&req, 0); } virtual void OnRspOrderInsert(CThostFtdcInputOrderField *pInputOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) { if (pRspInfo != NULL && pRspInfo->ErrorID != 0) { printf(">>> Error: insert order failed, errno = %d, err msg = %s.\n", pRspInfo->ErrorID, pRspInfo->ErrorMsg); return; } printf(">>> Insert order success.\n"); } void SetTraderApi(CThostFtdcTraderApi *pTraderApi) { m_pTraderApi = pTraderApi; } private: CThostFtdcTraderApi *m_pTraderApi; }; int main() { CThostFtdcTraderApi *pTraderApi = CThostFtdcTraderApi::CreateFtdcTraderApi(); CTraderSpi *pTraderSpi = new CTraderSpi(); pTraderSpi->SetTraderApi(pTraderApi); pTraderApi->RegisterSpi(pTraderSpi); pTraderApi->SubscribePublicTopic(THOST_TERT_RESTART); pTraderApi->SubscribePrivateTopic(THOST_TERT_RESTART); pTraderApi->RegisterFront("交易前置地址"); pTraderApi->Init(); pTraderApi->Join(); return 0; } ``` 您只需要将代码中的经纪商代码、投资者账户、用户密码、期货合约代码、交易前置地址修改为您自己的信息即可进行期货下单操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值