Skip to main content

futu_mcp/tool_enums/
trd_market_enum.rs

1//! Split from tool_enums.rs: TrdMarketEnum.
2
3use serde::Serialize;
4
5use futu_proto::trd_common::TrdMarket as ProtoTrdMarket;
6
7use super::ToolEnum;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, schemars::JsonSchema)]
10#[serde(into = "i32")]
11#[non_exhaustive]
12#[allow(clippy::upper_case_acronyms)] // HKCC = "HK Connect to CN", proto wire 必用此名
13pub enum TrdMarketEnum {
14    HK,
15    US,
16    CN,
17    HKCC,
18    Futures,
19    SG,
20    AU,
21    JP,
22    MY,
23    CA,
24    /// v1.4.102 fund-market handoff (per pitfall #54): view-only HKFUND/USFUND
25    /// 融资融券 / 基金账户. C++ `NN_TrdMarket_HK_Fund=113`,
26    /// `NN_TrdMarket_US_Fund=123`. cash-log backend `Market` enum 用 13/23,
27    /// 翻译见 `cash_log_market_for_trd_market` in cash_log.rs.
28    HKFund,
29    USFund,
30}
31
32impl From<TrdMarketEnum> for i32 {
33    fn from(t: TrdMarketEnum) -> Self {
34        t.as_i32()
35    }
36}
37
38impl TrdMarketEnum {
39    /// v1.4.93 C3 (Option D): map a prost-generated `ProtoTrdMarket` to our
40    /// exposed subset.
41    ///
42    /// proto variants we **don't** expose (return `None`):
43    /// - `Unknown` (=0) — invalid placeholder
44    /// - `FuturesSimulateHk/Us/Sg/Jp` (=10..=13) — separate sim plumbing
45    /// - `SgFund` / `MyFund` / `JpFund` / `CaFund` — not verified in Rust surface yet
46    fn from_proto_variant(p: ProtoTrdMarket) -> Option<Self> {
47        Some(match p {
48            ProtoTrdMarket::Hk => Self::HK,
49            ProtoTrdMarket::Us => Self::US,
50            ProtoTrdMarket::Cn => Self::CN,
51            ProtoTrdMarket::Hkcc => Self::HKCC,
52            ProtoTrdMarket::Futures => Self::Futures,
53            ProtoTrdMarket::Sg => Self::SG,
54            ProtoTrdMarket::Au => Self::AU,
55            ProtoTrdMarket::Jp => Self::JP,
56            ProtoTrdMarket::My => Self::MY,
57            ProtoTrdMarket::Ca => Self::CA,
58            // v1.4.102 fund-market: HKFUND=113 / USFUND=123 (view-only acc).
59            ProtoTrdMarket::HkFund => Self::HKFund,
60            ProtoTrdMarket::UsFund => Self::USFund,
61            // Unknown / Futures_Simulate_* / SgFund/MyFund/JpFund/CaFund — not exposed.
62            _ => return None,
63        })
64    }
65}
66
67impl ToolEnum for TrdMarketEnum {
68    fn type_name() -> &'static str {
69        "trd_market"
70    }
71
72    fn from_i32(v: i32) -> Option<Self> {
73        Some(match v {
74            1 => Self::HK,
75            2 => Self::US,
76            3 => Self::CN,
77            4 => Self::HKCC,
78            5 => Self::Futures,
79            6 => Self::SG,
80            8 => Self::AU,
81            15 => Self::JP,
82            111 => Self::MY,
83            112 => Self::CA,
84            // v1.4.102 fund-market handoff
85            113 => Self::HKFund,
86            123 => Self::USFund,
87            _ => return None,
88        })
89    }
90
91    /// v1.4.93 C3 (Option D): delegate canonical-name lookup to prost-generated
92    /// `ProtoTrdMarket::from_str_name`, then map exposed variants to our local
93    /// enum. Hand-written short names (`"HK"` / `"FUTURES"` / ...) keep working
94    /// as a friendly-alias fallback so LLM agents can use either form.
95    ///
96    /// This consolidates the two enum-name lists (proto canonical + tool short)
97    /// down to one source of truth (proto). Adding a new proto variant only
98    /// requires extending [`Self::from_proto_variant`] one arm. Unrecognised
99    /// proto variants are intentionally rejected until the corresponding runtime
100    /// route has evidence; HK_Fund / US_Fund are the currently exposed fund variants.
101    fn from_str(s: &str) -> Option<Self> {
102        let trimmed = s.trim();
103        let upper = trimmed.to_ascii_uppercase();
104
105        // Step 1: prost canonical names (case-sensitive: `"TrdMarket_HK"`,
106        // `"TrdMarket_Futures"`, ...). Use the trimmed-but-not-uppercased input
107        // because prost's match table is case-sensitive on its exact names.
108        // Let-chain (Rust 2024) collapses two `if let` — both must succeed.
109        // If prost matches but the variant is unexposed (e.g.
110        // `Futures_Simulate_HK` / `SG_Fund`), we fall through to the short-name
111        // attempt; in practice short-name match below will also miss, so we'll
112        // return None like before.
113        if let Some(proto) = ProtoTrdMarket::from_str_name(trimmed)
114            && let Some(local) = Self::from_proto_variant(proto)
115        {
116            return Some(local);
117        }
118
119        // Step 2: short-name aliases (uppercased for case-insensitive UX).
120        Some(match upper.as_str() {
121            "HK" => Self::HK,
122            "US" => Self::US,
123            "CN" => Self::CN,
124            "HKCC" => Self::HKCC,
125            "FUTURES" => Self::Futures,
126            "SG" => Self::SG,
127            "AU" => Self::AU,
128            "JP" => Self::JP,
129            "MY" => Self::MY,
130            "CA" => Self::CA,
131            // v1.4.102 fund-market
132            "HKFUND" | "HK_FUND" => Self::HKFund,
133            "USFUND" | "US_FUND" => Self::USFund,
134            _ => return None,
135        })
136    }
137
138    fn as_i32(self) -> i32 {
139        match self {
140            Self::HK => 1,
141            Self::US => 2,
142            Self::CN => 3,
143            Self::HKCC => 4,
144            Self::Futures => 5,
145            Self::SG => 6,
146            Self::AU => 8,
147            Self::JP => 15,
148            Self::MY => 111,
149            Self::CA => 112,
150            Self::HKFund => 113,
151            Self::USFund => 123,
152        }
153    }
154
155    fn all_int_values() -> Vec<i32> {
156        // v1.4.102 fund-market handoff: 113/123 (HKFUND/USFUND).
157        vec![1, 2, 3, 4, 5, 6, 8, 15, 111, 112, 113, 123]
158    }
159
160    fn all_string_values() -> Vec<&'static str> {
161        vec![
162            "HK", "US", "CN", "HKCC", "FUTURES", "SG", "AU", "JP", "MY", "CA", "HKFUND", "USFUND",
163        ]
164    }
165}