1use futu_core::error::{FutuError, Result};
2use futu_core::proto_id;
3use futu_net::client::FutuClient;
4
5use crate::types::Security;
6
7#[derive(Debug, Clone)]
9pub struct Ticker {
10 pub time: String,
11 pub sequence: i64,
12 pub dir: i32,
13 pub price: f64,
14 pub volume: i64,
15 pub turnover: f64,
16 pub ticker_type: Option<i32>,
17 pub timestamp: f64,
18}
19
20impl Ticker {
21 pub fn from_proto(t: &futu_proto::qot_common::Ticker) -> Self {
22 Self {
23 time: t.time.clone(),
24 sequence: t.sequence,
25 dir: t.dir,
26 price: t.price,
27 volume: t.volume,
28 turnover: t.turnover,
29 ticker_type: t.r#type,
30 timestamp: t.timestamp.unwrap_or(0.0),
31 }
32 }
33}
34
35#[derive(Debug, Clone)]
37pub struct TickerResult {
38 pub security: Security,
39 pub ticker_list: Vec<Ticker>,
40}
41
42pub async fn get_ticker(
47 client: &FutuClient,
48 security: &Security,
49 max_ret_num: i32,
50) -> Result<TickerResult> {
51 let req = futu_proto::qot_get_ticker::Request {
52 c2s: futu_proto::qot_get_ticker::C2s {
53 security: security.to_proto(),
54 max_ret_num,
55 },
56 };
57
58 let body = prost::Message::encode_to_vec(&req);
59 let resp_frame = client.request(proto_id::QOT_GET_TICKER, body).await?;
60
61 let resp: futu_proto::qot_get_ticker::Response =
62 prost::Message::decode(resp_frame.body.as_ref()).map_err(FutuError::Proto)?;
63
64 if resp.ret_type != 0 {
65 return Err(FutuError::ServerError {
66 ret_type: resp.ret_type,
67 msg: resp.ret_msg.unwrap_or_default(),
68 });
69 }
70
71 let s2c = resp
72 .s2c
73 .ok_or(FutuError::Codec("missing s2c in GetTicker".into()))?;
74
75 Ok(TickerResult {
76 security: Security::from_proto(&s2c.security),
77 ticker_list: s2c.ticker_list.iter().map(Ticker::from_proto).collect(),
78 })
79}