1use rustkernel_derive::KernelMessage;
7use serde::{Deserialize, Serialize};
8
9use crate::types::{
10 ARIMAParams, ARIMAResult, AnomalyMethod, ChangePointMethod, ChangePointResult,
11 DecompositionResult, GARCHParams, ProphetResult, TimeSeries, TimeSeriesAnomalyResult,
12 TrendMethod, TrendResult, VolatilityResult,
13};
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct ARIMAForecastInput {
22 pub series: TimeSeries,
24 pub params: ARIMAParams,
26 pub horizon: usize,
28}
29
30impl ARIMAForecastInput {
31 pub fn new(series: TimeSeries, params: ARIMAParams, horizon: usize) -> Self {
33 Self {
34 series,
35 params,
36 horizon,
37 }
38 }
39
40 pub fn with_defaults(series: TimeSeries, horizon: usize) -> Self {
42 Self {
43 series,
44 params: ARIMAParams::new(1, 1, 1),
45 horizon,
46 }
47 }
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct ARIMAForecastOutput {
53 pub result: ARIMAResult,
55 pub compute_time_us: u64,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct ProphetDecompositionInput {
66 pub series: TimeSeries,
68 pub period: Option<usize>,
70 pub horizon: usize,
72}
73
74impl ProphetDecompositionInput {
75 pub fn new(series: TimeSeries, period: Option<usize>, horizon: usize) -> Self {
77 Self {
78 series,
79 period,
80 horizon,
81 }
82 }
83
84 pub fn with_period(series: TimeSeries, period: usize, horizon: usize) -> Self {
86 Self {
87 series,
88 period: Some(period),
89 horizon,
90 }
91 }
92
93 pub fn without_seasonality(series: TimeSeries, horizon: usize) -> Self {
95 Self {
96 series,
97 period: None,
98 horizon,
99 }
100 }
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct ProphetDecompositionOutput {
106 pub result: ProphetResult,
108 pub compute_time_us: u64,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
118pub struct ChangePointDetectionInput {
119 pub series: TimeSeries,
121 pub method: ChangePointMethod,
123 pub penalty: f64,
125 pub min_segment: usize,
127}
128
129impl ChangePointDetectionInput {
130 pub fn new(
132 series: TimeSeries,
133 method: ChangePointMethod,
134 penalty: f64,
135 min_segment: usize,
136 ) -> Self {
137 Self {
138 series,
139 method,
140 penalty,
141 min_segment,
142 }
143 }
144
145 pub fn pelt(series: TimeSeries, penalty: f64) -> Self {
147 Self {
148 series,
149 method: ChangePointMethod::PELT,
150 penalty,
151 min_segment: 10,
152 }
153 }
154
155 pub fn binary_segmentation(series: TimeSeries, penalty: f64) -> Self {
157 Self {
158 series,
159 method: ChangePointMethod::BinarySegmentation,
160 penalty,
161 min_segment: 10,
162 }
163 }
164
165 pub fn cusum(series: TimeSeries, threshold: f64) -> Self {
167 Self {
168 series,
169 method: ChangePointMethod::CUSUM,
170 penalty: threshold,
171 min_segment: 10,
172 }
173 }
174}
175
176#[derive(Debug, Clone, Serialize, Deserialize)]
178pub struct ChangePointDetectionOutput {
179 pub result: ChangePointResult,
181 pub compute_time_us: u64,
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
193#[message(type_id = 2020, domain = "TemporalAnalysis")]
194pub struct TimeSeriesAnomalyDetectionInput {
195 pub series: TimeSeries,
197 pub method: AnomalyMethod,
199 pub threshold: f64,
201 pub window: Option<usize>,
203}
204
205impl TimeSeriesAnomalyDetectionInput {
206 pub fn new(
208 series: TimeSeries,
209 method: AnomalyMethod,
210 threshold: f64,
211 window: Option<usize>,
212 ) -> Self {
213 Self {
214 series,
215 method,
216 threshold,
217 window,
218 }
219 }
220
221 pub fn zscore(series: TimeSeries, threshold: f64) -> Self {
223 Self {
224 series,
225 method: AnomalyMethod::ZScore,
226 threshold,
227 window: None,
228 }
229 }
230
231 pub fn rolling_zscore(series: TimeSeries, threshold: f64, window: usize) -> Self {
233 Self {
234 series,
235 method: AnomalyMethod::ZScore,
236 threshold,
237 window: Some(window),
238 }
239 }
240
241 pub fn iqr(series: TimeSeries, multiplier: f64) -> Self {
243 Self {
244 series,
245 method: AnomalyMethod::IQR,
246 threshold: multiplier,
247 window: None,
248 }
249 }
250
251 pub fn moving_average(series: TimeSeries, threshold: f64, window: usize) -> Self {
253 Self {
254 series,
255 method: AnomalyMethod::MovingAverageDeviation,
256 threshold,
257 window: Some(window),
258 }
259 }
260
261 pub fn seasonal_esd(series: TimeSeries, threshold: f64, period: usize) -> Self {
263 Self {
264 series,
265 method: AnomalyMethod::SeasonalESD,
266 threshold,
267 window: Some(period),
268 }
269 }
270}
271
272#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
276#[message(type_id = 2021, domain = "TemporalAnalysis")]
277pub struct TimeSeriesAnomalyDetectionOutput {
278 pub result: TimeSeriesAnomalyResult,
280 pub compute_time_us: u64,
282}
283
284#[derive(Debug, Clone, Serialize, Deserialize)]
290pub struct SeasonalDecompositionInput {
291 pub series: TimeSeries,
293 pub period: usize,
295 pub robust: bool,
297}
298
299impl SeasonalDecompositionInput {
300 pub fn new(series: TimeSeries, period: usize, robust: bool) -> Self {
302 Self {
303 series,
304 period,
305 robust,
306 }
307 }
308
309 pub fn standard(series: TimeSeries, period: usize) -> Self {
311 Self {
312 series,
313 period,
314 robust: false,
315 }
316 }
317
318 pub fn robust(series: TimeSeries, period: usize) -> Self {
320 Self {
321 series,
322 period,
323 robust: true,
324 }
325 }
326}
327
328#[derive(Debug, Clone, Serialize, Deserialize)]
330pub struct SeasonalDecompositionOutput {
331 pub result: DecompositionResult,
333 pub compute_time_us: u64,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
343pub struct TrendExtractionInput {
344 pub series: TimeSeries,
346 pub method: TrendMethod,
348 pub window: usize,
350}
351
352impl TrendExtractionInput {
353 pub fn new(series: TimeSeries, method: TrendMethod, window: usize) -> Self {
355 Self {
356 series,
357 method,
358 window,
359 }
360 }
361
362 pub fn simple_ma(series: TimeSeries, window: usize) -> Self {
364 Self {
365 series,
366 method: TrendMethod::SimpleMovingAverage,
367 window,
368 }
369 }
370
371 pub fn ema(series: TimeSeries, span: usize) -> Self {
373 Self {
374 series,
375 method: TrendMethod::ExponentialMovingAverage,
376 window: span,
377 }
378 }
379
380 pub fn centered_ma(series: TimeSeries, window: usize) -> Self {
382 Self {
383 series,
384 method: TrendMethod::CenteredMovingAverage,
385 window,
386 }
387 }
388
389 pub fn lowess(series: TimeSeries, bandwidth: usize) -> Self {
391 Self {
392 series,
393 method: TrendMethod::Lowess,
394 window: bandwidth,
395 }
396 }
397}
398
399#[derive(Debug, Clone, Serialize, Deserialize)]
401pub struct TrendExtractionOutput {
402 pub result: TrendResult,
404 pub compute_time_us: u64,
406}
407
408#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
416#[message(type_id = 2050, domain = "TemporalAnalysis")]
417pub struct VolatilityAnalysisInput {
418 pub returns: TimeSeries,
420 pub params: GARCHParams,
422 pub forecast_horizon: usize,
424}
425
426impl VolatilityAnalysisInput {
427 pub fn new(returns: TimeSeries, params: GARCHParams, forecast_horizon: usize) -> Self {
429 Self {
430 returns,
431 params,
432 forecast_horizon,
433 }
434 }
435
436 pub fn garch_1_1(returns: TimeSeries, forecast_horizon: usize) -> Self {
438 Self {
439 returns,
440 params: GARCHParams::new(1, 1),
441 forecast_horizon,
442 }
443 }
444
445 pub fn garch(returns: TimeSeries, p: usize, q: usize, forecast_horizon: usize) -> Self {
447 Self {
448 returns,
449 params: GARCHParams::new(p, q),
450 forecast_horizon,
451 }
452 }
453}
454
455#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
459#[message(type_id = 2051, domain = "TemporalAnalysis")]
460pub struct VolatilityAnalysisOutput {
461 pub result: VolatilityResult,
463 pub compute_time_us: u64,
465}
466
467#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
471#[message(type_id = 2052, domain = "TemporalAnalysis")]
472pub struct EWMAVolatilityInput {
473 pub returns: TimeSeries,
475 pub lambda: f64,
477 pub forecast_horizon: usize,
479}
480
481impl EWMAVolatilityInput {
482 pub fn new(returns: TimeSeries, lambda: f64, forecast_horizon: usize) -> Self {
484 Self {
485 returns,
486 lambda,
487 forecast_horizon,
488 }
489 }
490
491 pub fn riskmetrics(returns: TimeSeries, forecast_horizon: usize) -> Self {
493 Self {
494 returns,
495 lambda: 0.94,
496 forecast_horizon,
497 }
498 }
499}
500
501#[derive(Debug, Clone, Serialize, Deserialize, KernelMessage)]
505#[message(type_id = 2053, domain = "TemporalAnalysis")]
506pub struct EWMAVolatilityOutput {
507 pub result: VolatilityResult,
509 pub compute_time_us: u64,
511}