Skip to main content

futucli/cli/dispatch/
qot.rs

1use anyhow::Result;
2
3use super::super::commands::{
4    BrokerArgs, CapitalFlowArgs, CompanyExecutiveBackgroundArgs, CompanyExecutivesArgs,
5    CompanyOperationalEfficiencyArgs, CompanyProfileArgs, CorporateActionsBuybacksArgs,
6    CorporateActionsDividendsArgs, CorporateActionsStockSplitsArgs, DailyShortVolumeArgs,
7    DerivativeUnusualArgs, FinancialUnusualArgs, FinancialsEarningsPriceHistoryArgs,
8    FinancialsEarningsPriceMoveArgs, FinancialsRevenueBreakdownArgs, FinancialsStatementsArgs,
9    InsiderHolderListArgs, InsiderTradeListArgs, KlineArgs, OptionExerciseProbabilityArgs,
10    OptionScreenArgs, OptionVolatilityArgs, OrderbookArgs, PlateListArgs, PlateStocksArgs,
11    ProtoJsonArgs, QuoteArgs, ResearchAnalystConsensusArgs, ResearchMorningstarReportArgs,
12    ResearchRatingSummaryArgs, RtArgs, ShareholdersHolderDetailArgs,
13    ShareholdersHoldingChangesArgs, ShareholdersInstitutionalArgs, ShareholdersOverviewArgs,
14    ShortInterestArgs, SnapshotArgs, StaticArgs, StockScreenArgs, SubArgs, TechnicalUnusualArgs,
15    TickerArgs, TopTenBuySellBrokersArgs, ValuationDetailArgs, ValuationPlateStockListArgs,
16    WarrantScreenArgs,
17};
18use crate::cmd;
19use crate::output::OutputFormat;
20
21pub(super) async fn dispatch_quote(
22    gateway: &str,
23    output: OutputFormat,
24    args: QuoteArgs,
25) -> Result<()> {
26    cmd::quote::run(gateway, &args.symbols, output).await
27}
28
29pub(super) async fn dispatch_snapshot(
30    gateway: &str,
31    output: OutputFormat,
32    args: SnapshotArgs,
33) -> Result<()> {
34    cmd::snapshot::run(gateway, &args.symbols, output).await
35}
36
37pub(super) async fn dispatch_sub(gateway: &str, output: OutputFormat, args: SubArgs) -> Result<()> {
38    cmd::sub::run(gateway, &args.symbols, &args.r#type, output).await
39}
40
41pub(super) async fn dispatch_kline(
42    gateway: &str,
43    output: OutputFormat,
44    args: KlineArgs,
45) -> Result<()> {
46    // v1.4.83 §10: positional 或 --symbol/--code/--stock flag 二选一
47    let symbol = args.symbol_positional.or(args.symbol_arg).ok_or_else(|| {
48        anyhow::anyhow!(
49            "kline: 需要 positional <SYMBOL> 或 --symbol/--code/--stock \
50             (如 `futucli kline US.AAPL` 或 `futucli kline --code US.AAPL`)"
51        )
52    })?;
53    cmd::kline::run_with_format(
54        gateway,
55        &symbol,
56        &args.r#type,
57        args.count,
58        args.begin.as_deref(),
59        args.end.as_deref(),
60        output,
61    )
62    .await
63}
64
65pub(super) async fn dispatch_orderbook(
66    gateway: &str,
67    output: OutputFormat,
68    args: OrderbookArgs,
69) -> Result<()> {
70    let symbol = args.symbol_positional.or(args.symbol_arg).ok_or_else(|| {
71        anyhow::anyhow!("orderbook: 需要 positional <SYMBOL> 或 --symbol/--code/--stock")
72    })?;
73    cmd::orderbook::run(gateway, &symbol, args.depth, args.odd_lot, output).await
74}
75
76pub(super) async fn dispatch_ticker(
77    gateway: &str,
78    output: OutputFormat,
79    args: TickerArgs,
80) -> Result<()> {
81    let symbol = args.symbol_positional.or(args.symbol_arg).ok_or_else(|| {
82        anyhow::anyhow!("ticker: 需要 positional <SYMBOL> 或 --symbol/--code/--stock")
83    })?;
84    cmd::ticker::run(gateway, &symbol, args.count, output).await
85}
86
87pub(super) async fn dispatch_rt(gateway: &str, output: OutputFormat, args: RtArgs) -> Result<()> {
88    let symbol = args.symbol_positional.or(args.symbol_arg).ok_or_else(|| {
89        anyhow::anyhow!("rt: 需要 positional <SYMBOL> 或 --symbol/--code/--stock")
90    })?;
91    cmd::rt::run(gateway, &symbol, output).await
92}
93
94pub(super) async fn dispatch_static(
95    gateway: &str,
96    output: OutputFormat,
97    args: StaticArgs,
98) -> Result<()> {
99    cmd::static_info::run(gateway, &args.symbols, output).await
100}
101
102pub(super) async fn dispatch_broker(
103    gateway: &str,
104    output: OutputFormat,
105    args: BrokerArgs,
106) -> Result<()> {
107    let symbol = args.symbol_positional.or(args.symbol_arg).ok_or_else(|| {
108        anyhow::anyhow!("broker: 需要 positional <SYMBOL> 或 --symbol/--code/--stock")
109    })?;
110    cmd::broker::run(gateway, &symbol, output).await
111}
112
113pub(super) async fn dispatch_plate_list(
114    gateway: &str,
115    output: OutputFormat,
116    args: PlateListArgs,
117) -> Result<()> {
118    cmd::plate::list(gateway, &args.market, &args.set, output).await
119}
120
121pub(super) async fn dispatch_plate_stocks(
122    gateway: &str,
123    output: OutputFormat,
124    args: PlateStocksArgs,
125) -> Result<()> {
126    let plate = args
127        .plate
128        .or(args.plate_arg)
129        .ok_or_else(|| anyhow::anyhow!("plate-stocks: 需要位置参数 <PLATE> 或 --plate"))?;
130    cmd::plate::stocks(gateway, &plate, output).await
131}
132
133pub(super) async fn dispatch_option_quote(
134    gateway: &str,
135    output: OutputFormat,
136    args: ProtoJsonArgs,
137) -> Result<()> {
138    cmd::proto_json::run_option_quote(gateway, &args.c2s_json, output).await
139}
140
141pub(super) async fn dispatch_option_strategy(
142    gateway: &str,
143    output: OutputFormat,
144    args: ProtoJsonArgs,
145) -> Result<()> {
146    cmd::proto_json::run_option_strategy(gateway, &args.c2s_json, output).await
147}
148
149pub(super) async fn dispatch_option_strategy_analysis(
150    gateway: &str,
151    output: OutputFormat,
152    args: ProtoJsonArgs,
153) -> Result<()> {
154    cmd::proto_json::run_option_strategy_analysis(gateway, &args.c2s_json, output).await
155}
156
157pub(super) async fn dispatch_option_strategy_spread(
158    gateway: &str,
159    output: OutputFormat,
160    args: ProtoJsonArgs,
161) -> Result<()> {
162    cmd::proto_json::run_option_strategy_spread(gateway, &args.c2s_json, output).await
163}
164
165pub(super) async fn dispatch_capital_flow(
166    gateway: &str,
167    output: OutputFormat,
168    args: CapitalFlowArgs,
169) -> Result<()> {
170    cmd::analysis::run_capital_flow(
171        gateway,
172        &args.symbol,
173        args.period_type,
174        args.begin.as_deref(),
175        args.end.as_deref(),
176        output,
177    )
178    .await
179}
180
181pub(super) async fn dispatch_company_profile(
182    gateway: &str,
183    output: OutputFormat,
184    args: CompanyProfileArgs,
185) -> Result<()> {
186    cmd::analysis::run_company_profile(gateway, &args.symbol, output).await
187}
188
189pub(super) async fn dispatch_company_executives(
190    gateway: &str,
191    output: OutputFormat,
192    args: CompanyExecutivesArgs,
193) -> Result<()> {
194    cmd::analysis::run_company_executives(gateway, &args.symbol, output).await
195}
196
197pub(super) async fn dispatch_company_executive_background(
198    gateway: &str,
199    output: OutputFormat,
200    args: CompanyExecutiveBackgroundArgs,
201) -> Result<()> {
202    cmd::analysis::run_company_executive_background(
203        gateway,
204        &args.symbol,
205        &args.leader_name,
206        output,
207    )
208    .await
209}
210
211pub(super) async fn dispatch_company_operational_efficiency(
212    gateway: &str,
213    output: OutputFormat,
214    args: CompanyOperationalEfficiencyArgs,
215) -> Result<()> {
216    cmd::analysis::run_company_operational_efficiency(
217        gateway,
218        &args.symbol,
219        args.next_key.as_deref(),
220        args.num,
221        args.currency_code.as_deref(),
222        args.financial_type,
223        output,
224    )
225    .await
226}
227
228pub(super) async fn dispatch_financials_earnings_price_move(
229    gateway: &str,
230    output: OutputFormat,
231    args: FinancialsEarningsPriceMoveArgs,
232) -> Result<()> {
233    cmd::analysis::run_financials_earnings_price_move(
234        gateway,
235        &args.symbol,
236        args.period_count,
237        output,
238    )
239    .await
240}
241
242pub(super) async fn dispatch_financials_earnings_price_history(
243    gateway: &str,
244    output: OutputFormat,
245    args: FinancialsEarningsPriceHistoryArgs,
246) -> Result<()> {
247    cmd::analysis::run_financials_earnings_price_history(gateway, &args.symbol, output).await
248}
249
250pub(super) async fn dispatch_financials_statements(
251    gateway: &str,
252    output: OutputFormat,
253    args: FinancialsStatementsArgs,
254) -> Result<()> {
255    cmd::analysis::run_financials_statements(
256        gateway,
257        &args.symbol,
258        args.statement_type,
259        args.financial_type,
260        args.currency_code.as_deref(),
261        args.next_key.as_deref(),
262        args.num,
263        output,
264    )
265    .await
266}
267
268pub(super) async fn dispatch_financials_revenue_breakdown(
269    gateway: &str,
270    output: OutputFormat,
271    args: FinancialsRevenueBreakdownArgs,
272) -> Result<()> {
273    cmd::analysis::run_financials_revenue_breakdown(
274        gateway,
275        &args.symbol,
276        args.date,
277        args.financial_type,
278        args.currency_code.as_deref(),
279        output,
280    )
281    .await
282}
283
284pub(super) async fn dispatch_research_analyst_consensus(
285    gateway: &str,
286    output: OutputFormat,
287    args: ResearchAnalystConsensusArgs,
288) -> Result<()> {
289    cmd::analysis::run_research_analyst_consensus(gateway, &args.symbol, output).await
290}
291
292pub(super) async fn dispatch_research_rating_summary(
293    gateway: &str,
294    output: OutputFormat,
295    args: ResearchRatingSummaryArgs,
296) -> Result<()> {
297    cmd::analysis::run_research_rating_summary(
298        gateway,
299        &args.symbol,
300        args.rating_dimension_type,
301        args.uid.as_deref(),
302        args.next_key.as_deref(),
303        args.num,
304        output,
305    )
306    .await
307}
308
309pub(super) async fn dispatch_research_morningstar_report(
310    gateway: &str,
311    output: OutputFormat,
312    args: ResearchMorningstarReportArgs,
313) -> Result<()> {
314    cmd::analysis::run_research_morningstar_report(gateway, &args.symbol, output).await
315}
316
317pub(super) async fn dispatch_valuation_detail(
318    gateway: &str,
319    output: OutputFormat,
320    args: ValuationDetailArgs,
321) -> Result<()> {
322    cmd::analysis::run_valuation_detail(
323        gateway,
324        &args.symbol,
325        args.valuation_type,
326        args.interval_type,
327        output,
328    )
329    .await
330}
331
332pub(super) async fn dispatch_valuation_plate_stock_list(
333    gateway: &str,
334    output: OutputFormat,
335    args: ValuationPlateStockListArgs,
336) -> Result<()> {
337    cmd::analysis::run_valuation_plate_stock_list(
338        gateway,
339        &args.symbol,
340        args.valuation_type,
341        args.next_key.as_deref(),
342        args.num,
343        args.sort_type,
344        args.sort_id,
345        args.filter_security.as_deref(),
346        output,
347    )
348    .await
349}
350
351pub(super) async fn dispatch_stock_screen(
352    gateway: &str,
353    output: OutputFormat,
354    args: StockScreenArgs,
355) -> Result<()> {
356    cmd::analysis::run_stock_screen(gateway, &args.c2s_json, output).await
357}
358
359pub(super) async fn dispatch_option_screen(
360    gateway: &str,
361    output: OutputFormat,
362    args: OptionScreenArgs,
363) -> Result<()> {
364    cmd::analysis::run_option_screen(gateway, &args.c2s_json, output).await
365}
366
367pub(super) async fn dispatch_warrant_screen(
368    gateway: &str,
369    output: OutputFormat,
370    args: WarrantScreenArgs,
371) -> Result<()> {
372    cmd::analysis::run_warrant_screen(gateway, &args.c2s_json, output).await
373}
374
375pub(super) async fn dispatch_technical_unusual(
376    gateway: &str,
377    output: OutputFormat,
378    args: TechnicalUnusualArgs,
379) -> Result<()> {
380    cmd::analysis::run_technical_unusual(
381        gateway,
382        &args.stock_symbol,
383        args.time_range,
384        args.indicator_filters,
385        args.language_id,
386        output,
387    )
388    .await
389}
390
391pub(super) async fn dispatch_financial_unusual(
392    gateway: &str,
393    output: OutputFormat,
394    args: FinancialUnusualArgs,
395) -> Result<()> {
396    cmd::analysis::run_financial_unusual(
397        gateway,
398        &args.stock_symbol,
399        args.time_range,
400        args.analysis_dimensions,
401        args.language_id,
402        output,
403    )
404    .await
405}
406
407pub(super) async fn dispatch_derivative_unusual(
408    gateway: &str,
409    output: OutputFormat,
410    args: DerivativeUnusualArgs,
411) -> Result<()> {
412    cmd::analysis::run_derivative_unusual(
413        gateway,
414        &args.stock_symbol,
415        args.time_range,
416        args.analysis_dimensions,
417        args.language_id,
418        output,
419    )
420    .await
421}
422
423pub(super) async fn dispatch_corporate_actions_buybacks(
424    gateway: &str,
425    output: OutputFormat,
426    args: CorporateActionsBuybacksArgs,
427) -> Result<()> {
428    cmd::analysis::run_corporate_actions_buybacks(
429        gateway,
430        &args.symbol,
431        args.next_key.as_deref(),
432        args.num,
433        output,
434    )
435    .await
436}
437
438pub(super) async fn dispatch_corporate_actions_dividends(
439    gateway: &str,
440    output: OutputFormat,
441    args: CorporateActionsDividendsArgs,
442) -> Result<()> {
443    cmd::analysis::run_corporate_actions_dividends(gateway, &args.symbol, output).await
444}
445
446pub(super) async fn dispatch_corporate_actions_stock_splits(
447    gateway: &str,
448    output: OutputFormat,
449    args: CorporateActionsStockSplitsArgs,
450) -> Result<()> {
451    cmd::analysis::run_corporate_actions_stock_splits(
452        gateway,
453        &args.symbol,
454        args.next_key.as_deref(),
455        args.num,
456        output,
457    )
458    .await
459}
460
461pub(super) async fn dispatch_daily_short_volume(
462    gateway: &str,
463    output: OutputFormat,
464    args: DailyShortVolumeArgs,
465) -> Result<()> {
466    cmd::analysis::run_daily_short_volume(
467        gateway,
468        &args.symbol,
469        args.next_key.as_deref(),
470        args.num,
471        output,
472    )
473    .await
474}
475
476pub(super) async fn dispatch_short_interest(
477    gateway: &str,
478    output: OutputFormat,
479    args: ShortInterestArgs,
480) -> Result<()> {
481    cmd::analysis::run_short_interest(
482        gateway,
483        &args.symbol,
484        args.next_key.as_deref(),
485        args.num,
486        output,
487    )
488    .await
489}
490
491pub(super) async fn dispatch_top_ten_buy_sell_brokers(
492    gateway: &str,
493    output: OutputFormat,
494    args: TopTenBuySellBrokersArgs,
495) -> Result<()> {
496    cmd::analysis::run_top_ten_buy_sell_brokers(gateway, &args.symbol, args.days_before, output)
497        .await
498}
499
500pub(super) async fn dispatch_shareholders_overview(
501    gateway: &str,
502    output: OutputFormat,
503    args: ShareholdersOverviewArgs,
504) -> Result<()> {
505    cmd::analysis::run_shareholders_overview(gateway, &args.symbol, args.period_id, output).await
506}
507
508pub(super) async fn dispatch_shareholders_holding_changes(
509    gateway: &str,
510    output: OutputFormat,
511    args: ShareholdersHoldingChangesArgs,
512) -> Result<()> {
513    cmd::analysis::run_shareholders_holding_changes(
514        cmd::analysis::ShareholdersHoldingChangesCommand {
515            gateway,
516            symbol: &args.symbol,
517            next_key: args.next_key,
518            num: args.num,
519            sort_type: args.sort_type,
520            sort_column: args.sort_column,
521            filter_type: args.filter_type,
522            format: output,
523        },
524    )
525    .await
526}
527
528pub(super) async fn dispatch_shareholders_holder_detail(
529    gateway: &str,
530    output: OutputFormat,
531    args: ShareholdersHolderDetailArgs,
532) -> Result<()> {
533    cmd::analysis::run_shareholders_holder_detail(cmd::analysis::ShareholdersHolderDetailCommand {
534        gateway,
535        symbol: &args.symbol,
536        request_type: args.request_type,
537        next_key: args.next_key,
538        num: args.num,
539        sort_column: args.sort_column,
540        sort_type: args.sort_type,
541        period_id: args.period_id,
542        holder_id: args.holder_id,
543        format: output,
544    })
545    .await
546}
547
548pub(super) async fn dispatch_shareholders_institutional(
549    gateway: &str,
550    output: OutputFormat,
551    args: ShareholdersInstitutionalArgs,
552) -> Result<()> {
553    cmd::analysis::run_shareholders_institutional(
554        gateway,
555        &args.symbol,
556        args.next_key,
557        args.num,
558        output,
559    )
560    .await
561}
562
563pub(super) async fn dispatch_insider_holder_list(
564    gateway: &str,
565    output: OutputFormat,
566    args: InsiderHolderListArgs,
567) -> Result<()> {
568    cmd::analysis::run_insider_holder_list(gateway, &args.symbol, args.next_key, args.num, output)
569        .await
570}
571
572pub(super) async fn dispatch_insider_trade_list(
573    gateway: &str,
574    output: OutputFormat,
575    args: InsiderTradeListArgs,
576) -> Result<()> {
577    cmd::analysis::run_insider_trade_list(
578        gateway,
579        &args.symbol,
580        args.holder_id,
581        args.next_key,
582        args.num,
583        output,
584    )
585    .await
586}
587
588pub(super) async fn dispatch_option_volatility(
589    gateway: &str,
590    output: OutputFormat,
591    args: OptionVolatilityArgs,
592) -> Result<()> {
593    cmd::analysis::run_option_volatility(
594        gateway,
595        &args.symbol,
596        args.query_time_period,
597        args.hv_time_period,
598        output,
599    )
600    .await
601}
602
603pub(super) async fn dispatch_option_exercise_probability(
604    gateway: &str,
605    output: OutputFormat,
606    args: OptionExerciseProbabilityArgs,
607) -> Result<()> {
608    cmd::analysis::run_option_exercise_probability(gateway, &args.symbol, output).await
609}