futu_qot/
kline.rs

1use futu_core::error::{FutuError, Result};
2use futu_core::proto_id;
3use futu_net::client::FutuClient;
4
5use crate::types::{KLType, KLine, RehabType, Security};
6
7/// K 线查询结果
8#[derive(Debug, Clone)]
9pub struct KLineResult {
10    pub security: Security,
11    pub kl_list: Vec<KLine>,
12}
13
14/// 获取 K 线数据
15///
16/// 查询指定股票的 K 线数据。需要先订阅对应类型的 K 线。
17///
18/// - `rehab_type`: 复权类型
19/// - `kl_type`: K 线类型(日K、分钟K等)
20/// - `req_num`: 请求的 K 线根数
21pub async fn get_kl(
22    client: &FutuClient,
23    security: &Security,
24    rehab_type: RehabType,
25    kl_type: KLType,
26    req_num: i32,
27) -> Result<KLineResult> {
28    let req = futu_proto::qot_get_kl::Request {
29        c2s: futu_proto::qot_get_kl::C2s {
30            rehab_type: rehab_type as i32,
31            kl_type: kl_type as i32,
32            security: security.to_proto(),
33            req_num,
34        },
35    };
36
37    let body = prost::Message::encode_to_vec(&req);
38    let resp_frame = client.request(proto_id::QOT_GET_KL, body).await?;
39
40    let resp: futu_proto::qot_get_kl::Response =
41        prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
42
43    if resp.ret_type != 0 {
44        return Err(FutuError::ServerError {
45            ret_type: resp.ret_type,
46            msg: resp.ret_msg.unwrap_or_default(),
47        });
48    }
49
50    let s2c = resp
51        .s2c
52        .ok_or(FutuError::Codec("missing s2c in GetKL".into()))?;
53
54    Ok(KLineResult {
55        security: Security::from_proto(&s2c.security),
56        kl_list: s2c.kl_list.iter().map(KLine::from_proto).collect(),
57    })
58}