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