群益API 斷線怎麼重連:報價與回報的重連步驟

群益API 斷線怎麼重連?報價與回報的重連步驟

盤中 OnConnection 突然收到 3002,不知道該不該在事件裡馬上重連。重連成功、也收到 3003 了,報價卻沒有回來。回報斷線時在事件裡立刻重連,連線結果不穩定。

群益API 斷線後的重連,先記住一句話:斷線事件只用來「知道斷了」,重連要在事件之外做;重連之後,訂閱要重新送出。

本文處理的是「連線真的斷了」之後的事。如果連線看起來還在、資料卻停了,那是另一種情境,見〈群益API 報價停止更新怎麼辦〉。

群益API 斷線重連示意圖:事件裡只記狀態,事件之外重新連線、重送訂閱

群益API 斷線的事件裡,為什麼不能馬上重連?

官方對報價與回報兩邊都有提醒。

報價: 官方在 OnConnection 的說明裡提醒,不要在這個事件裡直接進行連線、斷線、訂閱。原文與說明見〈群益API 連線狀態碼怎麼解讀〉。

回報: 回報斷線事件 OnSolaceReplyDisconnect 的官方說明是:「請注意:收到此通知事件時,底層尚未完成斷線的處理,因此請勿在此事件中立刻執行重新連線或斷線的動作。請收到此事件後啟用一個 Timer,等待數秒後再嘗試重新連線或斷線。」

兩邊的方向一致:斷線事件裡只記下「斷了」這個狀態,重連要回到事件之外再做;回報還要等幾秒。 官方只說「等待數秒」,沒有給具體秒數。

這也是〈群益API 事件回呼跑在哪個執行緒〉那條紀律的實際例子:回呼裡只做最輕量的收集。

報價斷線(3002)之後,怎麼重新連線?

OnConnection 收到 3002(SK_SUBJECT_CONNECTION_DISCONNECT)代表報價連線斷了。接回來的步驟:

  1. 事件裡只記一個旗標,不做別的。
  2. 回到事件之外,重新連線:再呼叫一次 SKQuoteLib_EnterMonitorLONG()。這是建立行情連線的函式,連線狀態由 OnConnection 回傳。以上重連方式是我們的做法,不是官方規定的重連流程。
  3. 等 3003 再往下。等待中不要重複呼叫 EnterMonitorLONG,原因見〈群益API 連線狀態碼怎麼解讀〉。
  4. 把訂閱整批重送一次,下一節說明原因。

重連收到 3003 了,報價為什麼沒回來?

因為訂閱要重新送出。

官方在訂閱函式 SKQuoteLib_RequestStocks 的說明裡寫道(節錄):「可重新連線即還原限制與設定。」

這句說的是重新連線會「還原限制與設定」,字面上沒有直接寫「訂閱會被清掉」。我們把它理解為:重新連線之後,訂閱要重新送出。 所以收到 3003 之後,把訂閱清單整批再送一次。

重送訂閱之後,會不會再收到重複的資料,官方沒有寫,我們也沒有觀察紀錄。程式要能承受可能重複的資料,去重的做法見〈群益API Tick 回補是什麼〉。

回報斷線之後,怎麼重新連線?

回報斷線的事件是 OnSolaceReplyDisconnect。官方註記:「*v2.13.48 版本起,回報斷線事件請透過4-3-h OnSolaceReplyDisconnect」;2.13.48 的改版紀錄也寫明「移除回報連線相關事件OnConnect、OnDisconnect」。舊版的回報斷線事件已經移除,不要再用。

接回來的步驟:

  1. 收到 OnSolaceReplyDisconnect:記下時間,暫停送單。
  2. 等幾秒:照官方說明,在事件之外用計時器(Timer)等待。
  3. 確認狀態:呼叫 SKReplyLib_IsConnectedByID(帳號)。官方說明的回傳值是(節錄):「0表示斷線。1表示連線中。2表示下載中。」
  4. 重新連線:仍是斷線,就呼叫 SKReplyLib_ConnectByID(帳號)。
  5. 等 OnComplete 到了,才恢復送單。

第 5 步的理由:官方說明回報連線之後會先進行回補,OnComplete 代表回補完成;重新連線呼叫的也是同一個函式,所以同樣要等 OnComplete。這一點是從官方說明推的,我們沒有專門測過重連後的回補。如果一直等不到,官方的說明是(節錄):「若未收到此通知,代表新建立的回報連線及回傳回報資料異常.」送單為什麼要等回報就緒,見〈群益API 下單初始化有哪 7 步〉。

群益API 重連的程式結構

下面的片段接在〈群益API Python 入門〉的最小範例之後使用,只示範結構:

import time
import pythoncom

state = {"quote_down": False, "quote_ready": False,
         "reply_down_at": None, "reply_ready": False}
SUBSCRIBE_LIST = "TX00"     # 你的訂閱清單


