gRPC¶
:33333 提供一个通用 Request(proto_id, body) RPC + 一个流式 SubscribePush。
服务定义¶
crates/futu-grpc/proto/futu.proto:
service FutuOpenD {
rpc Request(FutuRequest) returns (FutuResponse);
rpc SubscribePush(SubscribePushRequest) returns (stream PushEvent);
}
message FutuRequest {
uint32 proto_id = 1;
bytes body = 2; // protobuf 编码
}
message FutuResponse {
int32 ret_type = 1;
string ret_msg = 2;
uint32 proto_id = 3;
bytes body = 4;
}
调用示例¶
import grpc
from futu_pb2 import FutuRequest
from futu_pb2_grpc import FutuOpenDStub
creds = grpc.metadata_call_credentials(
lambda ctx, cb: cb((("authorization", "Bearer fc_xxxx..."),), None)
)
channel = grpc.secure_channel("localhost:33333", grpc.ssl_channel_credentials())
stub = FutuOpenDStub(channel)
# 打包 proto_id=3004 (QOT_GET_BASIC_QOT) body
body = build_get_basic_qot_request(code="00700") # protobuf encode
resp = stub.Request(FutuRequest(proto_id=3004, body=body))
proto_id → scope 映射¶
| 范围 | 所需 scope |
|---|---|
1xxx 系统(InitConnect / KeepAlive / ...) |
无 |
3xxx 行情 |
qot:read |
2005 UnlockTrade |
trade:real |
2202 / 2205 / 2237 下单 / 改单 / 确认 |
trade:real |
2001 / 2008 / 2101 / 2102 / ... 账户只读 |
acc:read |
| 其他 | fail-closed 拒(catch-all trade:real) |
限额¶
- auth 层:trade:real 请求过通用 rate + hours 闸门
- handler 层(v1.2+):
2202 PlaceOrder/2205 ModifyOrder解码 body 后做 market / symbol / value / side / daily 细粒度检查
详见 鉴权与限额。
流式推送¶
grpcurl -plaintext \
-H 'authorization: Bearer fc_xxxx...' \
-d '{}' \
localhost:33333 futu.service.FutuOpenD/SubscribePush
每条 PushEvent 含 event_type (quote / notify / trade) 和 body (protobuf)。
v1.1+:服务端按 client key 的 scope 过滤推送 —— qot:read-only 的 key 不会收到 trade 类事件(交易回报)。过滤掉的事件计 futu_ws_filtered_pushes_total counter。
错误码映射¶
| tonic Status | 含义 |
|---|---|
Unauthenticated |
Bearer 缺失 / 无效 / 过期 |
PermissionDenied |
scope 不够 |
ResourceExhausted |
限额触发(对应 REST 的 429) |
InvalidArgument |
proto_id 不对 / body decode 失败 |
Unavailable |
网关 disconnect |