
为什么需要全市场合约ID
做期货量化,第一步是把市场上能交易的合约都找出来。股票那边有交易所公布的代码列表,期货这边得靠CTP接口去问。不知道合约ID,行情订阅、下单、风控都没法做。
CTP里合约ID藏在哪
CTP分两个接口:交易接口(TraderApi)和行情接口(MdApi)。合约ID在交易接口里查,行情接口只负责推行情。
交易接口有个函数叫ReqQryInstrument,专门用来查所有合约。调用它,CTP会把当前所有可交易的合约信息一次性返回给你。返回的数据里有个字段叫InstrumentID,就是我们要的合约ID。

查询前必须做的几件事
先创建TraderApi实例,注册前置地址。
登录交易账户,必须登录成功才能查。
登录后等OnRspUserLogin回调,在回调里发起查询。
查询是异步的,结果通过OnRspQryInstrument回调返回。
代码示例(C++伪代码)
// 登录成功后,在OnRspUserLogin里调用
CThostFtdcQryInstrumentField req;
int ret = m_pTraderApi->ReqQryInstrument(&req, ++m_nRequestID);
if (ret != 0) {
// 查询请求发送失败,检查网络或登录状态
}
回调里怎么收
void OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {
if (pInstrument) {
// 拿到一个合约
string instrumentID = pInstrument->InstrumentID;
string exchangeID = pInstrument->ExchangeID;
// 存到数据库或内存列表
}
if (bIsLast) {
// 最后一包,查询结束
}
}
过滤掉不能交易的合约
CTP返回的列表里包含已到期、已下市、或者只用来做行情参考的合约。期货量化只关心当前能下单的。
过滤条件看这几个字段:
ProductClass:只保留期货(THOST_FTDC_PC_Futures)和期权(THOST_FTDC_PC_Options)。股票用不到CTP,股票代码走另外的接口。ExpireDate:到期日大于当前交易日。IsTrading:等于1表示正在交易。VolumeMultiple:大于0才是正常合约。
股票与期货的差异
股票没有CTP接口,股票合约ID从交易所官网、券商柜台或者行情软件获取。期货、期权才用CTP。如果你做股票量化,直接去交易所下载代码表,不要走CTP。
常见坑点
查询请求发出去没反应:登录没成功,或者前置没连上。
回调只来几包就断了:没等到
bIsLast == true,要一直等。合约ID重复:不同交易所可能有相同代码,要用ExchangeID+InstrumentID联合主键。
夜盘合约:临近收盘时查询,可能返回的合约列表不完整。
拿到之后怎么用
把合约ID存到Redis或者内存字典。行情订阅时,用InstrumentID去订阅。下单时,用InstrumentID构造报单引用。风控时,用InstrumentID查合约乘数、最小变动价位。
整套流程跑通,你就拥有了全市场期货合约的实时列表。