Skip to main content

futu_mcp/handlers/reference/
code_change.rs

1//! mcp/handlers/reference/code_change — get_code_change
2//! (v1.4.110 CC Batch L: 拆自 reference.rs L796-853)
3
4use std::sync::Arc;
5
6use anyhow::{Result, anyhow, bail};
7use futu_net::client::FutuClient;
8use prost::Message;
9use serde::Serialize;
10
11use crate::state::parse_symbol;
12
13// ============================================================
14// get_code_change / Qot_GetCodeChange (CMD 3216)
15// ============================================================
16
17#[derive(Serialize)]
18struct CodeChangeOut {
19    change_type: i32,
20    main_code: String,
21    related_code: String,
22    public_time: Option<String>,
23    effective_time: Option<String>,
24}
25
26/// 股票代码变更信息(目前仅港股)。
27pub async fn get_code_change(client: &Arc<FutuClient>, symbols: &[String]) -> Result<String> {
28    let sec_list: Vec<_> = symbols
29        .iter()
30        .map(|s| parse_symbol(s))
31        .collect::<Result<Vec<_>>>()?;
32    let proto_secs: Vec<_> = sec_list
33        .iter()
34        .map(|s| futu_proto::qot_common::Security {
35            market: s.market as i32,
36            code: s.code.clone(),
37        })
38        .collect();
39    let req = futu_proto::qot_get_code_change::Request {
40        c2s: futu_proto::qot_get_code_change::C2s {
41            place_holder: None,
42            security_list: proto_secs,
43            time_filter_list: vec![],
44            type_list: vec![],
45            header: None,
46        },
47    };
48    let body = req.encode_to_vec();
49    let frame = client
50        .request(futu_core::proto_id::QOT_GET_CODE_CHANGE, body)
51        .await?;
52    let resp = futu_proto::qot_get_code_change::Response::decode(frame.body.as_ref())
53        .map_err(|e| anyhow!("decode code_change: {e}"))?;
54    if resp.ret_type != 0 {
55        bail!(
56            "code_change ret_type={} msg={:?}",
57            resp.ret_type,
58            resp.ret_msg
59        );
60    }
61    let s2c = resp.s2c.ok_or_else(|| anyhow!("missing s2c"))?;
62    let out: Vec<CodeChangeOut> = s2c
63        .code_change_list
64        .iter()
65        .map(|c| CodeChangeOut {
66            change_type: c.r#type,
67            main_code: c.security.code.clone(),
68            related_code: c.related_security.code.clone(),
69            public_time: c.public_time.clone(),
70            effective_time: c.effective_time.clone(),
71        })
72        .collect();
73    Ok(serde_json::to_string_pretty(&out)?)
74}