1use crate::static_data::CachedSecurityInfo;
2
3use futu_domain_qot_orderbook::entitlement::OrderBookRightFacts;
4use futu_domain_qot_orderbook::{OrderBookEntitlementFacts, OrderBookSecurityFacts};
5use futu_domain_qot_subscription::{
6 SubscriptionQotRightFacts, SubscriptionSecurityFacts, basic_qot_uses_us_pre_after_detail_facts,
7 lv2_order_groups_for_security_facts, lv2_order_groups_for_security_facts_with_dynamic,
8};
9
10use super::{
11 JP_LV2_ORDER_STOCK, JP_LV2_ORDER_STOCK_FULL, Lv2OrderGroupPlan, QOT_MARKET_CC_SECURITY,
12 QOT_RIGHT_BMP, QotRightData, SECURITY_TYPE_CRYPTO, SECURITY_TYPE_DRVT, SECURITY_TYPE_FUTURE,
13 SECURITY_TYPE_INDEX, SG_LV2_ORDER_STOCK_ODD_LOT,
14};
15
16fn is_hk_future_market(info: &CachedSecurityInfo) -> bool {
17 info.sec_type == SECURITY_TYPE_FUTURE && matches!(info.mkt_id, 5 | 6 | 110..=119)
18}
19
20fn is_us_future_market(info: &CachedSecurityInfo) -> bool {
21 info.sec_type == SECURITY_TYPE_FUTURE && (60..=109).contains(&info.mkt_id)
22}
23
24fn is_sg_security_market(info: &CachedSecurityInfo) -> bool {
25 (180..=184).contains(&info.mkt_id)
26 || (info.market == 31
27 && info.sec_type != SECURITY_TYPE_FUTURE
28 && info.sec_type != SECURITY_TYPE_DRVT)
29}
30
31fn is_jp_future_market(info: &CachedSecurityInfo) -> bool {
32 info.sec_type == SECURITY_TYPE_FUTURE && (185..=194).contains(&info.mkt_id)
33}
34
35fn is_jp_security_market(info: &CachedSecurityInfo) -> bool {
36 (830..=849).contains(&info.mkt_id)
37 || (info.market == 41
38 && info.sec_type != SECURITY_TYPE_FUTURE
39 && info.sec_type != SECURITY_TYPE_DRVT
40 && !is_jp_future_market(info)
41 && !(800..=829).contains(&info.mkt_id))
42}
43
44fn is_hk_option_market(info: &CachedSecurityInfo) -> bool {
45 info.sec_type == SECURITY_TYPE_DRVT && matches!(info.mkt_id, 7 | 8 | 570..=579)
46}
47
48fn is_us_option_market(info: &CachedSecurityInfo) -> bool {
49 info.sec_type == SECURITY_TYPE_DRVT && (41..=49).contains(&info.mkt_id)
50}
51
52fn is_hk_security_market(info: &CachedSecurityInfo) -> bool {
53 matches!(info.mkt_id, 1..=4 | 1000..=1049)
54 || (info.market == 1
55 && !is_hk_future_market(info)
56 && !is_hk_option_market(info)
57 && info.sec_type != SECURITY_TYPE_FUTURE
58 && info.sec_type != SECURITY_TYPE_DRVT)
59}
60
61pub(super) fn snapshot_masks_hk_bmp_bid_ask_impl(
66 info: &CachedSecurityInfo,
67 qr: &QotRightData,
68) -> bool {
69 let is_hk = matches!(info.market, 1 | 2);
70 if !is_hk {
71 return false;
72 }
73
74 if is_hk_option_market(info) {
75 return qr.hk_option_qot_right == QOT_RIGHT_BMP;
76 }
77 if is_hk_future_market(info) {
78 return qr.hk_future_qot_right == QOT_RIGHT_BMP;
79 }
80 is_hk_security_market(info) && qr.hk_qot_right == QOT_RIGHT_BMP
81}
82
83pub fn snapshot_masks_hk_bmp_bid_ask(info: &CachedSecurityInfo, qr: &QotRightData) -> bool {
84 snapshot_masks_hk_bmp_bid_ask_impl(info, qr)
85}
86
87fn is_us_security_market(info: &CachedSecurityInfo) -> bool {
88 matches!(info.mkt_id, 10..=29 | 1200..=1249)
89 || (info.market == 11
90 && !is_us_future_market(info)
91 && !is_us_option_market(info)
92 && info.sec_type != SECURITY_TYPE_FUTURE
93 && info.sec_type != SECURITY_TYPE_DRVT)
94}
95
96pub fn us_lv2_order_uses_exchange_cache(info: &CachedSecurityInfo) -> bool {
102 is_us_security_market(info) && info.sec_type != SECURITY_TYPE_INDEX
103}
104
105pub fn is_crypto_market(info: &CachedSecurityInfo) -> bool {
111 info.sec_type == SECURITY_TYPE_CRYPTO
112 || info.market == QOT_MARKET_CC_SECURITY
113 || (360..=459).contains(&info.mkt_id)
114}
115
116pub(super) fn orderbook_security_facts_impl(info: &CachedSecurityInfo) -> OrderBookSecurityFacts {
117 OrderBookSecurityFacts::from_static_fields(
118 info.stock_id,
119 info.market,
120 info.mkt_id,
121 info.sec_type,
122 )
123}
124
125pub(super) fn orderbook_right_facts_impl(qr: &QotRightData) -> OrderBookRightFacts {
126 OrderBookRightFacts {
127 hk_qot_right: qr.hk_qot_right,
128 us_qot_right: qr.us_qot_right,
129 sh_qot_right: qr.sh_qot_right,
130 sz_qot_right: qr.sz_qot_right,
131 hk_option_qot_right: qr.hk_option_qot_right,
132 hk_future_qot_right: qr.hk_future_qot_right,
133 hk_option_orderbook_depth: qr.hk_option_orderbook_depth,
134 hk_future_orderbook_depth: qr.hk_future_orderbook_depth,
135 us_option_qot_right: qr.us_option_qot_right,
136 us_cme_future_qot_right: qr.us_cme_future_qot_right,
137 us_cbot_future_qot_right: qr.us_cbot_future_qot_right,
138 us_nymex_future_qot_right: qr.us_nymex_future_qot_right,
139 us_comex_future_qot_right: qr.us_comex_future_qot_right,
140 us_cboe_future_qot_right: qr.us_cboe_future_qot_right,
141 sg_future_qot_right: qr.sg_future_qot_right,
142 jp_future_qot_right: qr.jp_future_qot_right,
143 sg_stock_qot_right: qr.sg_stock_qot_right,
144 jp_stock_qot_right: qr.jp_stock_qot_right,
145 my_stock_qot_right: qr.my_stock_qot_right,
146 cc_qot_right: qr.cc_qot_right,
147 cc_pt_orderbook_qot_right: qr.cc_pt_orderbook_qot_right,
148 us_lv2_arca_qot_right: qr.us_lv2_arca_qot_right,
149 us_lv2_nyse_qot_right: qr.us_lv2_nyse_qot_right,
150 us_lv2_nasdaq_totalview_qot_right: qr.us_lv2_nasdaq_totalview_qot_right,
151 }
152}
153
154fn orderbook_entitlement_facts_impl(
155 info: &CachedSecurityInfo,
156 qr: &QotRightData,
157) -> OrderBookEntitlementFacts {
158 futu_domain_qot_orderbook::resolve_orderbook_entitlement_facts(
159 &orderbook_security_facts_impl(info),
160 &orderbook_right_facts_impl(qr),
161 )
162}
163
164pub fn basic_qot_uses_us_pre_after_detail(info: &CachedSecurityInfo) -> bool {
172 basic_qot_uses_us_pre_after_detail_facts(&subscription_security_facts_impl(info))
173}
174
175fn subscription_security_facts_impl(info: &CachedSecurityInfo) -> SubscriptionSecurityFacts {
176 SubscriptionSecurityFacts {
177 stock_id: info.stock_id,
178 sec_type: info.sec_type,
179 mkt_id: info.mkt_id,
180 market: info.market,
181 }
182}
183
184fn subscription_qot_right_facts_impl(qr: &QotRightData) -> SubscriptionQotRightFacts {
185 SubscriptionQotRightFacts {
186 us_qot_right: qr.us_qot_right,
187 us_cme_future_qot_right: qr.us_cme_future_qot_right,
188 us_cbot_future_qot_right: qr.us_cbot_future_qot_right,
189 us_nymex_future_qot_right: qr.us_nymex_future_qot_right,
190 us_comex_future_qot_right: qr.us_comex_future_qot_right,
191 us_cboe_future_qot_right: qr.us_cboe_future_qot_right,
192 sg_stock_qot_right: qr.sg_stock_qot_right,
193 jp_stock_qot_right: qr.jp_stock_qot_right,
194 us_lv2_arca_qot_right: qr.us_lv2_arca_qot_right,
195 us_lv2_nyse_qot_right: qr.us_lv2_nyse_qot_right,
196 us_lv2_nasdaq_totalview_qot_right: qr.us_lv2_nasdaq_totalview_qot_right,
197 event_contract_qot_right: qr.event_contract_qot_right,
198 }
199}
200
201pub(super) fn lv2_order_groups_for_security_impl(
202 info: &CachedSecurityInfo,
203 qr: &QotRightData,
204 extended_time: bool,
205) -> Vec<Lv2OrderGroupPlan> {
206 lv2_order_groups_for_security_facts(
207 &subscription_security_facts_impl(info),
208 &subscription_qot_right_facts_impl(qr),
209 extended_time,
210 )
211}
212
213pub fn lv2_order_groups_for_security(
214 info: &CachedSecurityInfo,
215 qr: &QotRightData,
216 extended_time: bool,
217) -> Vec<Lv2OrderGroupPlan> {
218 lv2_order_groups_for_security_impl(info, qr, extended_time)
219}
220
221pub fn lv2_order_groups_for_security_with_dynamic(
222 info: &CachedSecurityInfo,
223 qr: &QotRightData,
224 extended_time: bool,
225 dynamic_lv2_prob_sum: Option<i32>,
226) -> Vec<Lv2OrderGroupPlan> {
227 lv2_order_groups_for_security_facts_with_dynamic(
228 &subscription_security_facts_impl(info),
229 &subscription_qot_right_facts_impl(qr),
230 extended_time,
231 dynamic_lv2_prob_sum,
232 )
233}
234
235pub fn has_lv2_order_groups_for_security(info: &CachedSecurityInfo, qr: &QotRightData) -> bool {
236 !lv2_order_groups_for_security_impl(info, qr, true).is_empty()
237}
238
239pub fn order_book_max_depth_for_security(info: &CachedSecurityInfo, qr: &QotRightData) -> usize {
240 orderbook_entitlement_facts_impl(info, qr).max_depth
241}
242
243pub fn order_book_requires_backend_full_depth(
249 info: &CachedSecurityInfo,
250 qr: &QotRightData,
251) -> bool {
252 orderbook_entitlement_facts_impl(info, qr).requires_backend_full_depth
253}
254
255pub fn order_book_uses_backend_side_count(info: &CachedSecurityInfo, qr: &QotRightData) -> bool {
256 orderbook_entitlement_facts_impl(info, qr).requires_backend_full_depth
257}
258
259pub fn order_book_read_uses_requested_count(info: &CachedSecurityInfo, qr: &QotRightData) -> bool {
266 orderbook_entitlement_facts_impl(info, qr).read_uses_requested_count
267}
268
269pub fn order_book_requires_accepted_lv2_push(info: &CachedSecurityInfo, qr: &QotRightData) -> bool {
277 orderbook_entitlement_facts_impl(info, qr).requires_accepted_lv2_push
278}
279
280pub fn lv2_order_uses_sg_odd_lot_cache(info: &CachedSecurityInfo, lv2_type: i32) -> bool {
281 is_sg_security_market(info) && lv2_type == SG_LV2_ORDER_STOCK_ODD_LOT as i32
282}
283
284pub fn lv2_order_uses_jp_main_cache(info: &CachedSecurityInfo, lv2_type: i32) -> bool {
285 is_jp_security_market(info)
286 && matches!(
287 lv2_type,
288 value if value == JP_LV2_ORDER_STOCK as i32
289 || value == JP_LV2_ORDER_STOCK_FULL as i32
290 )
291}