訂閱持倉事件
介面說明
訂閱已訂閱帳戶的持倉生命週期事件通知。每則通知會提供該生命週期事件的商品識別碼與相關合約明細。subscribeType 僅支援 = 4。事件交割訊息需使用最新版本的 SDK。
持倉事件訂閱 Proto 協定定義
請求 Proto
message SubscribeRequest {
uint32 subscribeType = 4; // 訂閱類型
int64 timestamp = 2; // 時間戳記
string contentType = 3; // 內容類型
string payload = 4; // 內容
repeated string accounts = 5; // 帳戶 ID
}
回應 Proto
message SubscribeResponse {
EventType eventType = 1; // 事件類型
uint32 subscribeType = 4; // 訂閱類型
string contentType = 3; // 訂閱類型
string payload = 4; // 內容
string requestId = 5; // 請求 id
int64 timestamp = 6; // 時間戳記
}
EventType 列舉
enum EventType {
SubscribeSuccess = 0; // 訂閱成功
Ping = 1; // 心跳資訊
AuthError = 2; // 認證錯誤
NumOfConnExceed = 3; // 連線數超出上限
SubscribeExpired = 4; // 訂閱已過期
}
請求範例
Python
在以下案例中,使用 on_log 方法輸出日誌。my_on_events_message 方法用於接收訂單狀態變更訊息。
import logging
from webull.trade.events.types import EVENT_TYPE_POSITION, POSITION_STATUS_CHANGED
from webull.trade.trade_events_client import TradeEventsClient
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
account_id = "<your_account_id>"
region_id = "my"
# 正式環境 host:events-api.webull.com.my
# 測試環境 host:my-events-api.uat.webullbroker.com
optional_api_endpoint = "<event_api_endpoint>"
def on_log(level, log_content):
print(logging.getLevelName(level), log_content)
def my_on_events_message(event_type, subscribe_type, payload, raw_message):
if EVENT_TYPE_ORDER == event_type and ORDER_STATUS_CHANGED == subscribe_type:
print('----request_id:%s----' % payload['request_id'])
print(payload)
if EVENT_TYPE_POSITION == event_type and POSITION_STATUS_CHANGED == subscribe_type:
print('event payload:%s' % payload)
if EVENT_TYPE_OPTION == event_type and OPTION_STATUS_CHANGED == subscribe_type:
print('option payload:%s' % payload)
if __name__ == '__main__':
# 建立 EventsClient 實例
trade_events_client = TradeEventsClient(your_app_key, your_app_secret, region_id)
# 若為非正式環境,需透過 eventsclient 設定訂閱服務的網域名稱。例如此處設定 UAT 環境的網域名稱
# trade_events_client = TradeEventsClient(your_app_key, your_app_secret, region_id, host=optional_api_endpoint)
trade_events_client.on_log = on_log
# 設定接收到事件資料時的回呼函式。
# 此處印出訂單狀態變更的資料
trade_events_client.on_events_message = my_on_events_message
# 設定要訂閱的帳戶 ID 並發起訂閱。此方法為同步方法
trade_events_client.do_subscribe([account_id])
Java
handleEventMessage 方法用於接收訂單狀態變更訊息。
import com.google.gson.reflect.TypeToken;
import com.webull.openapi.core.execption.ClientException;
import com.webull.openapi.core.execption.ServerException;
import com.webull.openapi.core.logger.Logger;
import com.webull.openapi.core.logger.LoggerFactory;
import com.webull.openapi.core.serialize.JsonSerializer;
import com.webull.openapi.samples.config.Env;
import com.webull.openapi.trade.events.subscribe.ISubscription;
import com.webull.openapi.trade.events.subscribe.ITradeEventClient;
import com.webull.openapi.trade.events.subscribe.message.EventType;
import com.webull.openapi.trade.events.subscribe.message.SubscribeRequest;
import com.webull.openapi.trade.events.subscribe.message.SubscribeResponse;
import java.util.Map;
public class TradeEventsClient {
private static final Logger logger = LoggerFactory.getLogger(TradeEventsClient.class);
public static void main(String[] args) {
try (ITradeEventClient client = ITradeEventClient.builder()
.appKey(Env.APP_KEY)
.appSecret(Env.APP_SECRET)
.regionId(Env.REGION_ID)
// .host("<event_api_endpoint>")
.onMessage(TradeEventsClient::handleEventMessage)
.build()) {
SubscribeRequest request = new SubscribeRequest("<your_account_id>");
ISubscription subscription = client.subscribe(request);
subscription.blockingAwait();
} catch (ClientException ex) {
logger.error("Client error", ex);
} catch (ServerException ex) {
logger.error("Sever error", ex);
} catch (Exception ex) {
logger.error("Unknown error", ex);
}
}
private static void handleEventMessage(SubscribeResponse response) {
if (SubscribeResponse.CONTENT_TYPE_JSON.equals(response.getContentType())) {
Map<String, String> payload = JsonSerializer.fromJson(response.getPayload(),
new TypeToken<Map<String, String>>(){}.getType());
if (EventType.Position.getCode() == response.getEventType()) {
logger.info("{}", payload);
}
}
}
}
回應範例
持倉事件情境類型
OPTION EXERCISE
{
"account_id": "1276674499001173504",
"position_id": "037SDSML6O6DT0KHK6R4000000",
"quantity": "5",
"symbol": "AAPL261120C00305000",
"instrument_type": "OPTION",
"market": "US",
"status": "exercised",
"biz_type": "OPTION_EXERCISE"
}
DEBUG response:eventType: Ping
subscribeType: 4
contentType: "text/plain"
requestId: "ab39b532-3ad4-46c4-823d-3dff12e0f1b9"
timestamp: 1768994319673
OPTION EXPIRATION
{
"account_id": "1276674499001173504",
"position_id": "037SES739C6DT0KHJT90000000",
"quantity": "5",
"symbol": "AAPL261120C00315000",
"instrument_type": "OPTION",
"market": "US",
"status": "expired",
"biz_type": "OPTION_EXPIRATION"
}
DEBUG response:eventType: Ping
subscribeType: 4
contentType: "text/plain"
requestId: "ab39b532-3ad4-46c4-823d-3dff12e0f1b9"
timestamp: 1768994319673