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 header: None,
44 },
45 };
46
47 let body = prost::Message::encode_to_vec(&req);
48 let resp_frame = client
49 .request(proto_id::QOT_REQUEST_HISTORY_KL, body)
50 .await?;
51
52 let resp: futu_proto::qot_request_history_kl::Response =
53 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
54
55 if resp.ret_type != 0 {
56 return Err(crate::server_err(resp.ret_type, resp.ret_msg));
57 }
58
59 let s2c = resp
60 .s2c
61 .ok_or(FutuError::Codec("missing s2c in GetHistoryKL".into()))?;
62
63 Ok(HistoryKLResult {
64 security: Security::from_proto(&s2c.security),
65 kl_list: s2c.kl_list.iter().map(KLine::from_proto).collect(),
66 next_kl_time: None, })
68}
69
70#[derive(Debug, Clone)]
72pub struct RequestHistoryKLParams<'a> {
73 pub security: &'a Security,
74 pub rehab_type: RehabType,
75 pub kl_type: KLType,
76 pub begin_time: &'a str,
77 pub end_time: &'a str,
78 pub max_num: Option<i32>,
79 pub next_req_key: Option<&'a [u8]>,
80}
81
82#[derive(Debug, Clone)]
84pub struct RequestHistoryKLResult {
85 pub security: Security,
86 pub kl_list: Vec<KLine>,
87 pub next_req_key: Option<Vec<u8>>,
89}
90
91pub async fn request_history_kl(
93 client: &FutuClient,
94 params: &RequestHistoryKLParams<'_>,
95) -> Result<RequestHistoryKLResult> {
96 let req = futu_proto::qot_request_history_kl::Request {
97 c2s: futu_proto::qot_request_history_kl::C2s {
98 rehab_type: params.rehab_type as i32,
99 kl_type: params.kl_type as i32,
100 security: params.security.to_proto(),
101 begin_time: params.begin_time.to_string(),
102 end_time: params.end_time.to_string(),
103 max_ack_kl_num: params.max_num,
104 need_kl_fields_flag: None,
105 next_req_key: params.next_req_key.map(|k| k.to_vec()),
106 extended_time: None,
107 session: None,
108 header: None,
109 },
110 };
111
112 let body = prost::Message::encode_to_vec(&req);
113 let resp_frame = client
114 .request(proto_id::QOT_REQUEST_HISTORY_KL, body)
115 .await?;
116
117 let resp: futu_proto::qot_request_history_kl::Response =
118 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
119
120 if resp.ret_type != 0 {
121 return Err(crate::server_err(resp.ret_type, resp.ret_msg));
122 }
123
124 let s2c = resp
125 .s2c
126 .ok_or(FutuError::Codec("missing s2c in RequestHistoryKL".into()))?;
127
128 Ok(RequestHistoryKLResult {
129 security: Security::from_proto(&s2c.security),
130 kl_list: s2c.kl_list.iter().map(KLine::from_proto).collect(),
131 next_req_key: s2c.next_req_key,
132 })
133}