futu_mcp/handlers/reference/
option_analysis.rs1use 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}