class QuoteEvents:
    def OnConnection(self, nKind, nCode):
        if nKind == 3002:                  # SK_SUBJECT_CONNECTION_DISCONNECT
            state["quote_down"] = True     # 事件裡只記旗標
            state["quote_ready"] = False
        elif nKind == 3003:                # SK_SUBJECT_CONNECTION_STOCKS_READY
            state["quote_ready"] = True


class ReplyEvents:
    def OnSolaceReplyDisconnect(self, bstrUserID, nErrorCode):
        state["reply_down_at"] = time.time()   # 官方:不要在事件裡立刻重連
        state["reply_ready"] = False           # 暫停送單

    def OnComplete(self, bstrUserID):
        state["reply_ready"] = True            # 回補完成,才恢復送單


def main_loop(quote, reply, user_id, reply_wait_seconds):
    while True:
        pythoncom.PumpWaitingMessages()

        if state["quote_down"]:
            state["quote_down"] = False
            quote.SKQuoteLib_EnterMonitorLONG()          # 在事件之外重新連線
        if state["quote_ready"] and not resubscribed():
            resubscribe(quote, SUBSCRIBE_LIST)           # 重連後重送訂閱

        down_at = state["reply_down_at"]
        if down_at and time.time() - down_at >= reply_wait_seconds:
            state["reply_down_at"] = None
            if reply.SKReplyLib_IsConnectedByID(user_id) == 0:   # 0 表示斷線
                reply.SKReplyLib_ConnectByID(user_id)

        time.sleep(0.05)

幾點說明:

  • 本片段只示範結構,重試與訂閱狀態管理請自行補上。例如重連失敗要不要再試,以及「這次連線已經重送過訂閱」的旗標要在哪裡清除,都要依你的程式設計自行決定。
  • resubscribed()、resubscribe() 是示意函式,由你自己實作。
  • reply_wait_seconds 不給預設值:官方只說「等待數秒」。
  • IsConnectedByID 只在回傳 0(斷線)時重連;回傳 2(下載中)時該怎麼處理,官方沒有說明,片段取保守寫法,不動作。
  • 0.05 秒是示意值。

群益API 重連的 3 個誤解

  1. 誤解: 收到 3002 要在事件裡馬上重連。其實: 事件裡只記旗標,回到事件之外再重新連線;官方提醒不要在 OnConnection 裡直接進行連線、斷線、訂閱。
  2. 誤解: 回報斷了要在事件裡馬上重連。其實: 官方要求收到 OnSolaceReplyDisconnect 後等待數秒,再嘗試重新連線。
  3. 誤解: 重連收到 3003,報價就會自己回來。其實: 要把訂閱再送一次;官方說明重新連線會「還原限制與設定」,我們把它理解為訂閱要重新送出。

常見問題

群益API 報價斷線收到 3002,要怎麼重連?

事件裡只記下斷線的狀態,回到事件之外再呼叫一次 SKQuoteLib_EnterMonitorLONG(),等 3003 之後把訂閱整批重送一次。

回報斷線之後,要等幾秒再重連?

官方只說收到 OnSolaceReplyDisconnect 後「啟用一個 Timer,等待數秒後再嘗試重新連線或斷線」,沒有給具體秒數。等待期間先暫停送單,重連之後要等 OnComplete 再恢復。

重連之後會不會收到重複的資料?

官方沒有寫,我們也沒有觀察紀錄。程式要能承受可能重複的資料,去重的做法可以參考〈群益API Tick 回補是什麼〉。

程式要結束時,要做什麼?

先停止送單,也不再送出新的訂閱。官方文件沒有登出函式。

風險揭露

期貨與選擇權屬高槓桿商品,價格波動可能造成超過原始保證金的損失,交易人須自負交易責任。本文為程式開發技術教學,說明群益API 斷線後的重連步驟,不構成投資建議,也不保證任何交易結果。程式化交易並不降低市場風險,斷線期間程式可能無法即時處理委託與部位,重連後也要確認狀態再恢復送單。

投資人教育資源

機構資源
臺灣期貨交易所(TAIFEX)期貨及選擇權數位學習網
證券暨期貨市場發展基金會證券期貨市場教育推廣
金融智慧網金管會金融知識平台
中華民國期貨業商業同業公會期貨業法規與宣導
證券投資人及期貨交易人保護中心投資人保護與申訴

延伸閱讀

參考資料

  • OnSolaceReplyDisconnect 的說明、回報斷線事件的版本註記與 2.13.48 改版紀錄、SKReplyLib_IsConnectedByID 的回傳值、SKQuoteLib_RequestStocks 的「還原限制與設定」、OnConnection 的提醒、OnComplete 的說明,依群益官方元件說明文件。
  • 報價斷線後在事件之外再呼叫 EnterMonitorLONG 重新連線、重連後重送訂閱:我們的做法與理解,非官方規定的流程。

免責聲明

本文章僅作為群益API實作經驗分享,不構成投資建議,且策略及程式皆應自行撰寫。期貨及衍生性金融商品交易屬高風險投資,請謹慎評估自身風險承擔能力。

延伸閱讀|相關文章

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *