futu_backend/quote_sub/
ticker.rs1use prost::Message;
2
3use futu_core::error::{FutuError, Result};
4
5use crate::conn::BackendConn;
6use crate::proto_internal::ft_cmd_tick;
7
8use super::{CMD_QOT_PULL_TICKER, ftapi_market_to_quote_mkt};
9
10const TICKER_FETCH_LATEST_KEY: u64 = u64::MAX;
12const TICKER_LATEST_DATE_TIME_S: u32 = u32::MAX;
14
15pub(super) mod nn_quote_session {
16 pub const RTH: i32 = 0;
17 pub const ETH: i32 = 1;
18 pub const ALL: i32 = 2;
19}
20
21pub(super) mod tick_period_type {
22 pub const NORMAL: u32 = 0;
24 pub const BEFORE: u32 = 1;
25 pub const AFTER: u32 = 2;
26 pub const OVERNIGHT: u32 = 4;
27}
28
29pub(super) fn common_session_to_nn(session: i32) -> i32 {
30 match session {
31 2 => nn_quote_session::ETH,
33 3 => nn_quote_session::ALL,
34 _ => nn_quote_session::RTH,
35 }
36}
37
38pub(super) fn ticker_periods_for_nn_session(nn_session: i32) -> Vec<u32> {
39 match nn_session {
40 nn_quote_session::ALL => vec![
41 tick_period_type::NORMAL,
42 tick_period_type::BEFORE,
43 tick_period_type::AFTER,
44 tick_period_type::OVERNIGHT,
45 ],
46 nn_quote_session::ETH => vec![
47 tick_period_type::NORMAL,
48 tick_period_type::BEFORE,
49 tick_period_type::AFTER,
50 ],
51 _ => vec![tick_period_type::NORMAL],
52 }
53}
54
55pub async fn pull_latest_ticker(
64 backend: &BackendConn,
65 stock_id: u64,
66 nn_mkt_type: u8,
67 common_session: i32,
68 pull_count: u32,
69 broker_id: Option<i32>,
70) -> Result<ft_cmd_tick::TickRsp> {
71 if stock_id == 0 || pull_count == 0 {
72 return Err(FutuError::Codec(format!(
73 "PullLatestTicker: invalid stock_id={stock_id} pull_count={pull_count}"
74 )));
75 }
76
77 let nn_session = if nn_mkt_type == ftapi_market_to_quote_mkt(11) {
80 common_session_to_nn(common_session)
81 } else {
82 nn_quote_session::RTH
83 };
84
85 let req = ft_cmd_tick::TickReq {
86 security_id: Some(stock_id),
87 date_time_s: Some(TICKER_LATEST_DATE_TIME_S),
88 begin_tick_key: Some(TICKER_FETCH_LATEST_KEY),
89 tick_count: Some(pull_count),
90 tick_period_type: None,
91 tick_period_type_ex: ticker_periods_for_nn_session(nn_session),
92 req_auth: None,
93 end_tick_key: None,
94 date_time_s_v2: None,
95 broker_id,
98 };
99
100 let mut reserved = [0u8; 10];
101 reserved[0] = nn_mkt_type;
102 let frame = backend
105 .request_with_reserved(CMD_QOT_PULL_TICKER, req.encode_to_vec(), reserved)
106 .await?;
107 let rsp: ft_cmd_tick::TickRsp = Message::decode(frame.body.as_ref())?;
108 let result = rsp.result.unwrap_or(-1);
109 if result != 0 {
110 return Err(FutuError::ServerError {
111 ret_type: result,
112 msg: format!("CMD6128 PullLatestTicker result={result}"),
113 });
114 }
115 Ok(rsp)
116}