1. 程式人生 > >CTP期貨行情介面使用筆記

CTP期貨行情介面使用筆記

CTP開發文件

期貨行情訂閱

使用流程

  • 建立繼承自 CThostFtdcMdSpi 的類
  • 通過 CThostFtdcMdApi::CreateFtdcMdApi() 建立api物件
  • 將spi物件通過 RegisterSpi() 註冊給api物件
  • 通過 RegisterFront() 函式向api物件註冊行情前置地址
  • 呼叫api物件的 init() 介面完成初始化
  • 當與行情前置連線成功後,可以使用api物件的 ReqUserLogin() 介面來進行登入
  • 登入成功後即可通過api物件的 SubscribeMarketData() 介面進行訂閱操作
  • 使用api物件的 ReqUserLogout()
    函式來退出登入
  • 使用api物件的 Release() 函式來釋放CTP資源
  • 使用api物件的 join() 函式等待執行緒退出

Demo開發注意事項

  1. 實現spi介面類

    繼承類 CThostFtdcMdSpi 中的虛擬函式,我們可以根據具體需要來選擇實現

    • OnFrontConnected 客戶端到行情前置的無身份驗證連線建立之後,這個函式會被呼叫,用於說明連線已經建立。連線建立之後,才能請求登入
    • OnFrontDisconnected 如果客戶端到行情前置的無身份驗證連線建立失敗,這個函式被呼叫,其中的引數說明連線失敗的原因
    • OnRspUserLogin 交易系統對客戶端的請求登入訊息作出的響應
    • OnRspSubMarketData 交易核心對客戶端請求訂閱行情的訊息處理結果迴應,包含錯誤程式碼及原因
    • OnRspUnSubMarketData 交易核心對客戶端請求退訂行情的訊息處理結果迴應,包含錯誤程式碼及原因
    • OnRtnDepthMarketData 通過這個函式返回行情資訊,頻率是每秒兩次
    • OnRspError 如果交易系統無法識別客戶端傳送的請求訊息,就通過這個函式返回錯誤資訊
    • OnHeartBeatWarning 如果超過一定時間在客戶端和系統之間沒有任何訊息交換髮生,這個函式會發送心跳用來說明客戶端到系統伺服器之間的連線是活躍的
  2. 行情介面的初始化

    // 建立api物件
    CThostFtdcMdApi *api = CThostFtdcMdApi::CreateFtdcMdApi();
    // 建立spi物件,CMySpi繼承自CThostFtdcMdSpi
    CMySpi *spi = new CMySpi(); // 將spi註冊給api api->RegisterSpi(spi); 註冊期貨行情前置地址 api->RegisterFront("tcp://127.0.0.1:17001"); // 初始化,並向期貨行情前置發起無身份驗證連線 api->init();
  3. 登入系統

    // 上面呼叫api的 `init()` 後,會想前置發起連線
    // 連線成功後,會回撥 `OnFrontConnected()`
    // 如果連線失敗,則回撥 `OnFrontDisconnected`
    // 連線成功後,就可以進行登入
    
    CThostFtdcReqUserLoginField field;
    memset(&field, 0, sizeof(field));
    // BROKER_ID 是期貨公司的會員號
    strcpy(field.BrokerID, BROKER_ID);
    // INVESTOR_ID 是投資者在該期貨公司的客戶號
    strcpy(field.UserID, INVESTOR_ID);
    // PASSWORD 是該投資者密碼
    strcpy(field.Password, PASSWORD);
    strcpy(field.UserProductInfo, UserProductInfo);
    // 該函式返回一個整數值,標誌請求是否被髮送出去,而不是是否已經被服務端處理
    // 0 傳送成功
    // -1 因網路原因傳送失敗
    // -2 未處理請求佇列總數量超限
    // -3 每秒傳送請求數量超限
    int ret = api->ReqUserLogin(&field, 0);

    伺服器通過 OnRspUserLogin() 對該登入請求做出響應

    virtual void OnRspUserLogin(CThostFtdcRspUserLoginField *pRspUserLogin,
        CThostFtdcRspInfoField *pRspInfo, /*該結構中的ErrorID為0表示登入成功,否則失敗;ErrorMsg表示錯誤資訊*/
        int nRequestID,
        bool bIsLast);
  4. 訂閱行情

    // 登入成功才可以訂閱
    // nameArray 合約名稱陣列
    // count 陣列大小
    int ret = SubscribeMarketData(nameArray, count);

    傳送訂閱後,回撥spi的 OnRspSubMarketData 進行處理響應

    ///訂閱行情應答
    virtual void OnRspSubMarketData(CThostFtdcSpecificInstrumentField *pSpecificInstrument,
        CThostFtdcRspInfoField *pRspInfo, /*服務端給的錯誤響應資訊,如果沒有錯誤,ErrorMsg內容為 "CTP:No Error" */
        int nRequestID,
        bool bIsLast);

    成功訂閱的行情資料,通過回撥spi的 OnRtnDepthMarketData 來返回

    ///深度行情通知
    ///頻率是每秒兩次
    virtual void OnRtnDepthMarketData(CThostFtdcDepthMarketDataField *pDepthMarketData);
  5. 退出登入及取消訂閱

    ///退訂行情。
    /// ppInstrumentID 合約ID  
    /// nCount 要訂閱/退訂行情的合約個數
    virtual int UnSubscribeMarketData(char *ppInstrumentID[], int nCount) = 0;
    ///登出請求
    virtual int ReqUserLogout(CThostFtdcUserLogoutField *pUserLogout, int nRequestID) = 0;

    退訂行情和取消登入的處理與上述的類似,也是回撥相應spi的虛擬函式介面

    注意:目前,通過ReqUserLogout登出系統的話,會先將現有的連線斷開。客戶端重新登入後系統會再重新建立一個新的連線,而SessionID會被重置,因此MaxOrderRef一般也會重新從0計數。

  6. 斷線重連

    客戶端與服務端斷開連線時,函式 OnFrontDisconnected 被呼叫,其中的引數nReason描述了斷線的原因。

    • 0x1001 網路讀失敗
    • 0x1002 網路寫失敗
    • 0x2001 讀心跳超時
    • 0x2002 傳送心跳超時
    • 0x2003 收到不能識別的錯誤訊息

    客戶端與服務端的連線斷開有兩種情況

    • 網路原因導致連線斷開
    • 服務端主動斷開連線

    伺服器主動斷開連線有兩種可能

    • 客戶端長時間沒有從服務端接收報文,時間超時
    • 客戶端建立的連線數超過限制

    超時

    • 網路超時會導致服務端主動與客戶端斷開連線
    • 預設的讀超時為:120 秒,寫超時為:60 秒,心跳超時為:80 秒
    • 客戶端與服務端連線斷開後,交易介面會自動嘗試重新連線,頻率是每5 秒一次