交易事件订阅
接口说明
交易事件订阅是基于gRPC
实现的Server Streaming
长连接,适用于通过OpenApi开发平台对接Webull客户。交易事件订阅完全遵循gRPC
开源协议,您在使用时可以参考gRPC开源库。
目前接口支持订单状态变化消息推送,支持的场景类型如下:
场景类型 | 描述 |
---|---|
PLACE_FAILED | 下单失败 |
MODIFY_SUCCESS | 改单成功 |
MODIFY_FAILED | 改单失败 |
CANCEL_SUCCESS | 撤单成功 |
CANCEL_FAILED | 撤单失败 |
FILLED | 部分成交 |
FINAL_FILLED | 全部成交 |
交易事件订阅Proto协议定义
请求Proto
message SubscribeRequest {
uint32 subscribeType = 1; // 订阅类型
int64 timestamp = 2; // 时间戳
string contentType = 3; // 内容类型
string payload = 4; // 内容
repeated string accounts = 5; // 账户ID
}
响应Proto
message SubscribeResponse {
EventType eventType = 1; // 事件类型
uint32 subscribeType = 2; // 订阅类型
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
- Java
使用sdk请求时,subscribeType、timestamp、contentType、payload可以不用关注。只需要传入accounts即可。subscribeType目前仅支持=1。 以下案例中,_on_log方法是输出日志使用。my_on_events_message方法是接受订单状态变化消息。
import logging
from webullsdktrade.events.types import ORDER_STATUS_CHANGED, EVENT_TYPE_ORDER
from webullsdktradeeventscore.events_client import EventsClient
from webullsdkcore.common.region import Region
your_app_key = "<your_app_key>"
your_app_secret = "<your_app_secret>"
account_id = "<your_account_id>"
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['account_id'])
print(payload['client_order_id'])
print(payload['order_status'])
if __name__ == '__main__':
client = EventsClient(your_app_key, your_app_secret, Region.HK.value)
client.on_log = _on_log
client.on_events_message = my_on_events_message
print("subscribe account", [account_id])
client.do_subscribe([account_id])
handleEventMessage方法接受订单状态变化消息。
import com.google.common.reflect.TypeToken;
import com.webull.openapi.common.Region;
import com.webull.openapi.example.config.Env;
import com.webull.openapi.logger.Logger;
import com.webull.openapi.logger.LoggerFactory;
import com.webull.openapi.serialize.JsonSerializer;
import com.webull.openapi.trade.events.subscribe.EventClient;
import com.webull.openapi.trade.events.subscribe.Subscription;
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 TradeEvents {
private static final Logger logger = LoggerFactory.getLogger(TradeEvents.class);
public static void main(String[] args) {
try (EventClient client = EventClient.builder()
.appKey(Env.APP_KEY)
.appSecret(Env.APP_SECRET)
.regionId(Region.hk.name())
.onMessage(TradeEvents::handleEventMessage)
.build()) {
SubscribeRequest request = new SubscribeRequest("<your_account_id>");
Subscription subscription = client.subscribe(request);
subscription.blockingAwait();
} catch (Exception ex) {
logger.error("Subscribe trade events 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.Order.getCode() == response.getEventType() || EventType.Position.getCode() == response.getEventType()) {
logger.info("----request_id:{}----", payload.get("request_id"));
logger.info(payload.get("account_id"));
logger.info(payload.get("client_order_id"));
logger.info(payload.get("order_status"));
}
}
}
}
订阅成功响应示列
# 连接成功
subscribeType: 1
contentType: "text/plain"
payload: "344992976"
requestId: "c1d2e05d-6984-45d8-b69f-f5b674c19a01"
timestamp: 1663667365268
# eventType:Ping消息为心调信息,无需处理。
eventType: Ping
subscribeType: 1
contentType: "text/plain"
requestId: "c1d2e05d-6984-45d8-b69f-f5b674c19a01"
timestamp: 1663667385269
# 接收订单变更消息
eventType: 1024
subscribeType: 1
contentType: "application/json"
payload: "{\"secAccountId\":18955861,\"requestId\":\"H2GIPOP8I0TPBREPCPDFDENO5B\",\"account_id\":\"MDJQ432JHNK60LFN3TO1JA83N9\",\"request_id\":\"47987108\",\"client_order_id\":\"6bf6bcfa365745a3bed44df29e00fb15\",\"instrument_id\":\"913256409\",\"order_status\":\"Cancelled\",\"symbol\":\"00700\",\"short_name\":\"TENCENT\",\"qty\":\"100.0\",\"filled_qty\":\"0.0\",\"side\":\"BUY\",\"scene_type\":\"CANCEL_SUCCESS\",\"category\":\"HK_STOCK\",\"order_type\":\"ENHANCED_LIMIT\"}"
requestId: "H2GIPOP8I0TPBREPCPDFDENO5B"
timestamp: 1663729830258
# my_on_events_message方法打印出来接收到订单变更消息
----request_id:47987108----
MDJQ432JHNK60LFN3TO1JA83N9
6bf6bcfa365745a3bed44df29e00fb15
Cancelled