augurs_core/traits.rs
1use crate::{Forecast, ModelError};
2
3/// A new, unfitted time series forecasting model.
4pub trait Fit {
5 /// The type of the fitted model produced by the `fit` method.
6 type Fitted: Predict;
7
8 /// The type of error returned when fitting the model.
9 type Error: ModelError;
10
11 /// Fit the model to the training data.
12 fn fit(&self, y: &[f64]) -> Result<Self::Fitted, Self::Error>;
13}
14
15impl<F> Fit for Box<F>
16where
17 F: Fit,
18{
19 type Fitted = F::Fitted;
20 type Error = F::Error;
21 fn fit(&self, y: &[f64]) -> Result<Self::Fitted, Self::Error> {
22 (**self).fit(y)
23 }
24}
25
26/// A fitted time series forecasting model.
27pub trait Predict {
28 /// The type of error returned when predicting with the model.
29 type Error: ModelError;
30
31 /// Calculate the in-sample predictions, storing the results in the provided
32 /// [`Forecast`] struct.
33 ///
34 /// The predictions are point forecasts and optionally include
35 /// prediction intervals at the specified `level`.
36 ///
37 /// `level` should be a float between 0 and 1 representing the
38 /// confidence level of the prediction intervals. If `None` then
39 /// no prediction intervals are returned.
40 ///
41 /// # Errors
42 ///
43 /// Any errors returned by the trend model are propagated.
44 fn predict_in_sample_inplace(
45 &self,
46 level: Option<f64>,
47 forecast: &mut Forecast,
48 ) -> Result<(), Self::Error>;
49
50 /// Calculate the n-ahead predictions for the given horizon, storing the results in the
51 /// provided [`Forecast`] struct.
52 ///
53 /// The predictions are point forecasts and optionally include
54 /// prediction intervals at the specified `level`.
55 ///
56 /// `level` should be a float between 0 and 1 representing the
57 /// confidence level of the prediction intervals. If `None` then
58 /// no prediction intervals are returned.
59 ///
60 /// # Errors
61 ///
62 /// Any errors returned by the trend model are propagated.
63 fn predict_inplace(
64 &self,
65 horizon: usize,
66 level: Option<f64>,
67 forecast: &mut Forecast,
68 ) -> Result<(), Self::Error>;
69
70 /// Return the number of training data points used to fit the model.
71 ///
72 /// This is used for pre-allocating the in-sample forecasts.
73 fn training_data_size(&self) -> usize;
74
75 /// Return the n-ahead predictions for the given horizon.
76 ///
77 /// The predictions are point forecasts and optionally include
78 /// prediction intervals at the specified `level`.
79 ///
80 /// `level` should be a float between 0 and 1 representing the
81 /// confidence level of the prediction intervals. If `None` then
82 /// no prediction intervals are returned.
83 ///
84 /// # Errors
85 ///
86 /// Any errors returned by the trend model are propagated.
87 fn predict(
88 &self,
89 horizon: usize,
90 level: impl Into<Option<f64>>,
91 ) -> Result<Forecast, Self::Error> {
92 let level = level.into();
93 let mut forecast = level
94 .map(|l| Forecast::with_capacity_and_level(horizon, l))
95 .unwrap_or_else(|| Forecast::with_capacity(horizon));
96 self.predict_inplace(horizon, level, &mut forecast)?;
97 Ok(forecast)
98 }
99
100 /// Return the in-sample predictions.
101 ///
102 /// The predictions are point forecasts and optionally include
103 /// prediction intervals at the specified `level`.
104 ///
105 /// `level` should be a float between 0 and 1 representing the
106 /// confidence level of the prediction intervals. If `None` then
107 /// no prediction intervals are returned.
108 ///
109 /// # Errors
110 ///
111 /// Any errors returned by the trend model are propagated.
112 fn predict_in_sample(&self, level: impl Into<Option<f64>>) -> Result<Forecast, Self::Error> {
113 let level = level.into();
114 let mut forecast = level
115 .map(|l| Forecast::with_capacity_and_level(self.training_data_size(), l))
116 .unwrap_or_else(|| Forecast::with_capacity(self.training_data_size()));
117 self.predict_in_sample_inplace(level, &mut forecast)?;
118 Ok(forecast)
119 }
120}