1use anyhow::Result;
17
18use crate::output::OutputFormat;
19
20mod combo;
21mod contract;
22mod transport;
23mod verification;
24
25#[cfg(test)]
26use combo::{ensure_combo_order_confirmed, packet_id_for_idempotency_key};
27pub use combo::{run_combo_max_trd_qtys, run_place_combo_order};
28use contract::parse_c2s;
29#[cfg(test)]
30use contract::{parse_combo_max_c2s_json, parse_place_combo_c2s_json};
31use transport::{ensure_success, print_proto_response, send_proto};
32pub use verification::run_verification;
33#[cfg(test)]
34use verification::validate_verification_args;
35
36macro_rules! qot_proto_json_command {
37 ($fn_name:ident, $label:literal, $proto_id:expr, $module:ident) => {
38 pub async fn $fn_name(gateway: &str, c2s_json: &str, output: OutputFormat) -> Result<()> {
39 let c2s = parse_c2s::<futu_proto::$module::C2s>($label, c2s_json)?;
40 let request = futu_proto::$module::Request { c2s };
41 let response: futu_proto::$module::Response =
42 send_proto(gateway, concat!("futucli-", $label), $proto_id, request).await?;
43 ensure_success(
44 $label,
45 response.ret_type,
46 response.ret_msg.as_deref(),
47 response.err_code,
48 )?;
49 print_proto_response(output, &response)
50 }
51 };
52}
53
54mod trd_commands;
56pub use trd_commands::*;
57
58qot_proto_json_command!(
59 run_option_quote,
60 "option-quote",
61 futu_core::proto_id::QOT_GET_OPTION_QUOTE,
62 qot_get_option_quote
63);
64qot_proto_json_command!(
65 run_option_strategy,
66 "option-strategy",
67 futu_core::proto_id::QOT_GET_OPTION_STRATEGY,
68 qot_get_option_strategy
69);
70qot_proto_json_command!(
71 run_option_strategy_analysis,
72 "option-strategy-analysis",
73 futu_core::proto_id::QOT_GET_OPTION_STRATEGY_ANALYSIS,
74 qot_get_option_strategy_analysis
75);
76qot_proto_json_command!(
77 run_option_strategy_spread,
78 "option-strategy-spread",
79 futu_core::proto_id::QOT_GET_OPTION_STRATEGY_SPREAD,
80 qot_get_option_strategy_spread
81);
82qot_proto_json_command!(
83 run_earnings_calendar,
84 "earnings-calendar",
85 futu_core::proto_id::QOT_GET_EARNINGS_CALENDAR,
86 qot_get_earnings_calendar
87);
88qot_proto_json_command!(
89 run_macro_indicator_list,
90 "macro-indicator-list",
91 futu_core::proto_id::QOT_GET_MACRO_INDICATOR_LIST,
92 qot_get_macro_indicator_list
93);
94qot_proto_json_command!(
95 run_security_trading_sessions,
96 "security-trading-sessions",
97 futu_core::proto_id::QOT_GET_SECURITY_TRADING_SESSIONS,
98 qot_get_security_trading_sessions
99);
100qot_proto_json_command!(
101 run_market_trading_sessions,
102 "market-trading-sessions",
103 futu_core::proto_id::QOT_GET_MARKET_TRADING_SESSIONS,
104 qot_get_market_trading_sessions
105);
106qot_proto_json_command!(
107 run_kline_pattern,
108 "kline-pattern",
109 futu_core::proto_id::QOT_GET_KLINE_PATTERN,
110 qot_get_kline_pattern
111);
112qot_proto_json_command!(
113 run_kline_pattern_statistics,
114 "kline-pattern-statistics",
115 futu_core::proto_id::QOT_GET_KLINE_PATTERN_STATISTICS,
116 qot_get_kline_pattern_statistics
117);
118qot_proto_json_command!(
119 run_kline_pattern_stocks,
120 "kline-pattern-stocks",
121 futu_core::proto_id::QOT_GET_KLINE_PATTERN_STOCKS,
122 qot_get_kline_pattern_stocks
123);
124qot_proto_json_command!(
125 run_kline_pattern_performance,
126 "kline-pattern-performance",
127 futu_core::proto_id::QOT_GET_KLINE_PATTERN_PERFORMANCE,
128 qot_get_kline_pattern_performance
129);
130qot_proto_json_command!(
131 run_kline_pattern_catalog,
132 "kline-pattern-catalog",
133 futu_core::proto_id::QOT_GET_KLINE_PATTERN_CATALOG,
134 qot_get_kline_pattern_catalog
135);
136qot_proto_json_command!(
137 run_hot_news,
138 "hot-news",
139 futu_core::proto_id::QOT_GET_HOT_NEWS,
140 qot_get_hot_news
141);
142qot_proto_json_command!(
143 run_latest_news,
144 "latest-news",
145 futu_core::proto_id::QOT_GET_LATEST_NEWS,
146 qot_get_latest_news
147);
148qot_proto_json_command!(
149 run_watchlist_news,
150 "watchlist-news",
151 futu_core::proto_id::QOT_GET_WATCHLIST_NEWS,
152 qot_get_watchlist_news
153);
154qot_proto_json_command!(
155 run_watchlist_announcement,
156 "watchlist-announcement",
157 futu_core::proto_id::QOT_GET_WATCHLIST_ANNOUNCEMENT,
158 qot_get_watchlist_announcement
159);
160qot_proto_json_command!(
161 run_watchlist_rating,
162 "watchlist-rating",
163 futu_core::proto_id::QOT_GET_WATCHLIST_RATING,
164 qot_get_watchlist_rating
165);
166qot_proto_json_command!(
167 run_stock_news,
168 "stock-news",
169 futu_core::proto_id::QOT_GET_STOCK_NEWS,
170 qot_get_stock_news
171);
172qot_proto_json_command!(
173 run_etf_screen,
174 "etf-screen",
175 futu_core::proto_id::QOT_ETF_SCREEN,
176 qot_get_etf_screen
177);
178qot_proto_json_command!(
179 run_fund_screen,
180 "fund-screen",
181 futu_core::proto_id::QOT_FUND_SCREEN,
182 qot_get_fund_screen
183);
184qot_proto_json_command!(
185 run_future_screen,
186 "future-screen",
187 futu_core::proto_id::QOT_FUTURE_SCREEN,
188 qot_get_future_screen
189);
190qot_proto_json_command!(
191 run_bond_screen,
192 "bond-screen",
193 futu_core::proto_id::QOT_BOND_SCREEN,
194 qot_get_bond_screen
195);
196qot_proto_json_command!(
197 run_macro_indicator_history,
198 "macro-indicator-history",
199 futu_core::proto_id::QOT_GET_MACRO_INDICATOR_HISTORY,
200 qot_get_macro_indicator_history
201);
202qot_proto_json_command!(
203 run_fed_watch_target_rate,
204 "fed-watch-target-rate",
205 futu_core::proto_id::QOT_GET_FED_WATCH_TARGET_RATE,
206 qot_get_fed_watch_target_rate
207);
208qot_proto_json_command!(
209 run_fed_watch_dot_plot,
210 "fed-watch-dot-plot",
211 futu_core::proto_id::QOT_GET_FED_WATCH_DOT_PLOT,
212 qot_get_fed_watch_dot_plot
213);
214qot_proto_json_command!(
215 run_earnings_beat_rank,
216 "earnings-beat-rank",
217 futu_core::proto_id::QOT_GET_EARNINGS_BEAT_RANK,
218 qot_get_earnings_beat_rank
219);
220qot_proto_json_command!(
221 run_dividend_rank,
222 "dividend-rank",
223 futu_core::proto_id::QOT_GET_DIVIDEND_RANK,
224 qot_get_dividend_rank
225);
226qot_proto_json_command!(
227 run_dividend_calendar,
228 "dividend-calendar",
229 futu_core::proto_id::QOT_GET_DIVIDEND_CALENDAR,
230 qot_get_dividend_calendar
231);
232qot_proto_json_command!(
233 run_economic_calendar,
234 "economic-calendar",
235 futu_core::proto_id::QOT_GET_ECONOMIC_CALENDAR,
236 qot_get_economic_calendar
237);
238qot_proto_json_command!(
239 run_us_pre_market_rank,
240 "us-pre-market-rank",
241 futu_core::proto_id::QOT_GET_US_PRE_MARKET_RANK,
242 qot_get_us_pre_market_rank
243);
244qot_proto_json_command!(
245 run_us_after_hours_rank,
246 "us-after-hours-rank",
247 futu_core::proto_id::QOT_GET_US_AFTER_HOURS_RANK,
248 qot_get_us_after_hours_rank
249);
250qot_proto_json_command!(
251 run_us_overnight_rank,
252 "us-overnight-rank",
253 futu_core::proto_id::QOT_GET_US_OVERNIGHT_RANK,
254 qot_get_us_overnight_rank
255);
256qot_proto_json_command!(
257 run_top_movers_rank,
258 "top-movers-rank",
259 futu_core::proto_id::QOT_GET_TOP_MOVERS_RANK,
260 qot_get_top_movers_rank
261);
262qot_proto_json_command!(
263 run_hot_list,
264 "hot-list",
265 futu_core::proto_id::QOT_GET_HOT_LIST,
266 qot_get_hot_list
267);
268qot_proto_json_command!(
269 run_short_selling_rank,
270 "short-selling-rank",
271 futu_core::proto_id::QOT_GET_SHORT_SELLING_RANK,
272 qot_get_short_selling_rank
273);
274qot_proto_json_command!(
275 run_period_change_rank,
276 "period-change-rank",
277 futu_core::proto_id::QOT_GET_PERIOD_CHANGE_RANK,
278 qot_get_period_change_rank
279);
280qot_proto_json_command!(
281 run_high_dividend_soe_rank,
282 "high-dividend-soe-rank",
283 futu_core::proto_id::QOT_GET_HIGH_DIVIDEND_SOE_RANK,
284 qot_get_high_dividend_soe_rank
285);
286qot_proto_json_command!(
287 run_institution_list,
288 "institution-list",
289 futu_core::proto_id::QOT_GET_INSTITUTION_LIST,
290 qot_get_institution_list
291);
292qot_proto_json_command!(
293 run_institution_profile,
294 "institution-profile",
295 futu_core::proto_id::QOT_GET_INSTITUTION_PROFILE,
296 qot_get_institution_profile
297);
298qot_proto_json_command!(
299 run_institution_distribution,
300 "institution-distribution",
301 futu_core::proto_id::QOT_GET_INSTITUTION_DISTRIBUTION,
302 qot_get_institution_distribution
303);
304qot_proto_json_command!(
305 run_institution_holding_change,
306 "institution-holding-change",
307 futu_core::proto_id::QOT_GET_INSTITUTION_HOLDING_CHANGE,
308 qot_get_institution_holding_change
309);
310qot_proto_json_command!(
311 run_institution_holding_list,
312 "institution-holding-list",
313 futu_core::proto_id::QOT_GET_INSTITUTION_HOLDING_LIST,
314 qot_get_institution_holding_list
315);
316qot_proto_json_command!(
317 run_ark_fund_holding,
318 "ark-fund-holding",
319 futu_core::proto_id::QOT_GET_ARK_FUND_HOLDING,
320 qot_get_ark_fund_holding
321);
322qot_proto_json_command!(
323 run_ark_stock_dynamic,
324 "ark-stock-dynamic",
325 futu_core::proto_id::QOT_GET_ARK_STOCK_DYNAMIC,
326 qot_get_ark_stock_dynamic
327);
328qot_proto_json_command!(
329 run_ark_active_transaction,
330 "ark-active-transaction",
331 futu_core::proto_id::QOT_GET_ARK_ACTIVE_TRANSACTION,
332 qot_get_ark_active_transaction
333);
334qot_proto_json_command!(
335 run_rating_change,
336 "rating-change",
337 futu_core::proto_id::QOT_GET_RATING_CHANGE,
338 qot_get_rating_change
339);
340qot_proto_json_command!(
341 run_search_quote,
342 "search-quote",
343 futu_core::proto_id::QOT_GET_SEARCH_QUOTE,
344 qot_get_search_quote
345);
346qot_proto_json_command!(
347 run_search_news,
348 "search-news",
349 futu_core::proto_id::QOT_GET_SEARCH_NEWS,
350 qot_get_search_news
351);
352qot_proto_json_command!(
353 run_indicator_list,
354 "indicator-list",
355 futu_core::proto_id::QOT_GET_INDICATOR_LIST,
356 qot_get_indicator_list
357);
358qot_proto_json_command!(
359 run_option_market_statistic,
360 "option-market-statistic",
361 futu_core::proto_id::QOT_GET_OPTION_MARKET_STATISTIC,
362 qot_get_option_market_statistic
363);
364qot_proto_json_command!(
365 run_option_underlying_his_statistic,
366 "option-underlying-his-statistic",
367 futu_core::proto_id::QOT_GET_OPTION_UNDERLYING_HIS_STATISTIC,
368 qot_get_option_underlying_his_statistic
369);
370qot_proto_json_command!(
371 run_option_underlying_overview,
372 "option-underlying-overview",
373 futu_core::proto_id::QOT_GET_OPTION_UNDERLYING_OVERVIEW,
374 qot_get_option_underlying_overview
375);
376qot_proto_json_command!(
377 run_option_underlying_his_volatility,
378 "option-underlying-his-volatility",
379 futu_core::proto_id::QOT_GET_OPTION_UNDERLYING_HIS_VOLATILITY,
380 qot_get_option_underlying_his_volatility
381);
382qot_proto_json_command!(
383 run_option_underlying_rank,
384 "option-underlying-rank",
385 futu_core::proto_id::QOT_GET_OPTION_UNDERLYING_RANK,
386 qot_get_option_underlying_rank
387);
388qot_proto_json_command!(
389 run_option_rank,
390 "option-rank",
391 futu_core::proto_id::QOT_GET_OPTION_RANK,
392 qot_get_option_rank
393);
394qot_proto_json_command!(
395 run_option_event,
396 "option-event",
397 futu_core::proto_id::QOT_GET_OPTION_EVENT,
398 qot_get_option_event
399);
400qot_proto_json_command!(
401 run_option_event_alert,
402 "option-event-alert",
403 futu_core::proto_id::QOT_GET_OPTION_EVENT_ALERT,
404 qot_get_option_event_alert
405);
406qot_proto_json_command!(
407 run_set_option_event_alert,
408 "set-option-event-alert",
409 futu_core::proto_id::QOT_SET_OPTION_EVENT_ALERT,
410 qot_set_option_event_alert
411);
412qot_proto_json_command!(
413 run_option_zero_dte_screener,
414 "option-zero-dte-screener",
415 futu_core::proto_id::QOT_GET_OPTION_ZERO_DTE_SCREENER,
416 qot_get_option_zero_dte_screener
417);
418qot_proto_json_command!(
419 run_option_zero_dte_contract,
420 "option-zero-dte-contract",
421 futu_core::proto_id::QOT_GET_OPTION_ZERO_DTE_CONTRACT,
422 qot_get_option_zero_dte_contract
423);
424qot_proto_json_command!(
425 run_option_earnings_screener,
426 "option-earnings-screener",
427 futu_core::proto_id::QOT_GET_OPTION_EARNINGS_SCREENER,
428 qot_get_option_earnings_screener
429);
430qot_proto_json_command!(
431 run_option_seller_screener,
432 "option-seller-screener",
433 futu_core::proto_id::QOT_GET_OPTION_SELLER_SCREENER,
434 qot_get_option_seller_screener
435);
436qot_proto_json_command!(
437 run_industrial_chain_list,
438 "industrial-chain-list",
439 futu_core::proto_id::QOT_GET_INDUSTRIAL_CHAIN_LIST,
440 qot_get_industrial_chain_list
441);
442qot_proto_json_command!(
443 run_industrial_chain_detail,
444 "industrial-chain-detail",
445 futu_core::proto_id::QOT_GET_INDUSTRIAL_CHAIN_DETAIL,
446 qot_get_industrial_chain_detail
447);
448qot_proto_json_command!(
449 run_industrial_chain_by_plate,
450 "industrial-chain-by-plate",
451 futu_core::proto_id::QOT_GET_INDUSTRIAL_CHAIN_BY_PLATE,
452 qot_get_industrial_chain_by_plate
453);
454qot_proto_json_command!(
455 run_industrial_plate_info,
456 "industrial-plate-info",
457 futu_core::proto_id::QOT_GET_INDUSTRIAL_PLATE_INFO,
458 qot_get_industrial_plate_info
459);
460qot_proto_json_command!(
461 run_industrial_plate_stock,
462 "industrial-plate-stock",
463 futu_core::proto_id::QOT_GET_INDUSTRIAL_PLATE_STOCK,
464 qot_get_industrial_plate_stock
465);
466qot_proto_json_command!(
467 run_heat_map_data,
468 "heat-map-data",
469 futu_core::proto_id::QOT_GET_HEAT_MAP_DATA,
470 qot_get_heat_map_data
471);
472qot_proto_json_command!(
473 run_rise_fall_distribution,
474 "rise-fall-distribution",
475 futu_core::proto_id::QOT_GET_RISE_FALL_DISTRIBUTION,
476 qot_get_rise_fall_distribution
477);
478
479#[cfg(test)]
480mod tests;