futu_core/qot_right_gate/
subscribe.rs1use crate::diagnostic_text::jp_stock_quote_permission_hint;
2
3use super::common::{
4 qot_permission_action, qot_right_denies_realtime, qot_right_is_none, us_future_right_for_mkt,
5};
6use super::constants::{QOT_RIGHT_LEVEL1, QOT_RIGHT_NO, QOT_RIGHT_UNKNOWN};
7use super::model::{QotRightSnapshot, QotSubRightSecurity, SecurityRightClass};
8
9const QOT_MARKET_EVENT_CONTRACT: i32 = 101;
10
11pub fn qot_sub_right_reject_reason(
12 market: i32,
13 code: &str,
14 security: SecurityRightClass,
15 sub_types: &[i32],
16 rights: &QotRightSnapshot,
17) -> Option<String> {
18 if market == QOT_MARKET_EVENT_CONTRACT && rights.event_contract_qot_right == QOT_RIGHT_NO {
25 return Some(format!(
26 "Subscribe: EventContract 行情权限不足,不能操作 {code};\
27 请检查 EventContract quote permissions。"
28 ));
29 }
30
31 let wants_orderbook = sub_types.contains(&2);
32 let wants_ticker = sub_types.contains(&4);
33 let wants_broker = sub_types.contains(&14);
34 let is_option = security.is_option();
35 let is_hk_future = security.is_hk_future();
36 let is_future = security.is_future(market);
37 let is_index = security.is_index();
38 let is_crypto = security.is_crypto(market);
39 let is_sg_stock = security.is_sg_security_market(market);
40 let is_my_stock = security.is_my_security_market(market);
41 let is_jp_stock = security.is_jp_security_market(market);
42 let is_other = !is_option && !is_future && !is_index;
43
44 match market {
45 _ if is_crypto && qot_right_denies_realtime(rights.cc_qot_right) => Some(format!(
46 "Subscribe: crypto 行情权限不足,不能订阅 {code};\
47 请检查 Crypto MarketCrypto quote permissions;{}。",
48 qot_permission_action(Some("Crypto"), code)
49 )),
50 21 if qot_right_denies_realtime(rights.sh_qot_right) => Some(format!(
51 "Subscribe: 沪股行情权限不足,不能订阅 SH market;{}。",
52 qot_permission_action(Some("SH"), code)
53 )),
54 22 if qot_right_denies_realtime(rights.sz_qot_right) => Some(format!(
55 "Subscribe: 深股行情权限不足,不能订阅 SZ market;{}。",
56 qot_permission_action(Some("SZ"), code)
57 )),
58 31 if security.is_sg_future() && qot_right_denies_realtime(rights.sg_future_qot_right) => {
59 Some(format!(
60 "Subscribe: SG future 行情权限不足,不能订阅 SG future;{}。",
61 qot_permission_action(Some("SG"), code)
62 ))
63 }
64 31 if is_sg_stock && qot_right_is_none(rights.sg_stock_qot_right) => Some(format!(
65 "Subscribe: SG stock 行情权限不足,不能订阅 {code};{}。",
66 qot_permission_action(Some("SG"), code)
67 )),
68 61 if is_my_stock && qot_right_is_none(rights.my_stock_qot_right) => Some(format!(
69 "Subscribe: MY stock 行情权限不足,不能订阅 {code};{}。",
70 qot_permission_action(Some("MY"), code)
71 )),
72 41 if security.is_jp_future() && qot_right_denies_realtime(rights.jp_future_qot_right) => {
73 Some(format!(
74 "Subscribe: JP future 行情权限不足,不能订阅 JP future;{}。",
75 qot_permission_action(Some("JP"), code)
76 ))
77 }
78 41 if is_jp_stock && qot_right_is_none(rights.jp_stock_qot_right) => Some(format!(
79 "Subscribe: JP stock / 日股行情权限不足,不能订阅 {code};{}",
80 jp_stock_quote_permission_hint().text_with_code()
81 )),
82 1 if is_other || is_index => {
83 if qot_right_denies_realtime(rights.hk_qot_right) {
84 Some(format!(
85 "Subscribe: HK 行情权限不足,不能订阅 {code};{}。",
86 qot_permission_action(Some("HK"), code)
87 ))
88 } else if wants_broker && rights.hk_qot_right == QOT_RIGHT_LEVEL1 {
89 Some(format!(
90 "Subscribe: HK Level1 权限不支持 broker queue 订阅 ({code})。"
91 ))
92 } else {
93 None
94 }
95 }
96 1 if is_option => {
97 if qot_right_denies_realtime(rights.hk_option_qot_right) {
98 Some(format!(
99 "Subscribe: HK option 行情权限不足,不能订阅 {code}。"
100 ))
101 } else if wants_orderbook && rights.hk_option_orderbook_depth == Some(0) {
102 Some(format!(
103 "Subscribe: HK option order book depth 为 0,不能订阅摆盘 ({code})。"
104 ))
105 } else if wants_ticker && rights.hk_option_qot_right == QOT_RIGHT_LEVEL1 {
106 Some(format!(
107 "Subscribe: HK option Level1 权限不支持 ticker 订阅 ({code});Ticker 需要 LV2。"
108 ))
109 } else {
110 None
111 }
112 }
113 1 if is_hk_future => {
114 if qot_right_denies_realtime(rights.hk_future_qot_right) {
115 Some(format!(
116 "Subscribe: HK future 行情权限不足,不能订阅 {code}。"
117 ))
118 } else if wants_orderbook && rights.hk_future_orderbook_depth == Some(0) {
119 Some(format!(
120 "Subscribe: HK future order book depth 为 0,不能订阅摆盘 ({code})。"
121 ))
122 } else if wants_ticker && rights.hk_future_qot_right == QOT_RIGHT_LEVEL1 {
123 Some(format!(
124 "Subscribe: HK future Level1 权限不支持 ticker 订阅 ({code});Ticker 需要 LV2。"
125 ))
126 } else {
127 None
128 }
129 }
130 11 if is_option && qot_right_denies_realtime(rights.us_option_qot_right) => Some(format!(
131 "Subscribe: US option 行情权限不足,不能订阅 {code};{}。",
132 qot_permission_action(Some("US"), code)
133 )),
134 11 if is_future => {
135 let right = us_future_right_for_mkt(rights, security.mkt_id);
136 if right == QOT_RIGHT_UNKNOWN || qot_right_denies_realtime(right) {
137 Some(format!(
138 "Subscribe: US future 行情权限不足或未知,不能订阅 {code};{}。",
139 qot_permission_action(Some("US"), code)
140 ))
141 } else {
142 None
143 }
144 }
145 11 if is_index && qot_right_denies_realtime(rights.us_index_qot_right) => Some(format!(
146 "Subscribe: US index 行情权限不足,不能订阅 {code};{}。",
147 qot_permission_action(Some("US"), code)
148 )),
149 11 if security.mkt_id == 13 && qot_right_denies_realtime(rights.us_otc_qot_right) => {
150 Some(format!(
151 "Subscribe: US OTC 行情权限不足,不能订阅 {code};{}。",
152 qot_permission_action(Some("US"), code)
153 ))
154 }
155 11 if is_other && qot_right_denies_realtime(rights.us_qot_right) => Some(format!(
156 "Subscribe: US 行情权限不足,不能订阅 {code};{}。",
157 qot_permission_action(Some("US"), code)
158 )),
159 _ => None,
160 }
161}
162
163pub fn first_qot_sub_right_reject_reason(
164 securities: &[QotSubRightSecurity<'_>],
165 sub_types: &[i32],
166 rights: &QotRightSnapshot,
167) -> Option<String> {
168 securities.iter().find_map(|security| {
169 qot_sub_right_reject_reason(
170 security.market,
171 security.code,
172 security.security,
173 sub_types,
174 rights,
175 )
176 })
177}