CTP接口入门

https://blog.csdn.net/weizehua/article/details/80514732

 

该文章主要讲什么
这篇文章的面向对象是有一些C++基础,并且想用C++来做程式化交易的同学。 
这篇文章可以算是我的程式化学习笔记中的一篇。其中介绍了CTP的简单的使用方式,并且附上了一些代码以及我在试用的时候遇到的一些小坑。

什么是CTP
CTP是上海期货推出的一套可供程序调用的交易接口。就好比官方给程序化交易提供了的一个专门的业务窗口。

接口相关文件下载
CTP接口可以在上期官网下载。 
上期的CTP接口维护似乎比较混乱,新旧版本混在一起了。 
我们只需要下载最新版本的API接口和API文档 (以下简称doc)即可。

环境搭建
按照doc里说的,搭建好环境就可以用了。 
虽然所需的东西在doc里都说明了,但是在这里我还是简单地复述一下吧。

项目创建
使用Visual Studio,建立新项目,将头文件,库文件还有dll的路径设置好就行了。

前置知识
CTP的所有接口都分为Spi和Api两种,分别对应C++中的类:XXXXSpi和XXXXApi。下面说的Api和Spi指的都是这两种东西。
我们主动对服务器发出的请求都是通过Api进行
而服务器的所有响应消息,都得用Spi,通过重写虚函数的形式接收
所有Api都有自己的创建(实例化)方法:XXXXApi::CreateXXXXApi,不应使用new
Spi没有自己的实例化方法,可以按自己喜欢的方式实例化。但是Spi必须注册到Api中才会有用。
Spi和Api一般是配套的,通用的初始化方式是(以CThostFtdcMdApi为例子,其他的都一样):
auto market_api = CThostFtdcMdApi::CreateFtdcMdApi("flow", false);  // 创建Api
MdSpi mdspi(market_api);                                            // 创建Spi(MdSpi继承于CThostFtdcMdSpi)
market_api->RegisterSpi(&mdspi);                                    // 将Spi注册到Api(将Spi与Api关联在一起)
market_api->RegisterFront((char *)"tcp://218.202.237.33:10012");    // 设置服务器
market_api->Init();                                                 // 初始化(开始连接服务器)

初始化完成之后,对应Spi的OnFrontConnected函数将会被调用(以下可能会用收到/响应OnFrontConnected消息这种说法)
请求参数错误会收到OnRspError消息。有些复杂的错误、异常会有特定的消息,详情看.h和doc。
行情查询(行情相关接口)
行情相关接口,其实只有行情查询一个。 
行情接口相关操作都被封装在CThostFtdcMdApi和CThostFtdcMdSpi中。

初始化接口
要查询行情,首先得初始化行情接口。 
按照前置知识中所说的,初始化接口就好。

登录
行情初始化后,收到OnFrontConnected消息,就可以进行登录操作了。所有Api实例都必须单独登录。 
登录只需要调用Api::ReqUserLogin,提供BrokerID, UserID, Password即可 
代码示例:

CThostFtdcReqUserLoginField req = { 0 };
strcpy_s(req.BrokerID, User::broker_id);
strcpy_s(req.UserID, User::user_id);
strcpy_s(req.Password, User::user_password);
int ret = market_api->ReqUserLogin(&req, request_id++);

行情接口登录不需要提供任何信息,调用Api::ReqUserLogin即可,这里贴的代码是演示正常登录用的

查询请求
登录成功之后就可以查询行情, 
调用Api::SubscribeMarketData即可:

const char *data[] = { "cu1807" };
int ret = market_api->SubscribeMarketData((char **)data, sizeof(data) / sizeof(char *));
1
2
返回的行情会响应OnRtnDepthMarketData函数

行情返回的频率最高是2s/次,并且只有在行情有变化的时候才会返回行情(doc中有说明)。

交易相关接口
这里说的交易相关接口是指CThostFtdcTraderApi和CThostFtdcTraderSpi中提供的接口。 
这两个类提供的接口非常丰富。与其说是交易相关接口,不如说是与帐号有关的操作。 
不过在这里我就只介绍仓位查询和下单了。

其他的可以看doc和.h文件。虽然说,里面的内容比较简洁。

登录
还是和上面一样,先登录,这次必须提供正确的BrokerID,用户ID和密码了。

确认结算
CTP有个特别的要求,就是在交易之前,必须确认一下昨天的结算结果

就像是在说:嘿,你昨天输了好多钱,不要赖账,先算清楚今天再继续!

