Skip to main content

futu_qot/
sub.rs

1use futu_core::error::{FutuError, Result};
2use futu_core::proto_id;
3use futu_net::client::FutuClient;
4
5use crate::types::{Security, SubType};
6
7/// 订阅行情
8///
9/// 订阅指定股票的指定类型行情数据。
10/// 订阅后可通过推送接收实时数据更新。
11pub async fn subscribe(
12    client: &FutuClient,
13    securities: &[Security],
14    sub_types: &[SubType],
15    is_reg_push: bool,
16    is_first_push: bool,
17) -> Result<()> {
18    let req = futu_proto::qot_sub::Request {
19        c2s: futu_proto::qot_sub::C2s {
20            security_list: securities.iter().map(|s| s.to_proto()).collect(),
21            sub_type_list: sub_types.iter().map(|t| *t as i32).collect(),
22            is_sub_or_un_sub: true,
23            is_reg_or_un_reg_push: Some(is_reg_push),
24            reg_push_rehab_type_list: vec![],
25            is_first_push: Some(is_first_push),
26            is_unsub_all: None,
27            is_sub_order_book_detail: None,
28            extended_time: None,
29            session: None,
30            header: None,
31        },
32    };
33
34    let body = prost::Message::encode_to_vec(&req);
35    let resp_frame = client.request(proto_id::QOT_SUB, body).await?;
36
37    let resp: futu_proto::qot_sub::Response =
38        prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
39
40    check_ret_type(resp.ret_type, resp.ret_msg)
41}
42
43/// 退订行情
44pub async fn unsubscribe(
45    client: &FutuClient,
46    securities: &[Security],
47    sub_types: &[SubType],
48) -> Result<()> {
49    let req = futu_proto::qot_sub::Request {
50        c2s: futu_proto::qot_sub::C2s {
51            security_list: securities.iter().map(|s| s.to_proto()).collect(),
52            sub_type_list: sub_types.iter().map(|t| *t as i32).collect(),
53            is_sub_or_un_sub: false,
54            is_reg_or_un_reg_push: Some(true),
55            reg_push_rehab_type_list: vec![],
56            is_first_push: None,
57            is_unsub_all: None,
58            is_sub_order_book_detail: None,
59            extended_time: None,
60            session: None,
61            header: None,
62        },
63    };
64
65    let body = prost::Message::encode_to_vec(&req);
66    let resp_frame = client.request(proto_id::QOT_SUB, body).await?;
67
68    let resp: futu_proto::qot_sub::Response =
69        prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
70
71    check_ret_type(resp.ret_type, resp.ret_msg)
72}
73
74fn check_ret_type(ret_type: i32, ret_msg: Option<String>) -> Result<()> {
75    if ret_type != 0 {
76        return Err(FutuError::ServerError {
77            ret_type,
78            msg: ret_msg.unwrap_or_default(),
79        });
80    }
81    Ok(())
82}