futu_qot/
static_info.rs

1use futu_core::error::{FutuError, Result};
2use futu_core::proto_id;
3use futu_net::client::FutuClient;
4
5use crate::types::{QotMarket, Security};
6
7/// 股票静态信息
8#[derive(Debug, Clone)]
9pub struct SecurityStaticInfo {
10    pub security: Security,
11    pub id: i64,
12    pub lot_size: i32,
13    pub sec_type: i32,
14    pub name: String,
15    pub list_time: String,
16    pub delisting: bool,
17}
18
19impl SecurityStaticInfo {
20    pub fn from_proto(info: &futu_proto::qot_common::SecurityStaticInfo) -> Self {
21        let basic = &info.basic;
22        Self {
23            security: Security::from_proto(&basic.security),
24            id: basic.id,
25            lot_size: basic.lot_size,
26            sec_type: basic.sec_type,
27            name: basic.name.clone(),
28            list_time: basic.list_time.clone(),
29            delisting: basic.delisting.unwrap_or(false),
30        }
31    }
32}
33
34/// 获取股票静态信息
35///
36/// 通过股票列表查询静态信息(名称、每手数量、类型等)。
37pub async fn get_static_info(
38    client: &FutuClient,
39    securities: &[Security],
40) -> Result<Vec<SecurityStaticInfo>> {
41    let req = futu_proto::qot_get_static_info::Request {
42        c2s: futu_proto::qot_get_static_info::C2s {
43            market: None,
44            sec_type: None,
45            security_list: securities.iter().map(|s| s.to_proto()).collect(),
46        },
47    };
48
49    let body = prost::Message::encode_to_vec(&req);
50    let resp_frame = client.request(proto_id::QOT_GET_STATIC_INFO, body).await?;
51
52    let resp: futu_proto::qot_get_static_info::Response =
53        prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
54
55    if resp.ret_type != 0 {
56        return Err(FutuError::ServerError {
57            ret_type: resp.ret_type,
58            msg: resp.ret_msg.unwrap_or_default(),
59        });
60    }
61
62    let s2c = resp
63        .s2c
64        .ok_or(FutuError::Codec("missing s2c in GetStaticInfo".into()))?;
65
66    Ok(s2c
67        .static_info_list
68        .iter()
69        .map(SecurityStaticInfo::from_proto)
70        .collect())
71}
72
73/// 按市场和类型获取股票静态信息
74pub async fn get_static_info_by_market(
75    client: &FutuClient,
76    market: QotMarket,
77    sec_type: i32,
78) -> Result<Vec<SecurityStaticInfo>> {
79    let req = futu_proto::qot_get_static_info::Request {
80        c2s: futu_proto::qot_get_static_info::C2s {
81            market: Some(market as i32),
82            sec_type: Some(sec_type),
83            security_list: vec![],
84        },
85    };
86
87    let body = prost::Message::encode_to_vec(&req);
88    let resp_frame = client.request(proto_id::QOT_GET_STATIC_INFO, body).await?;
89
90    let resp: futu_proto::qot_get_static_info::Response =
91        prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
92
93    if resp.ret_type != 0 {
94        return Err(FutuError::ServerError {
95            ret_type: resp.ret_type,
96            msg: resp.ret_msg.unwrap_or_default(),
97        });
98    }
99
100    let s2c = resp
101        .s2c
102        .ok_or(FutuError::Codec("missing s2c in GetStaticInfo".into()))?;
103
104    Ok(s2c
105        .static_info_list
106        .iter()
107        .map(SecurityStaticInfo::from_proto)
108        .collect())
109}