ta_statistics/traits/
paired_statistics.rs

1/// Paired statistics trait for calculating statistics on pairs of values
2///
3/// This trait provides a foundation for calculating various statistics on pairs of values,
4/// such as covariance, correlation, and beta. It is used as a base trait for more specific
5/// statistical calculations that examine relationships between two variables.
6pub trait PairedStatistics<T> {
7    /// Updates the paired statistical calculations with a new value pair in the time series
8    ///
9    /// Incorporates a new data point pair into the rolling window, maintaining the specified
10    /// window size by removing the oldest pair when necessary. This core method provides
11    /// the foundation for all paired statistical measures that examine relationships
12    /// between two variables.
13    ///
14    /// # Arguments
15    ///
16    /// * `value` - A tuple containing the paired values (x, y) to incorporate into calculations
17    ///
18    /// # Returns
19    ///
20    /// * `&mut Self` - The updated statistics object for method chaining
21    fn next(&mut self, value: (T, T)) -> &mut Self
22    where
23        Self: Sized;
24
25    /// Returns the covariance of the paired values in the rolling window
26    ///
27    /// Covariance measures how two variables change together, indicating the direction
28    /// of their linear relationship. This fundamental measure of association provides:
29    ///
30    /// - Directional relationship analysis between paired time series
31    /// - Foundation for correlation, beta, and regression calculations
32    /// - Raw measurement of how variables move in tandem
33    /// - Basis for portfolio diversification and risk assessments
34    ///
35    /// # Returns
36    ///
37    /// * `Option<T>` - The covariance of the values in the window, or `None` if the window is not full
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use ta_statistics::{Statistics, PairedStatistics};
43    /// use assert_approx_eq::assert_approx_eq;
44    ///
45    /// let mut stats = Statistics::new(3);
46    /// let mut results = vec![];
47    /// let inputs = [(2.0, 1.0), (4.0, 3.0), (6.0, 2.0), (8.0, 5.0), (10.0, 7.0)];
48    /// inputs.iter().for_each(|i| {
49    ///     stats.next(*i).cov().map(|v| results.push(v));
50    /// });
51    ///
52    /// let expected: [f64; 3] = [0.6667, 1.3333, 3.3333];
53    ///  for (i, e) in expected.iter().enumerate() {
54    ///  assert_approx_eq!(e, results[i], 0.1);
55    ///  }
56    ///
57    /// stats.reset().set_ddof(true);
58    /// results = vec![];
59    /// inputs.iter().for_each(|i| {
60    ///     stats.next(*i).cov().map(|v| results.push(v));
61    /// });
62    ///
63    /// let expected: [f64; 3] = [1.0, 2.0, 5.0];
64    /// for (i, e) in expected.iter().enumerate() {
65    ///    assert_approx_eq!(e, results[i], 0.1);
66    /// }
67    /// ```
68    fn cov(&self) -> Option<T>;
69
70    /// Returns the correlation coefficient (Pearson's r) of paired values in the rolling window
71    ///
72    /// Correlation normalizes covariance by the product of standard deviations, producing
73    /// a standardized measure of linear relationship strength between -1 and 1:
74    ///
75    /// - Quantifies the strength and direction of relationships between variables
76    /// - Enables cross-pair comparison on a standardized scale
77    /// - Provides the foundation for statistical arbitrage models
78    /// - Identifies regime changes in intermarket relationships
79    ///
80    /// # Returns
81    ///
82    /// * `Option<T>` - The correlation coefficient in the window, or `None` if the window is not full
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// use ta_statistics::{Statistics, PairedStatistics};
88    /// use assert_approx_eq::assert_approx_eq;
89    ///
90    /// let mut stats = Statistics::new(3);
91    /// let mut results = vec![];
92    /// let inputs = [
93    ///     (0.496714, 0.115991),
94    ///     (-0.138264, -0.329650),
95    ///     (0.647689, 0.574363),
96    ///     (1.523030, 0.109481),
97    ///     (-0.234153, -1.026366),
98    ///     (-0.234137, -0.445040),
99    ///     (1.579213, 0.599033),
100    ///     (0.767435, 0.694328),
101    ///     (-0.469474, -0.782644),
102    ///     (0.542560, -0.326360)
103    /// ];
104    ///
105    /// inputs.iter().for_each(|i| {
106    ///     stats.next(*i).corr().map(|v| results.push(v));
107    /// });
108    /// let expected: [f64; 8] = [0.939464, 0.458316, 0.691218, 0.859137, 0.935658, 0.858379, 0.895148, 0.842302,];
109    /// for (i, e) in expected.iter().enumerate() {
110    ///     assert_approx_eq!(e, results[i], 0.1);
111    /// }
112    ///
113    /// ```
114    fn corr(&self) -> Option<T>;
115
116    /// Returns the beta coefficient of the paired values in the rolling window
117    ///
118    /// Beta measures the relative volatility between two time series, indicating
119    /// the sensitivity of one variable to changes in another:
120    ///
121    /// - Quantifies systematic risk exposure between related instruments
122    /// - Determines optimal hedge ratios for risk management
123    /// - Provides relative sensitivity analysis for pair relationships
124    /// - Serves as a key input for factor modeling and attribution analysis
125    ///
126    /// # Returns
127    ///
128    /// * `Option<T>` - The beta coefficient in the window, or `None` if the window is not full
129    ///
130    /// # Examples
131    ///
132    /// ```
133    /// use ta_statistics::{Statistics, PairedStatistics};
134    /// use assert_approx_eq::assert_approx_eq;
135    ///
136    /// let mut stats = Statistics::new(3);
137    /// let mut results = vec![];
138    /// let inputs = [
139    ///      (0.015, 0.010),
140    ///      (0.025, 0.015),
141    ///      (-0.010, -0.005),
142    ///      (0.030, 0.020),
143    ///      (0.005, 0.010),
144    ///      (-0.015, -0.010),
145    ///      (0.020, 0.015),
146    /// ];
147    ///
148    /// inputs.iter().for_each(|i| {
149    ///     stats.next(*i).beta().map(|v| results.push(v));
150    /// });
151    ///  
152    /// let expected: [f64; 5] = [1.731, 1.643, 1.553, 1.429, 1.286];
153    /// for (i, e) in expected.iter().enumerate() {
154    ///     assert_approx_eq!(e, results[i], 0.1);
155    /// }
156    /// ```
157    fn beta(&self) -> Option<T>;
158}