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#[derive(Debug, Clone)]
9pub struct HistoryKLResult {
10 pub security: Security,
11 pub kl_list: Vec<KLine>,
12 pub next_kl_time: Option<String>,
14}
15
16pub async fn get_history_kl(
23 client: &FutuClient,
24 security: &Security,
25 rehab_type: RehabType,
26 kl_type: KLType,
27 begin_time: &str,
28 end_time: &str,
29 max_num: Option<i32>,
30) -> Result<HistoryKLResult> {
31 let req = futu_proto::qot_request_history_kl::Request {
32 c2s: futu_proto::qot_request_history_kl::C2s {
33 rehab_type: rehab_type as i32,
34 kl_type: kl_type as i32,
35 security: security.to_proto(),
36 begin_time: begin_time.to_string(),
37 end_time: end_time.to_string(),
38 max_ack_kl_num: max_num,
39 need_kl_fields_flag: None,
40 next_req_key: None,
41 extended_time: None,
42 session: None,
43 },
44 };
45
46 let body = prost::Message::encode_to_vec(&req);
47 let resp_frame = client
48 .request(proto_id::QOT_REQUEST_HISTORY_KL, body)
49 .await?;
50
51 let resp: futu_proto::qot_request_history_kl::Response =
52 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
53
54 if resp.ret_type != 0 {
55 return Err(FutuError::ServerError {
56 ret_type: resp.ret_type,
57 msg: resp.ret_msg.unwrap_or_default(),
58 });
59 }
60
61 let s2c = resp
62 .s2c
63 .ok_or(FutuError::Codec("missing s2c in GetHistoryKL".into()))?;
64
65 Ok(HistoryKLResult {
66 security: Security::from_proto(&s2c.security),
67 kl_list: s2c.kl_list.iter().map(KLine::from_proto).collect(),
68 next_kl_time: None, })
70}
71
72#[derive(Debug, Clone)]
74pub struct RequestHistoryKLParams<'a> {
75 pub security: &'a Security,
76 pub rehab_type: RehabType,
77 pub kl_type: KLType,
78 pub begin_time: &'a str,
79 pub end_time: &'a str,
80 pub max_num: Option<i32>,
81 pub next_req_key: Option<&'a [u8]>,
82}
83
84#[derive(Debug, Clone)]
86pub struct RequestHistoryKLResult {
87 pub security: Security,
88 pub kl_list: Vec<KLine>,
89 pub next_req_key: Option<Vec<u8>>,
91}
92
93pub async fn request_history_kl(
95 client: &FutuClient,
96 params: &RequestHistoryKLParams<'_>,
97) -> Result<RequestHistoryKLResult> {
98 let req = futu_proto::qot_request_history_kl::Request {
99 c2s: futu_proto::qot_request_history_kl::C2s {
100 rehab_type: params.rehab_type as i32,
101 kl_type: params.kl_type as i32,
102 security: params.security.to_proto(),
103 begin_time: params.begin_time.to_string(),
104 end_time: params.end_time.to_string(),
105 max_ack_kl_num: params.max_num,
106 need_kl_fields_flag: None,
107 next_req_key: params.next_req_key.map(|k| k.to_vec()),
108 extended_time: None,
109 session: None,
110 },
111 };
112
113 let body = prost::Message::encode_to_vec(&req);
114 let resp_frame = client
115 .request(proto_id::QOT_REQUEST_HISTORY_KL, body)
116 .await?;
117
118 let resp: futu_proto::qot_request_history_kl::Response =
119 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
120
121 if resp.ret_type != 0 {
122 return Err(FutuError::ServerError {
123 ret_type: resp.ret_type,
124 msg: resp.ret_msg.unwrap_or_default(),
125 });
126 }
127
128 let s2c = resp
129 .s2c
130 .ok_or(FutuError::Codec("missing s2c in RequestHistoryKL".into()))?;
131
132 Ok(RequestHistoryKLResult {
133 security: Security::from_proto(&s2c.security),
134 kl_list: s2c.kl_list.iter().map(KLine::from_proto).collect(),
135 next_req_key: s2c.next_req_key,
136 })
137}