futu_mcp/handlers/
plate.rs

1//! 板块 handler
2
3use std::sync::Arc;
4
5use anyhow::{bail, Result};
6use futu_net::client::FutuClient;
7use futu_qot::types::QotMarket;
8use serde::Serialize;
9
10use crate::state::{format_symbol, parse_symbol};
11
12fn parse_market(s: &str) -> Result<QotMarket> {
13    let m = match s.trim().to_ascii_uppercase().as_str() {
14        "HK" => QotMarket::HkSecurity,
15        "HK_FUTURE" => QotMarket::HkFuture,
16        "US" => QotMarket::UsSecurity,
17        "SH" => QotMarket::CnshSecurity,
18        "SZ" => QotMarket::CnszSecurity,
19        other => bail!("unknown market {other:?} (HK|HK_FUTURE|US|SH|SZ)"),
20    };
21    Ok(m)
22}
23
24fn parse_plate_set(s: &str) -> Result<i32> {
25    let v = match s.trim().to_ascii_lowercase().as_str() {
26        "all" => 0,
27        "industry" => 1,
28        "region" => 2,
29        "concept" => 3,
30        other => bail!("unknown plate-set {other:?} (all|industry|region|concept)"),
31    };
32    Ok(v)
33}
34
35#[derive(Serialize)]
36struct PlateOut {
37    plate: String,
38    name: String,
39    plate_type: Option<i32>,
40}
41
42pub async fn list_plates(
43    client: &Arc<FutuClient>,
44    market: &str,
45    plate_set: &str,
46) -> Result<String> {
47    let m = parse_market(market)?;
48    let set = parse_plate_set(plate_set)?;
49    let plates = futu_qot::market_misc::get_plate_set(client, m, set).await?;
50    let out: Vec<PlateOut> = plates
51        .iter()
52        .map(|p| PlateOut {
53            plate: format_symbol(&p.security),
54            name: p.name.clone(),
55            plate_type: p.plate_type,
56        })
57        .collect();
58    Ok(serde_json::to_string_pretty(&out)?)
59}
60
61#[derive(Serialize)]
62struct StockOut {
63    symbol: String,
64    id: i64,
65    name: String,
66    sec_type: i32,
67    lot_size: i32,
68    list_time: String,
69    delisting: bool,
70}
71
72pub async fn plate_stocks(client: &Arc<FutuClient>, plate_symbol: &str) -> Result<String> {
73    let plate = parse_symbol(plate_symbol)?;
74    let list = futu_qot::market_misc::get_plate_security(client, &plate).await?;
75    let out: Vec<StockOut> = list
76        .iter()
77        .map(|i| StockOut {
78            symbol: format_symbol(&i.security),
79            id: i.id,
80            name: i.name.clone(),
81            sec_type: i.sec_type,
82            lot_size: i.lot_size,
83            list_time: i.list_time.clone(),
84            delisting: i.delisting,
85        })
86        .collect();
87    Ok(serde_json::to_string_pretty(&out)?)
88}