二代行情接口

CTP-API

二代行情接口


1.使用前须知

二代行情mdAPI跟6.3.15api包里的mdAPI有所不同,区别如下:

  1. 接口方面:二代行情mdAPI多一个ReqQryMulticastInstrument接口。

  2. 使用范围:二代行情mdAPI只有连接支持交易所组播行情的mdfront才能获得完整功能,即可以使用ReqQryMulticastInstrument查询组播合约;连接其他行情前置则不能使用该函数。

  3. 兼容性:兼容非看穿式监管行情前置,包括mdfront和行情front;暂时不兼容看穿式监管行情前置front_se!

本文档的接口函数说明部分仅列出新增接口,其他接口参照CThostFtdcMdApiCThostFtdcMdSpi部分

2.说明

目前交易所不允许投资者直接连接交易所报盘网去接收组播行情,如果期货公司将行情转发出来给投资者使用,投资者便能享受到快速的组播行情。但是因为转发的只有增量行情,而只有增量部分的是无法得到完整的行情的,所以投资者可以订阅一路CTP行情,作为快照用。有了快照和增量,便能拼出一份完整的行情。如图所示:

以下方法仅做参考:

1、订阅CTP行情。

可以连接mdfront组件接收行情,因为CTP端的行情是完整的行情,而非增量,所以可以作为基准快照,在后续拼装完整行情的时候使用。

2、订阅期货公司的转发行情。

具有解码能力的投资者,可以订阅该行情,并参考交易所二代行情协议规范做相应解码。解码后会得到增量行情,但是这里要注意,这个增量行情还不能直接拿来用,因为该行情里没有InstrumentID,只有合约编号InstrumentNo,而CTP mdfront的行情里是InstrumentID,两者无法关联。为了解决这个问题,新的mdapi增加了ReqQryMulticastInstrument接口,该接口会返回InstrumentID和InstrumentNo的对应关系,有了这个函数便可以拼出完整的行情。注意,仅新的组播mdfront支持该函数,普通行情front和老mdfront不支持该函数!完整行情拼装方法如下:

a) 盘前接入

开盘后,CTP推送每tick快照行情,转发行情则推送每tick增量行情。投资者程序判断同一合约两边的UpdateTime和UpdateMillisec。如果一致,则将mdfront的这笔tick快照行情作为该合约的基准快照,后续的增量行情都在此基础上做拼装,得到笔笔完整行情。

b) 盘中接入

盘中,如果客户接入,则方法同上述a,投资者程序实时判断两边的UpdateTime和UpdateMillisec,直到遇到一致,则作为基准快照。

c) 盘中丢行情

交易所的组播行情带行情序号,如果行情序号不连续了,说明行情丢包了。此时应该停止行情组装工作,重新寻找最新的行情快照,方法同a。

3.代码示例

// mduserhandle.h

#include "ThostFtdcMdApi.h"
#include <stdio.h>
#include <Windows.h>
TThostFtdcInstrumentIDType  g_chInstrumentID;
class CMduserHandler : public CThostFtdcMdSpi
{
    private:
      CThostFtdcMdApi *m_mdApi;
    public:
    void connect()
    {
    //创建并初始化API
        m_mdApi = CThostFtdcMdApi::CreateFtdcMdApi("", true, true);
        m_mdApi->RegisterSpi(this);
        m_mdApi->RegisterFront("tcp://218.28.130.102:41413");
        m_mdApi->Init();
    }
    //登陆
    void login()
    {
        CThostFtdcReqUserLoginField t = {0};
        while (m_mdApi->ReqUserLogin(&t, 1)!=0) Sleep(1000);
    }
    //请求查询组播合约
     void ReqQryMulticastInstrument()
    {
        CThostFtdcQryMulticastInstrumentField a = { 0 };
        a.TopicID = 1001;
        strcpy_s(a.InstrumentID, "cu1905");
        while (m_mdApi->ReqQryMulticastInstrument(&a, 1)!=0) Sleep(1000);
    }
    void OnRspQryMulticastInstrument(CThostFtdcMulticastInstrumentField *pMulticastInstrument, CThostFtdcRspInfoField *pRspInfo, int nRequestID, bool bIsLast)
    {
        if (pMulticastInstrument)
        {
            strcpy_s(g_chInstrumentID,pMulticastInstrument->InstrumentID);
        }
    }
    // 订阅行情
    void subscribe()
    {
        char **ppInstrument=new char * [50];
        ppInstrumentID[0] = g_chInstrumentID;
        while (m_mdApi->SubscribeMarketData(ppInstrument, 1)!=0) Sleep(1000);
    }
    //接收行情
    void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData)
    {   
            printf("OnRtnDepthMarketData\n");
    }
};
// main.cpp
#include "mduserhandle.h"
int main(int argc, char* argv[])
{
    CMduserHandler *mduser = new CMduserHandler;
    mduser->connect();
    mduser->login();
    mduser->ReqQryMulticastInstrument();
    mduser->subscribe();
    Sleep(INFINITE);
}

< 前页 回目录 后页 >