Skip to main content

futu_mcp/handlers/trade/
helpers.rs

1//! mcp/handlers/trade/helpers — parse_* + build_header_* (跨 trade sub-mod 共用)
2//! (v1.4.110 CC Batch O: 拆自 trade.rs L26-110)
3
4use anyhow::{Result, bail};
5use futu_trd::types::{TrdEnv, TrdHeader, TrdMarket};
6
7pub fn parse_trd_market(s: &str) -> Result<TrdMarket> {
8    futu_trd::market::parse_trd_market(s).ok_or_else(|| {
9        anyhow::anyhow!(
10            "unknown trd market {:?} ({})",
11            s.trim().to_ascii_uppercase(),
12            futu_trd::market::TRD_MARKET_PARSE_CHOICES
13        )
14    })
15}
16
17pub fn parse_trd_env(s: &str) -> Result<TrdEnv> {
18    futu_trd::parsing::parse_trd_env(s).ok_or_else(|| {
19        anyhow::anyhow!(
20            "unknown trd env {:?} ({})",
21            s.trim().to_ascii_lowercase(),
22            futu_trd::parsing::TRD_ENV_PARSE_CHOICES
23        )
24    })
25}
26
27/// v1.4.102 codex 38 F4 / 41 F2 / 41 F3 / 42 F3 (P2): 严格 env → i32
28/// 共享 helper, 替换 cash_flow / margin_info / account_flag / bond 4 处
29/// 旧"non-real => 0 silent"模式. typo (e.g. "reel" / "prod") 现在 reject
30/// at MCP boundary (BUG-005 反 silent wrong-env).
31pub fn parse_trd_env_int(s: &str) -> Result<i32> {
32    Ok(parse_trd_env(s)? as i32)
33}
34
35/// v1.4.102 codex 33 F5 / 34 F4 / 35 F4 (P2): 拒 fund market 在 calculation /
36/// active trade-read path. 用于 max_trd_qtys / margin_ratio / order_fee /
37/// orders / deals 等 active backend call (区别于 view-only positions/funds/
38/// cash-log/history 真机 verified).
39pub fn parse_trd_market_strict_no_fund(s: &str) -> Result<TrdMarket> {
40    let m = parse_trd_market(s)?;
41    if let Some(label) = futu_trd::market::canonical_fund_trd_market_label(m) {
42        bail!(
43            "trd market {label} 仅 view-only read endpoints \
44             (positions/funds/cash-log/history-orders/history-fills) 真机 verified; \
45             active/calculation path (orders/deals/max_trd_qtys/margin_ratio/order_fee) \
46             用主市场. v1.4.102 audit 33 F5 / 34 F4 / 35 F4 fix."
47        );
48    }
49    Ok(m)
50}
51
52/// v1.4.102 codex 35 F4: build_header for active/calculation MCP tools.
53/// view-only read tools (positions/funds/cash-log/history) 用普通 build_header
54/// 接受 fund market.
55pub fn build_header_strict_no_fund(env: &str, acc_id: u64, market: &str) -> Result<TrdHeader> {
56    build_header_strict_no_fund_with_jp_acc_type(env, acc_id, market, None)
57}
58
59pub fn build_header_strict_no_fund_with_jp_acc_type(
60    env: &str,
61    acc_id: u64,
62    market: &str,
63    jp_acc_type: Option<i32>,
64) -> Result<TrdHeader> {
65    Ok(TrdHeader {
66        trd_env: parse_trd_env(env)?,
67        acc_id,
68        trd_market: parse_trd_market_strict_no_fund(market)?,
69        jp_acc_type,
70    })
71}
72
73pub fn build_header(env: &str, acc_id: u64, market: &str) -> Result<TrdHeader> {
74    Ok(TrdHeader {
75        trd_env: parse_trd_env(env)?,
76        acc_id,
77        trd_market: parse_trd_market(market)?,
78        jp_acc_type: None,
79    })
80}