1use super::*;
4
5#[derive(Debug, Deserialize, schemars::JsonSchema)]
6#[serde(deny_unknown_fields)]
7pub struct HistoryKLineReq {
8 #[schemars(description = "Security symbol (MARKET.CODE); alias: code / stock")]
9 #[serde(alias = "code", alias = "stock")]
11 pub symbol: String,
12 #[schemars(
13 description = "K-line type: day|week|month|quarter|year|1min|3min|5min|15min|30min|60min \
14 (default day); alias: ktype / k_type"
15 )]
16 #[serde(default = "default_kl_type", alias = "ktype", alias = "k_type")]
17 pub kl_type: String,
18 #[schemars(description = "Rehab type: none|forward|backward (default none)")]
19 #[serde(default = "default_rehab_none")]
20 pub rehab_type: String,
21 #[schemars(description = "Start date yyyy-MM-dd; alias: begin_time / start_time / from")]
22 #[serde(alias = "begin_time", alias = "start_time", alias = "from")]
23 pub begin: String,
24 #[schemars(description = "End date yyyy-MM-dd; alias: end_time / to")]
25 #[serde(alias = "end_time", alias = "to")]
26 pub end: String,
27 #[schemars(
28 description = "Max number of candles to return (default 1000, range 1-1000). \
29 If omitted, the gateway uses 1000; pass explicit 0 to request no limit \
30 only when you can handle a large response. alias: num / count / req_count"
31 )]
32 #[serde(
36 default = "default_history_kline_max_count",
37 alias = "num",
38 alias = "count",
39 alias = "req_count"
40 )]
41 pub max_count: Option<i32>,
42}
43
44impl HistoryKLineReq {
45 pub fn validated_max_count(&self) -> Result<Option<i32>, String> {
46 futu_qot::page_bounds::validate_optional_max_count(self.max_count, 1000, "history_kline")
47 .map_err(|e| e.to_string())
48 }
49}
50
51#[derive(Debug, Deserialize, schemars::JsonSchema)]
52#[serde(deny_unknown_fields)]
53pub struct ReferenceReq {
54 #[schemars(description = "Underlying symbol (e.g. HK.00700, US.AAPL); alias: code / stock")]
55 #[serde(alias = "code", alias = "stock")]
57 pub symbol: String,
58 #[schemars(
63 description = "Reference type: warrant|future (default warrant). Note: option is NOT supported — use futu_get_option_chain instead."
64 )]
65 #[serde(default = "default_reference_type")]
66 pub reference_type: String,
67}
68
69#[derive(Debug, Deserialize, schemars::JsonSchema)]
70#[serde(deny_unknown_fields)]
71pub struct OptionChainReq {
72 #[schemars(
73 description = "Underlying stock symbol (e.g. HK.00700, US.AAPL); alias: symbol / owner / code / stock"
74 )]
75 #[serde(alias = "symbol", alias = "owner", alias = "code", alias = "stock")]
77 pub owner_symbol: String,
78 #[schemars(
79 description = "Expiry range begin date yyyy-MM-dd; alias: begin / start_time / from"
80 )]
81 #[serde(alias = "begin", alias = "start_time", alias = "from")]
82 pub begin_time: String,
83 #[schemars(description = "Expiry range end date yyyy-MM-dd; alias: end / to")]
84 #[serde(alias = "end", alias = "to")]
85 pub end_time: String,
86 #[schemars(description = "Option type: all|call|put (default all)")]
87 pub option_type: Option<String>,
88
89 #[schemars(
92 description = "Optional Greek filter: only return options with delta in [min, max]; min must be <= max when both are provided. Typical ATM range: 0.3 to 0.7 for calls, -0.7 to -0.3 for puts."
93 )]
94 pub delta_min: Option<f64>,
95 #[schemars(description = "See delta_min; must be >= delta_min when both are provided.")]
96 pub delta_max: Option<f64>,
97 #[schemars(
98 description = "Implied volatility filter min (decimal, e.g. 0.3 = 30%); must be <= iv_max when both are provided."
99 )]
100 pub iv_min: Option<f64>,
101 #[schemars(description = "See iv_min; must be >= iv_min when both are provided.")]
102 pub iv_max: Option<f64>,
103 #[schemars(
104 description = "Open interest (contracts) filter min, integer; must be <= oi_max when both are provided."
105 )]
106 pub oi_min: Option<f64>,
107 #[schemars(description = "See oi_min; must be >= oi_min when both are provided.")]
108 pub oi_max: Option<f64>,
109 #[schemars(
110 description = "Gamma filter min (decimal); must be <= gamma_max when both are provided."
111 )]
112 pub gamma_min: Option<f64>,
113 #[schemars(description = "See gamma_min; must be >= gamma_min when both are provided.")]
114 pub gamma_max: Option<f64>,
115 #[schemars(
116 description = "Vega filter min (decimal); must be <= vega_max when both are provided."
117 )]
118 pub vega_min: Option<f64>,
119 #[schemars(description = "See vega_min; must be >= vega_min when both are provided.")]
120 pub vega_max: Option<f64>,
121 #[schemars(
122 description = "Theta filter min (decimal); must be <= theta_max when both are provided."
123 )]
124 pub theta_min: Option<f64>,
125 #[schemars(description = "See theta_min; must be >= theta_min when both are provided.")]
126 pub theta_max: Option<f64>,
127}
128
129impl OptionChainReq {
130 pub fn validate(&self) -> Result<(), String> {
131 let tool = "futu_get_option_chain";
132 validate_optional_f64_min_max(tool, "iv", self.iv_min, self.iv_max)?;
133 validate_optional_f64_min_max(tool, "delta", self.delta_min, self.delta_max)?;
134 validate_optional_f64_min_max(tool, "gamma", self.gamma_min, self.gamma_max)?;
135 validate_optional_f64_min_max(tool, "vega", self.vega_min, self.vega_max)?;
136 validate_optional_f64_min_max(tool, "theta", self.theta_min, self.theta_max)?;
137 validate_optional_f64_min_max(tool, "oi", self.oi_min, self.oi_max)?;
138 Ok(())
139 }
140}
141
142#[derive(Debug, Deserialize, schemars::JsonSchema)]
143#[serde(deny_unknown_fields)]
144pub struct WarrantReq {
145 #[schemars(
146 description = "Underlying stock symbol (e.g. HK.00700); None = whole-market warrants. Alias: symbol / owner / code"
147 )]
148 #[serde(default, alias = "symbol", alias = "owner", alias = "code")]
150 pub owner_symbol: Option<String>,
151 #[schemars(description = "Pagination begin index (default 0); alias: offset / skip")]
155 #[serde(default, alias = "offset", alias = "skip")]
156 pub begin: i32,
157 #[schemars(description = "Max rows (0-200, default 20); alias: count / max_count / req_count")]
158 #[serde(
159 default = "default_warrant_num",
160 alias = "count",
161 alias = "max_count",
162 alias = "req_count"
163 )]
164 pub num: i32,
165}
166
167impl WarrantReq {
168 pub fn validate(&self) -> Result<(), String> {
169 futu_qot::page_bounds::validate_begin_num(self.begin, self.num, 200, "warrant")
170 .map(|_| ())
171 .map_err(|err| err.to_string())
172 }
173}
174
175#[derive(Debug, Deserialize, schemars::JsonSchema)]
176#[serde(deny_unknown_fields)]
177pub struct IpoListReq {
178 #[schemars(
179 description = "Market code accepted by the IPO list backend. Accept int (1=HK, 2=HK_FUTURE, 11=US, 21=SH/CN, 22=SZ, 31=SG, 41=JP, 61=MY) \
180 OR string (\"HK\" / \"HK_FUTURE\" / \"US\" / \"SH\" / \"SZ\" / \"CN\" / \"SG\" / \"JP\" / \"MY\")."
181 )]
182 #[serde(deserialize_with = "deser_hk_hkfuture_us_cn_market_as_i32")]
184 pub market: i32,
185}
186
187impl IpoListReq {
188 pub fn validate(&self) -> Result<(), String> {
189 if matches!(self.market, 1 | 2 | 11 | 21 | 22 | 31 | 41 | 61) {
190 return Ok(());
191 }
192 Err(format!(
193 "futu_get_ipo_list market must be 1, 2, 11, 21, 22, 31, 41, or 61 (HK/HK_Future/US/SH/SZ/SG/JP/MY), got {}",
194 self.market
195 ))
196 }
197}
198
199#[derive(Debug, Deserialize, schemars::JsonSchema)]
200#[serde(deny_unknown_fields)]
201pub struct FutureInfoReq {
202 #[schemars(
203 description = "Array of future contract symbols in MARKET.CODE format \
204 (e.g. [\"HK.HSImain\", \"US.MNQmain\"]). Alias: stocks / \
205 code_list / symbol_list / security_list"
206 )]
207 #[serde(
209 alias = "stocks",
210 alias = "code_list",
211 alias = "symbol_list",
212 alias = "security_list"
213 )]
214 pub symbols: Vec<String>,
215}