1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
4#[serde(rename_all = "snake_case")]
5pub enum MaParamKind {
6 Float,
7 Int,
8}
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct MaParamInfo {
12 pub key: &'static str,
13 pub label: &'static str,
14 pub kind: MaParamKind,
15 pub default: f64,
16 pub min: Option<f64>,
17 pub max: Option<f64>,
18 pub step: Option<f64>,
19 pub notes: Option<&'static str>,
20}
21
22pub fn ma_param_schema(ma_type: &str) -> &'static [MaParamInfo] {
23 match ma_type.trim().to_ascii_lowercase().as_str() {
24 "alma" => &[
25 MaParamInfo {
26 key: "offset",
27 label: "Offset",
28 kind: MaParamKind::Float,
29 default: 0.85,
30 min: Some(0.0),
31 max: Some(1.0),
32 step: Some(0.01),
33 notes: None,
34 },
35 MaParamInfo {
36 key: "sigma",
37 label: "Sigma",
38 kind: MaParamKind::Float,
39 default: 6.0,
40 min: Some(0.1),
41 max: Some(64.0),
42 step: Some(0.1),
43 notes: None,
44 },
45 ],
46 "corrected_moving_average" | "cma" => &[],
47 "n_order_ema" => &[MaParamInfo {
48 key: "order",
49 label: "Order",
50 kind: MaParamKind::Int,
51 default: 1.0,
52 min: Some(1.0),
53 max: Some(64.0),
54 step: Some(1.0),
55 notes: Some("Additional enum params: ema_style and iir_style."),
56 }],
57 "epma" => &[MaParamInfo {
58 key: "offset",
59 label: "Offset",
60 kind: MaParamKind::Int,
61 default: 4.0,
62 min: Some(0.0),
63 max: Some(512.0),
64 step: Some(1.0),
65 notes: Some("Must be < period."),
66 }],
67 "sgf" => &[MaParamInfo {
68 key: "poly_order",
69 label: "Poly Order",
70 kind: MaParamKind::Int,
71 default: 2.0,
72 min: Some(0.0),
73 max: Some(16.0),
74 step: Some(1.0),
75 notes: Some("Must be an integer >= 0 and < effective period."),
76 }],
77 "gaussian" => &[MaParamInfo {
78 key: "poles",
79 label: "Poles",
80 kind: MaParamKind::Int,
81 default: 4.0,
82 min: Some(1.0),
83 max: Some(4.0),
84 step: Some(1.0),
85 notes: Some("Valid range: 1..4."),
86 }],
87 "highpass2" | "highpass_2_pole" => &[MaParamInfo {
88 key: "k",
89 label: "K",
90 kind: MaParamKind::Float,
91 default: 0.707,
92 min: Some(0.0001),
93 max: Some(10.0),
94 step: Some(0.001),
95 notes: Some("Must be finite and > 0."),
96 }],
97 "jma" => &[
98 MaParamInfo {
99 key: "phase",
100 label: "Phase",
101 kind: MaParamKind::Float,
102 default: 50.0,
103 min: Some(-100.0),
104 max: Some(100.0),
105 step: Some(1.0),
106 notes: Some("Typical range: -100..100."),
107 },
108 MaParamInfo {
109 key: "power",
110 label: "Power",
111 kind: MaParamKind::Int,
112 default: 2.0,
113 min: Some(1.0),
114 max: Some(16.0),
115 step: Some(1.0),
116 notes: Some("Must be an integer >= 1."),
117 },
118 ],
119 "tilson" => &[MaParamInfo {
120 key: "volume_factor",
121 label: "Volume Factor",
122 kind: MaParamKind::Float,
123 default: 0.0,
124 min: Some(-10.0),
125 max: Some(10.0),
126 step: Some(0.1),
127 notes: Some("Must be finite."),
128 }],
129 "ema_deviation_corrected_t3" => &[
130 MaParamInfo {
131 key: "hot",
132 label: "Hot",
133 kind: MaParamKind::Float,
134 default: 0.7,
135 min: Some(-16.0),
136 max: Some(16.0),
137 step: Some(0.01),
138 notes: Some("T3 hot coefficient. Must be finite."),
139 },
140 MaParamInfo {
141 key: "t3_mode",
142 label: "T3 Mode",
143 kind: MaParamKind::Int,
144 default: 0.0,
145 min: Some(0.0),
146 max: Some(1.0),
147 step: Some(1.0),
148 notes: Some("0 = T3 New, 1 = T3 Original."),
149 },
150 ],
151 "wave_smoother" => &[MaParamInfo {
152 key: "phase",
153 label: "Phase",
154 kind: MaParamKind::Float,
155 default: 70.0,
156 min: Some(0.0),
157 max: Some(119.0),
158 step: Some(0.1),
159 notes: Some("Wave phase in degrees. Valid range: 0..119."),
160 }],
161 "maaq" => &[
162 MaParamInfo {
163 key: "fast_period",
164 label: "Fast Period",
165 kind: MaParamKind::Int,
166 default: 2.0,
167 min: Some(1.0),
168 max: Some(512.0),
169 step: Some(1.0),
170 notes: Some("Must be an integer > 0."),
171 },
172 MaParamInfo {
173 key: "slow_period",
174 label: "Slow Period",
175 kind: MaParamKind::Int,
176 default: 30.0,
177 min: Some(1.0),
178 max: Some(2048.0),
179 step: Some(1.0),
180 notes: Some("Must be an integer > 0."),
181 },
182 ],
183 "ehlers_itrend" => &[MaParamInfo {
184 key: "warmup_bars",
185 label: "Warmup Bars",
186 kind: MaParamKind::Int,
187 default: 20.0,
188 min: Some(1.0),
189 max: Some(2048.0),
190 step: Some(1.0),
191 notes: Some("Must be an integer > 0."),
192 }],
193 "ehlers_ecema" => &[MaParamInfo {
194 key: "gain_limit",
195 label: "Gain Limit",
196 kind: MaParamKind::Int,
197 default: 50.0,
198 min: Some(1.0),
199 max: Some(2048.0),
200 step: Some(1.0),
201 notes: Some("Must be an integer > 0."),
202 }],
203 "ehlers_undersampled_double_moving_average" => &[
204 MaParamInfo {
205 key: "fast_length",
206 label: "Fast Length",
207 kind: MaParamKind::Int,
208 default: 6.0,
209 min: Some(1.0),
210 max: Some(4096.0),
211 step: Some(1.0),
212 notes: Some("Must be an integer > 0."),
213 },
214 MaParamInfo {
215 key: "slow_length",
216 label: "Slow Length",
217 kind: MaParamKind::Int,
218 default: 12.0,
219 min: Some(1.0),
220 max: Some(4096.0),
221 step: Some(1.0),
222 notes: Some("Must be an integer > 0."),
223 },
224 MaParamInfo {
225 key: "sample_length",
226 label: "Sample Length",
227 kind: MaParamKind::Int,
228 default: 5.0,
229 min: Some(1.0),
230 max: Some(4096.0),
231 step: Some(1.0),
232 notes: Some("Must be an integer > 0."),
233 },
234 ],
235 "elastic_volume_weighted_moving_average" => &[
236 MaParamInfo {
237 key: "length",
238 label: "Length",
239 kind: MaParamKind::Int,
240 default: 30.0,
241 min: Some(1.0),
242 max: Some(4096.0),
243 step: Some(1.0),
244 notes: Some("Used when use_volume_sum is 1."),
245 },
246 MaParamInfo {
247 key: "absolute_volume_millions",
248 label: "Absolute Volume Millions",
249 kind: MaParamKind::Float,
250 default: 134.0,
251 min: Some(0.000001),
252 max: Some(1000000000.0),
253 step: Some(0.001),
254 notes: Some("Used when use_volume_sum is 0."),
255 },
256 MaParamInfo {
257 key: "use_volume_sum",
258 label: "Use Volume Sum",
259 kind: MaParamKind::Int,
260 default: 0.0,
261 min: Some(0.0),
262 max: Some(1.0),
263 step: Some(1.0),
264 notes: Some("0 = absolute volume, 1 = rolling volume sum."),
265 },
266 ],
267 "frama" => &[
268 MaParamInfo {
269 key: "sc",
270 label: "SC",
271 kind: MaParamKind::Int,
272 default: 300.0,
273 min: Some(1.0),
274 max: Some(4096.0),
275 step: Some(1.0),
276 notes: Some("Smoothing constant (must be > 0)."),
277 },
278 MaParamInfo {
279 key: "fc",
280 label: "FC",
281 kind: MaParamKind::Int,
282 default: 1.0,
283 min: Some(1.0),
284 max: Some(4096.0),
285 step: Some(1.0),
286 notes: Some("Fast constant (must be > 0)."),
287 },
288 ],
289 "volatility_adjusted_ma" | "vama" => &[MaParamInfo {
290 key: "vol_period",
291 label: "Vol Period",
292 kind: MaParamKind::Int,
293 default: 51.0,
294 min: Some(1.0),
295 max: Some(4096.0),
296 step: Some(1.0),
297 notes: Some("Must be an integer > 0."),
298 }],
299 "sama" => &[
300 MaParamInfo {
301 key: "maj_length",
302 label: "Maj Length",
303 kind: MaParamKind::Int,
304 default: 14.0,
305 min: Some(1.0),
306 max: Some(4096.0),
307 step: Some(1.0),
308 notes: Some("Must be an integer > 0."),
309 },
310 MaParamInfo {
311 key: "min_length",
312 label: "Min Length",
313 kind: MaParamKind::Int,
314 default: 6.0,
315 min: Some(1.0),
316 max: Some(4096.0),
317 step: Some(1.0),
318 notes: Some("Must be an integer > 0."),
319 },
320 ],
321 "vpwma" => &[MaParamInfo {
322 key: "power",
323 label: "Power",
324 kind: MaParamKind::Float,
325 default: 0.382,
326 min: Some(-8.0),
327 max: Some(8.0),
328 step: Some(0.001),
329 notes: Some("Must be finite. Integer 0..8 can be faster."),
330 }],
331 "dma" => &[
332 MaParamInfo {
333 key: "ema_length",
334 label: "EMA Length",
335 kind: MaParamKind::Int,
336 default: 20.0,
337 min: Some(1.0),
338 max: Some(4096.0),
339 step: Some(1.0),
340 notes: Some("Must be an integer > 0."),
341 },
342 MaParamInfo {
343 key: "ema_gain_limit",
344 label: "EMA Gain Limit",
345 kind: MaParamKind::Int,
346 default: 50.0,
347 min: Some(1.0),
348 max: Some(4096.0),
349 step: Some(1.0),
350 notes: Some("Must be an integer > 0."),
351 },
352 ],
353 "cora_wave" => &[
354 MaParamInfo {
355 key: "r_multi",
356 label: "R Multi",
357 kind: MaParamKind::Float,
358 default: 2.0,
359 min: Some(0.0),
360 max: Some(16.0),
361 step: Some(0.001),
362 notes: Some("Must be finite and >= 0."),
363 },
364 MaParamInfo {
365 key: "smooth",
366 label: "Smooth",
367 kind: MaParamKind::Int,
368 default: 1.0,
369 min: Some(0.0),
370 max: Some(1.0),
371 step: Some(1.0),
372 notes: Some("0 = off, 1 = on (default)."),
373 },
374 ],
375 _ => &[],
376 }
377}