Skip to main content

futu_cache/qot_right/
projection.rs

1use super::{QOT_RIGHT_LEVEL1, QOT_RIGHT_LEVEL2, QOT_RIGHT_LEVEL3, QOT_RIGHT_NO};
2
3pub type UsLv2Flags = (
4    Option<u32>,
5    Option<u32>,
6    Option<u32>,
7    Option<u32>,
8    Option<u32>,
9);
10pub type UsIndexFlags = (Option<u32>, Option<u32>, Option<u32>);
11pub type UsOtcAuths = (Option<u32>, Option<u32>);
12pub type UsFutureDetailAuths = (Option<u32>, Option<u32>, Option<u32>, Option<u32>);
13
14pub(super) fn hk_clt_to_api(clt: u32) -> i32 {
15    match clt {
16        1 => 3,
17        2 => 1,
18        3 => 2,
19        4 => 4,
20        _ => 0,
21    }
22}
23
24pub(super) fn us_clt_to_api(clt: u32) -> i32 {
25    match clt {
26        0 => 0,
27        1 => 2,
28        2 => 5,
29        _ => 5,
30    }
31}
32
33pub(super) fn us_backend_status_to_api(got: Option<u32>, flags: Option<UsLv2Flags>) -> Option<i32> {
34    let mut right = got.map(us_clt_to_api);
35    let Some((arca, _nyse, nasdaq_tv, _edg, _bzx)) = flags else {
36        return right;
37    };
38
39    // Ref: FutuOpenD/Src/NNProtoCenter/Quote/NNBiz_Qot_Right.cpp:190-223.
40    // C++ builds INNData_Qot_Right::GetUSQotStatus() from the base
41    // us_qut_got_auth and then promotes that API-display status with US LV2
42    // venue flags: TotalView + Arca => Level3, TotalView alone => Level2.
43    // Arca-only remains the base right. Rust keeps `us_qot_right` as an
44    // orderbook gate; this helper is only the C++ GetUserInfo/GUI projection.
45    if right != Some(QOT_RIGHT_NO) {
46        if arca == Some(1) && nasdaq_tv == Some(1) {
47            right = Some(QOT_RIGHT_LEVEL3);
48        } else if nasdaq_tv == Some(1) {
49            right = Some(QOT_RIGHT_LEVEL2);
50        }
51    }
52
53    right
54}
55
56pub(super) fn cn_clt_to_api(clt: u32) -> i32 {
57    match clt {
58        1 => 2,
59        2 => 3,
60        3 => 5,
61        _ => 5,
62    }
63}
64
65pub(super) fn other_clt_to_api(clt: u32) -> i32 {
66    match clt {
67        1 => 3,
68        2 => 2,
69        _ => 5,
70    }
71}
72
73pub(super) fn my_stock_common_clt_to_api(clt: u32) -> i32 {
74    match clt {
75        4 => QOT_RIGHT_LEVEL3,
76        3 => QOT_RIGHT_LEVEL2,
77        2 => QOT_RIGHT_LEVEL1,
78        _ => QOT_RIGHT_NO,
79    }
80}
81
82pub(super) fn jp_stock_clt_to_api(clt: u32) -> i32 {
83    match clt {
84        4 => QOT_RIGHT_LEVEL3,
85        1 => QOT_RIGHT_LEVEL2,
86        2 => QOT_RIGHT_LEVEL1,
87        _ => QOT_RIGHT_NO,
88    }
89}
90
91pub(super) fn us_future_clt_to_api(clt: u32) -> i32 {
92    match clt {
93        0 => 5,
94        1 => 3,
95        2 => 1,
96        3 => 3,
97        4 => 2,
98        _ => 5,
99    }
100}
101
102pub(super) fn us_option_clt_to_api(clt: u32) -> i32 {
103    match clt {
104        0 => 1,
105        1 => 2,
106        _ => 1,
107    }
108}
109
110pub(super) fn us_otc_comm_auth_to_api(
111    deal_data_auth: Option<u32>,
112    order_book_auth: Option<u32>,
113) -> i32 {
114    // Ref: FutuOpenD/Src/NNProtoCenter/Quote/NNBiz_Qot_Right.cpp:572-604.
115    // C++ treats missing OTC fields as COMM_AUTH_RT; OTC is usable only when
116    // both deal data and orderbook are realtime.
117    const COMM_AUTH_RT: u32 = 2;
118    let deal = deal_data_auth.unwrap_or(COMM_AUTH_RT);
119    let order_book = order_book_auth.unwrap_or(COMM_AUTH_RT);
120    if deal == COMM_AUTH_RT && order_book == COMM_AUTH_RT {
121        QOT_RIGHT_LEVEL1
122    } else {
123        QOT_RIGHT_NO
124    }
125}
126
127pub(super) fn crypto_auth_to_api(auth: u32) -> i32 {
128    if auth == 1 {
129        QOT_RIGHT_LEVEL1
130    } else {
131        QOT_RIGHT_NO
132    }
133}
134
135pub(super) fn us_index_flags_to_api(
136    dow_jones: Option<u32>,
137    nasdaq: Option<u32>,
138    standard_poor: Option<u32>,
139) -> Option<i32> {
140    // Ref: FutuOpenD/Src/NNProtoCenter/Quote/NNBiz_Qot_Right.cpp:529-566.
141    // Any present index flag makes the aggregate US index right known; any
142    // positive family grants Level1 for all US index symbols.
143    if dow_jones.is_none() && nasdaq.is_none() && standard_poor.is_none() {
144        return None;
145    }
146    let has_any = dow_jones == Some(1) || nasdaq == Some(1) || standard_poor == Some(1);
147    Some(if has_any {
148        QOT_RIGHT_LEVEL1
149    } else {
150        QOT_RIGHT_NO
151    })
152}
153
154pub(super) fn has_any_us_lv2_flag(flags: UsLv2Flags) -> bool {
155    let (arca, nyse, nasdaq_tv, edg, bzx) = flags;
156    arca == Some(1) || nyse == Some(1) || nasdaq_tv == Some(1) || edg == Some(1) || bzx == Some(1)
157}