一、请求
查询数据的请求函数通常定义为:
class CThostFtdcTraderApi
{
int ReqQryXXX(*pQuery, int nRequestID);
};
该函数由Api实现,用初始化时创建的Api实例直接调用,就可以将查询参数pQuery
中的信息发送给CTP柜台。
-
发送失败有可能是网络连接出了问题,返回值为
-1
。 -
发送失败的另一种可能就是触发了流控限制,返回值为
-2
或者-3
。查询流控要求:- 在途(成功发出请求至收到
bIsLast
为true
的最后一条响应)的查询操作最多只能有一个。触发返回值-2
。 - 每秒钟最多只能进行有限次(具体参数由期货公司设置)查询操作。触发返回值
-3
。
- 在途(成功发出请求至收到
-
发送成功,返回值为
0
。请求到达前置时仍然会被校验流控,如果触发,则会触发OnRspError
,并提示:“CTP:查询未就绪,请稍后重试”。 -
未触发流控的查询请求,都有一个专属的回调函数负责返回查询结果。即便查询失败,该回调函数的
pRspInfo
参数会附带错误信息。 -
还有一类以
ReqQuery
开头的查询函数,例如ReqQueryBankAccountMoneyByFuture
,此类函数都是通过交易核心处理的,不通过查询核心,不受流控限制。 -
对于大部分查询接口,如果请求要素信息填空,则会返回所有的记录;但是也有例外,比如保证金率
ReqQryInstrumentMarginRate
和手续费率ReqQryInstrumentCommissionRate
,如果InstrumentID
填空,则返回持仓合约的相关数据。如果要查询所有,则需要通过多次查询得到。
二、响应
class CThostFtdcTraderSpi
{
void OnRspQryXXX(*pResponse, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
{
/// 自定义处理逻辑
}
///错误应答
void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
-
pResponse
:结果数据的结构体指针。如果查询出现错误,或者最后一条响应,可能为空指针。 -
pRspInfo
:错误信息。如果无错误,pRspInfo或者为空指针,或者字段ErrorID值为0。 -
nRequestID
:与发送请求时传递的参数一致,不要求递增,无限制。 -
bIsLast
:最后一条响应标识。
三、常用查询
1. 查询合约信息
class CThostFtdcTraderApi
{
///请求查询合约
int ReqQryInstrument(CThostFtdcQryInstrumentField *pQryInstrument, int nRequestID) = 0;
};
class CThostFtdcTraderSpi
{
///请求查询合约响应
void OnRspQryInstrument(CThostFtdcInstrumentField *pInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
从结果数据CThostFtdcInstrumentField
中可以获得合约的交易规则,例如最小变动价位PriceTick
,合约乘数VolumeMultiple
,以及单笔最大报单数量等。
期货、期权合约的更新频率相对比较高,所以,每个交易日开盘前,或者客户端系统启动前,一般都需要发送该查询请求,以获得最及时、最准确的可交易合约信息。
另外,由于行情MdApi
订阅行情时必须明确具体的合约名称,所以批量订阅行情时,可以通过这个查询获取结果。
2. 查询报单
class CThostFtdcTraderApi
{
///请求查询报单
int ReqQryOrder(CThostFtdcQryOrderField *pQryOrder, int nRequestID) = 0;
};
class CThostFtdcTraderSpi
{
///请求查询报单响应
void OnRspQryOrder(CThostFtdcOrderField *pOrder, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
结果数据CThostFtdcOrderField
定义与实时订单状态回调函数OnRtnOrder
附带的数据定义一致。
结果中只包括截至查询时刻订单的最后状态。
最后状态与最终状态不同,最终状态是指不再发生变化的状态,包括废单、全部成交、已撤销;最后状态是相对某一时刻而言,可能是最终状态,也可能不是,例如排队中,后续可以继续变化。
实践中,为了保持OrderRef
的唯一性,便于对订单索引,每次启动客户端系统时,都会查询一下所有订单,并记录最大的OrderRef
,后续报单在这个基础上进行递增。
3. 查询成交
class CThostFtdcTraderApi
{
///请求查询成交
int ReqQryTrade(CThostFtdcQryTradeField *pQryTrade, int nRequestID) = 0;
};
class CThostFtdcTraderSpi
{
///请求查询成交响应
void OnRspQryTrade(CThostFtdcTradeField *pTrade, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
结果数据CThostFtdcTradeField
定义与实时成交回调函数OnRtnTrade
附带的数据定义一致。
不同交易所,TradeDate
字段的含义不同。大商所、郑商所回报中该字段为交易日;上期所、能源回报为自然日。建议确认一笔成交的时间用Tradingday+TradeTime
这一组字段。
4. 查询账户资金
class CThostFtdcTraderApi
{
///请求查询资金账户
int ReqQryTradingAccount(CThostFtdcQryTradingAccountField *pQryTradingAccount, int nRequestID) = 0;
};
class CThostFtdcTraderSpi
{
///请求查询资金账户响应
void OnRspQryTradingAccount(CThostFtdcTradingAccountField *pTradingAccount, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
单向大边目前只有上期所和中金所有此项业务。对于上期所,同品种的买卖双边分别计算,取买卖双边中保证金金额较大的一边单向实时收取。对于中金所,套利、套保和投机的交易编码不同,计算的时候首先是区分交易编码的,每个交易编码下同品种的买卖双边再分别计算取大边。对于能源中心,sc目前是单向大边的规则。
5. 查询结算单
class CThostFtdcTraderApi
{
///请求查询投资者结算结果
int ReqQrySettlementInfo(CThostFtdcQrySettlementInfoField *pQrySettlementInfo, int nRequestID) = 0;
};
class CThostFtdcTraderSpi
{
///请求查询投资者结算结果响应
void OnRspQrySettlementInfo(CThostFtdcSettlementInfoField *pSettlementInfo, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
可以查询当天或历史结算单,也可以查询月结算单,但是前提是CTP柜台生成了相应的日或月结算单。
查询某一天的结算单,TradingDay
填写格式为"yyyymmdd"
;查询某一月的结算单,TradingDay
填写格式为"yyyymm"
四、OnRspError
响应
class CThostFtdcTraderSpi
{
///错误应答
virtual void OnRspError(CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast) {};
};
触发前置流控,报单流控、查询流控和会话数控制等都会产生该响应。
另外,登录后立即发起查询,有可能出现CTP:查询未就绪,请稍后重试
的错误,是因为登录后查询核心还没有就绪。遇到这种情况,可以在登录后隔一秒再查询。