结算的方法是,先用Api::ReqSettlementInfoConfirm请求昨天的结算单。 
然后在OnRspQrySettlementInfo中记下SettlementID,用Api::ReqSettlementInfoConfirm确认这个结算单就好了。 
代码示例:

// 先查询昨天的结算单
CThostFtdcQrySettlementInfoField info = { 0 };
strcpy_s(info.BrokerID, User::broker_id);
strcpy_s(info.InvestorID, User::user_id);
strcpy_s(info.TradingDay, TradingDay(pRspUserLogin->TradingDay).prev_day().to_string().c_str());
int ret = trade_api->ReqQrySettlementInfo(&info, request_id++);

// 记录好结算单ID之后,确认这个结算单
CThostFtdcSettlementInfoConfirmField info;
strcpy_s(info.AccountID, User::user_id);
strcpy_s(info.BrokerID, User::broker_id);
info.SettlementID = pSettlementInfo->SettlementID; // 结算单ID
strcpy_s(info.InvestorID, pSettlementInfo->InvestorID);
strcpy_s(info.CurrencyID, pSettlementInfo->CurrencyID);
int ret = trade_api->ReqSettlementInfoConfirm(&info, request_id++);


TradingDay的参数格式是:”YYYYMMDD”,例如:”20180525”。记得填入的要是昨天的日期,而不是今天的。 
tips : OnRspUserLogin可以获取到今天的交易日

查询仓位
要查询当前仓位,使用Api::ReqQryInvestorPosition。提供BrokerID和UserID即可。 
所有的仓位信息会返回到Spi::OnRspQryInvestorPosition中。 
代码示例:

CThostFtdcQryInvestorPositionField info = { 0 };
strcpy_s(info.BrokerID, User::broker_id);
strcpy_s(info.InvestorID, User::user_id);
//strcpy_s(info.InstrumentID, "cu1807");
int ret = trade_api->ReqQryInvestorPosition(&info, request_id++);

若要查询某个合约的仓位,填上InstrumentID即可。

下单
下单使用Api::ReqOrderInsert,需要填的东西很多,大体可以分为通用部分和条件部分。

CThostFtdcInputOrderField info = { 0 };
// 通用部分
strcpy_s(info.BrokerID, User::broker_id);
strcpy_s(info.InvestorID, User::user_id);
strcpy_s(info.InstrumentID, "cu1807");
info.Direction = THOST_FTDC_D_Buy;                      // 买卖(多头、空头)
info.CombOffsetFlag[0] = THOST_FTDC_OF_Open;            // 开仓、平仓
info.CombHedgeFlag[0] = THOST_FTDC_HF_Speculation;      // 
info.VolumeTotalOriginal = 1;                           // 数量
info.ContingentCondition = THOST_FTDC_CC_Immediately;   // 触发条件
info.VolumeCondition = THOST_FTDC_VC_AV;                // 成交量类型
info.MinVolume = 1;                                     // 最小成交量
info.ForceCloseReason = THOST_FTDC_FCC_NotForceClose;   // 
info.IsAutoSuspend = false;                             // 
info.UserForceClose = false;                            // // 条件部分:市价单
info.OrderPriceType = THOST_FTDC_OPT_AnyPrice;          // 价格类型:市价单
info.LimitPrice = 0;                                    // 限价单的价格
info.

TimeCondition = THOST_FTDC_TC_IOC;                 // 有效期类型

int ret = trade_api->ReqOrderInsert(&info, request_id++);
 

还有很多参数可选,所有的参数在.h中都有说明 
通过参数的组合可以做出很多条件单,例如FOK, FAK。详情可以看doc 4.7

一些小坑
以下是我在用simnow测试的时候遇到的一些小坑。

意思是,也许在真实环境中这些就不是坑了

Api使用频率限制
Api在本地有使用频率限制,似乎是1次/秒(在doc中有说明,4.14.1)。超过这个频率的请求都会被拒绝。 
考虑到接口内部实现精度可能不高,最好是认为频率被限制在了n次/秒(n小于1且无限接近于1)。

一些永远用不到的参数
一些Api参数在结构体中有,看起来好像很重要,但是其实设置成什么都无所谓。doc中没有说明。 
以下是一些看起来很重要,其实一点用都没有的参数列表:

ExchangeID:好像是交易所ID
ExchangeInstID:好像是合约在交易所的代码
CurrencyID:好像是币种代码
一些同名参数
一些参数名字不一样,.h中的解释也不一样,但是指的都是同一个东西

UserID和InvestorID指的都是用户ID
--------------------- 
作者:Happy0403 
来源:CSDN 
原文:https://blog.csdn.net/weizehua/article/details/80514732 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值