Skip to main content

futu_mcp/handlers/reference/
option_analysis.rs

1use std::sync::Arc;
2
3use anyhow::{Result, anyhow, bail};
4use futu_net::client::FutuClient;
5use prost::Message;
6use serde::Serialize;
7
8use crate::state::parse_symbol;
9
10#[derive(Serialize)]
11struct OptionVolatilityOut {
12    symbol: String,
13    s2c: futu_proto::qot_get_option_volatility::S2c,
14}
15
16#[derive(Serialize)]
17struct OptionExerciseProbabilityOut {
18    symbol: String,
19    s2c: futu_proto::qot_get_option_exercise_probability::S2c,
20}
21
22pub async fn get_option_volatility(
23    client: &Arc<FutuClient>,
24    symbol: &str,
25    query_time_period: Option<i32>,
26    hv_time_period: Option<i32>,
27) -> Result<String> {
28    let sec = parse_symbol(symbol)?;
29    let req = futu_proto::qot_get_option_volatility::Request {
30        c2s: futu_proto::qot_get_option_volatility::C2s {
31            security: futu_proto::qot_common::Security {
32                market: sec.market as i32,
33                code: sec.code.clone(),
34            },
35            query_time_period,
36            hv_time_period,
37        },
38    };
39    let frame = client
40        .request(
41            futu_core::proto_id::QOT_GET_OPTION_VOLATILITY,
42            req.encode_to_vec(),
43        )
44        .await?;
45    let resp = futu_proto::qot_get_option_volatility::Response::decode(frame.body.as_ref())
46        .map_err(|e| anyhow!("decode option_volatility: {e}"))?;
47    if resp.ret_type != 0 {
48        bail!(
49            "option_volatility ret_type={} msg={:?}",
50            resp.ret_type,
51            resp.ret_msg
52        );
53    }
54    let s2c = resp.s2c.ok_or_else(|| anyhow!("missing s2c"))?;
55    Ok(serde_json::to_string_pretty(&OptionVolatilityOut {
56        symbol: symbol.to_string(),
57        s2c,
58    })?)
59}
60
61pub async fn get_option_exercise_probability(
62    client: &Arc<FutuClient>,
63    symbol: &str,
64) -> Result<String> {
65    let sec = parse_symbol(symbol)?;
66    let req = futu_proto::qot_get_option_exercise_probability::Request {
67        c2s: futu_proto::qot_get_option_exercise_probability::C2s {
68            security: futu_proto::qot_common::Security {
69                market: sec.market as i32,
70                code: sec.code.clone(),
71            },
72        },
73    };
74    let frame = client
75        .request(
76            futu_core::proto_id::QOT_GET_OPTION_EXERCISE_PROBABILITY,
77            req.encode_to_vec(),
78        )
79        .await?;
80    let resp =
81        futu_proto::qot_get_option_exercise_probability::Response::decode(frame.body.as_ref())
82            .map_err(|e| anyhow!("decode option_exercise_probability: {e}"))?;
83    if resp.ret_type != 0 {
84        bail!(
85            "option_exercise_probability ret_type={} msg={:?}",
86            resp.ret_type,
87            resp.ret_msg
88        );
89    }
90    let s2c = resp.s2c.ok_or_else(|| anyhow!("missing s2c"))?;
91    Ok(serde_json::to_string_pretty(
92        &OptionExerciseProbabilityOut {
93            symbol: symbol.to_string(),
94            s2c,
95        },
96    )?)
97}