ta_statistics/traits/
single_statistics.rs

1/// Single statistics trait for calculating statistics on a single value
2///
3/// This trait provides a foundation for calculating various statistics on a single value,
4/// such as mean, variance, standard deviation, and other measures of central tendency and
5/// dispersion. It is used as a base trait for more specific statistical calculations that
6/// examine relationships between variables.
7pub trait SingleStatistics<T> {
8    /// Updates the statistical calculations with a new value in the time series
9    ///
10    /// Incorporates a new data point into the rolling window, maintaining the specified
11    /// window size by removing the oldest value when necessary. This is the core method
12    /// that should be called whenever new data is available for processing.
13    fn next(&mut self, value: T) -> &mut Self
14    where
15        Self: Sized;
16    /// Returns the sum of all values in the rolling window
17    ///
18    /// This fundamental calculation serves as the basis for numerous higher-order statistics
19    /// and provides key insights for:
20    ///
21    /// - Aggregating transaction volumes to identify participant interest levels
22    /// - Constructing accumulation/distribution profiles across price action
23    /// - Measuring net directional pressure in time series data
24    /// - Quantifying capital flows between market segments
25    ///
26    /// # Returns
27    ///
28    /// * `Option<T>` - The sum of all values in the window, or `None` if the window is not full
29    ///
30    /// # Examples
31    ///
32    /// ```
33    /// # use ta_statistics::{Statistics, SingleStatistics};
34    /// let mut stats = Statistics::new(3);
35    /// let inputs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
36    /// let mut results = vec![];
37    ///
38    /// inputs.iter().for_each(|i| {
39    ///     stats.next(*i).sum().map(|v| results.push(v));
40    /// });
41    ///
42    /// let expected = [6.0, 9.0, 12.0, 15.0];
43    /// assert_eq!(&results, &expected);
44    /// ```
45    fn sum(&self) -> Option<T>;
46
47    /// Returns the sum of squares of all values in the rolling window
48    ///
49    /// This calculation provides the sum of squared values in the series, offering insights into
50    /// the magnitude of values regardless of sign:
51    ///
52    /// - Serves as a component for calculating variance and other dispersion measures
53    /// - Emphasizes larger values due to the squaring operation
54    /// - Provides power estimation in signal processing applications
55    /// - Helps detect significant deviations from expected behavior
56    ///
57    /// # Returns
58    ///
59    /// * `Option<T>` - The sum of squares in the window, or `None` if the window is not full
60    ///
61    /// # Examples
62    ///
63    /// ```
64    /// # use ta_statistics::{Statistics, SingleStatistics};
65    /// let mut stats = Statistics::new(3);
66    /// let inputs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
67    /// let mut results = vec![];
68    ///
69    /// inputs.iter().for_each(|i| {
70    ///     stats.next(*i).sum_sq().map(|v| results.push(v));
71    /// });
72    ///
73    /// let expected = [14.0, 29.0, 50.0, 77.0];
74    /// assert_eq!(&results, &expected);
75    /// ```
76    fn sum_sq(&self) -> Option<T>;
77
78    /// Returns the arithmetic mean of all values in the rolling window
79    ///
80    /// This central tendency measure forms the foundation for numerous statistical calculations
81    /// and serves as a reference point for analyzing data distributions:
82    ///
83    /// - Establishes equilibrium levels for reversion-based analytical models
84    /// - Provides baseline reference for filtering noisy sequential data
85    /// - Creates statistical foundation for pattern detection in time series
86    /// - Enables feature normalization in advanced predictive modeling
87    ///
88    /// # Returns
89    ///
90    /// * `Option<T>` - The arithmetic mean of values in the window, or `None` if the window is not full
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// # use ta_statistics::{Statistics, SingleStatistics};
96    /// let mut stats = Statistics::new(3);
97    /// let inputs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
98    /// let mut results = vec![];
99    ///
100    /// inputs.iter().for_each(|i| {
101    ///     stats.next(*i).mean().map(|v| results.push(v));
102    /// });
103    ///
104    /// let expected = [2.0, 3.0, 4.0, 5.0];
105    /// assert_eq!(&results, &expected);
106    /// ```
107    fn mean(&self) -> Option<T>;
108    /// Returns the mean of squares of all values in the rolling window
109    ///
110    /// This calculation provides the average of squared values in the series, offering
111    /// insights into the magnitude of values regardless of sign:
112    ///
113    /// - Serves as a component for calculating variance and other dispersion measures
114    /// - Emphasizes larger values due to the squaring operation
115    /// - Provides power estimation in signal processing applications
116    /// - Helps detect significant deviations from expected behavior
117    ///
118    /// # Returns
119    ///
120    /// * `Option<T>` - The mean of squared values in the window, or `None` if the window is not full
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// # use ta_statistics::{Statistics, SingleStatistics};
126    /// # use assert_approx_eq::assert_approx_eq;
127    /// let mut stats = Statistics::new(3);
128    /// let inputs = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0];
129    /// let mut results = vec![];
130    ///
131    /// inputs.iter().for_each(|i| {
132    ///     stats.next(*i).mean_sq().map(|v| results.push(v));
133    /// });
134    ///
135    /// let expected: [f64; 4] = [4.66, 9.66, 16.66, 25.66];
136    /// for (i, e) in expected.iter().enumerate() {
137    ///     assert_approx_eq!(e, results[i], 0.1);
138    /// }
139    /// ```
140    fn mean_sq(&self) -> Option<T>;
141    /// Returns the mode (most frequently occurring value) in the rolling window
142    ///
143    /// The mode identifies the most common value within a distribution, providing
144    /// insight into clustering behavior and prevalent conditions:
145    ///
146    /// - Identifies common price points that may act as magnets or barriers
147    /// - Detects clustering in volume or activity patterns
148    /// - Provides non-parametric central tendency alternative to mean/median
149    /// - Highlights dominant price levels where transactions concentrate
150    ///
151    /// # Returns
152    ///
153    /// * `Option<T>` - The mode of values in the window, or `None` if the window is not full
154    ///
155    /// # Examples
156    ///
157    /// ```
158    /// # use ta_statistics::{Statistics, SingleStatistics};
159    /// # use assert_approx_eq::assert_approx_eq;
160    /// let mut stats = Statistics::new(3);
161    /// let inputs = [1.0, 2.0, 1.0, 2.0, 3.0, 3.0, 3.0, 2.0, 2.0, 1.0];
162    /// let mut results = vec![];
163    ///
164    /// inputs.iter().for_each(|i| {
165    ///     stats.next(*i).mode().map(|v| results.push(v));
166    /// });
167    ///
168    /// let expected: [f64; 8] = [1.0, 2.0, 1.0, 3.0, 3.0, 3.0, 2.0, 2.0];
169    /// assert_eq!(&results, &expected);
170    /// ```
171    fn mode(&mut self) -> Option<T>;
172    /// Returns the median (middle value) of the rolling window
173    ///
174    /// The median represents the central value when data is sorted, providing a robust
175    /// measure of central tendency that's less affected by outliers than the mean:
176    ///
177    /// - Offers resilient central price estimation in volatile conditions
178    /// - Establishes more stable reference points during extreme events
179    /// - Provides core input for non-parametric statistical models
180    /// - Creates baseline for interquartile range and other robust dispersion measures
181    ///
182    /// # Returns
183    ///
184    /// * `Option<T>` - The median of values in the window, or `None` if the window is not full
185    ///
186    /// # Examples
187    ///
188    /// ```
189    /// # use ta_statistics::{Statistics, SingleStatistics};
190    /// # use assert_approx_eq::assert_approx_eq;
191    /// let mut stats = Statistics::new(3);
192    /// let inputs = [5.0, 2.0, 8.0, 1.0, 7.0, 3.0, 9.0];
193    /// let mut results = vec![];
194    ///
195    /// inputs.iter().for_each(|i| {
196    ///     stats.next(*i).median().map(|v| results.push(v));
197    /// });
198    ///
199    /// let expected: [f64; 5] = [5.0, 2.0, 7.0, 3.0, 7.0];
200    /// assert_eq!(&results, &expected);
201    /// ```
202    fn median(&mut self) -> Option<T>;
203    /// Returns the minimum value in the rolling window
204    ///
205    /// The minimum value represents the lower bound of a data series over the observation
206    /// period, providing key reference points for analysis and decision-making:
207    ///
208    /// - Establishes potential support levels in price-based analysis
209    /// - Identifies optimal entry thresholds for mean-reverting sequences
210    /// - Sets critical risk boundaries for position management systems
211    /// - Provides baseline scenarios for stress-testing and risk modeling
212    ///
213    /// # Returns
214    ///
215    /// * `Option<T>` - The minimum value in the window, or `None` if the window is not full
216    ///
217    /// # Examples
218    ///
219    /// ```
220    /// # use ta_statistics::{Statistics, SingleStatistics};
221    /// # use assert_approx_eq::assert_approx_eq;
222    /// let mut stats = Statistics::new(3);
223    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
224    /// let mut results = vec![];
225    ///
226    /// inputs.iter().for_each(|i| {
227    ///     stats.next(*i).min().map(|v| results.push(v));
228    /// });
229    ///
230    /// let expected: [f64; 7] = [25.4, 26.0, 25.8, 25.8, 25.8, 25.9, 26.2];
231    /// assert_eq!(&results, &expected);
232    /// ```
233    fn min(&mut self) -> Option<T>;
234    /// Returns the maximum value in the rolling window
235    ///
236    /// The maximum value identifies the upper bound of a data series over the observation
237    /// period, establishing crucial reference points for analytical frameworks:
238    ///
239    /// - Identifies potential resistance zones in technical analysis
240    /// - Optimizes profit-taking thresholds based on historical precedent
241    /// - Confirms genuine breakouts from established trading ranges
242    /// - Defines upper boundaries for range-bound trading approaches
243    ///
244    /// # Returns
245    ///
246    /// * `Option<T>` - The maximum value in the window, or `None` if the window is not full
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// # use ta_statistics::{Statistics, SingleStatistics};
252    /// # use assert_approx_eq::assert_approx_eq;
253    /// let mut stats = Statistics::new(3);
254    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
255    /// let mut results = vec![];
256    ///
257    /// inputs.iter().for_each(|i| {
258    ///     stats.next(*i).max().map(|v| results.push(v));
259    /// });
260    ///
261    /// let expected: [f64; 7] = [26.2, 26.2, 26.1, 26.1, 26.3, 26.3, 26.5];
262    /// assert_eq!(&results, &expected);
263    /// ```
264    fn max(&mut self) -> Option<T>;
265    /// Returns the mean absolute deviation of values in the rolling window
266    ///
267    /// This robust dispersion measure calculates the average absolute difference from the mean,
268    /// offering advantages over variance in certain analytical contexts:
269    ///
270    /// - Provides volatility measurement that's less sensitive to extreme outliers
271    /// - Quantifies data noise levels to enhance signal processing accuracy
272    /// - Complements standard risk models with an alternative dispersion metric
273    /// - Establishes more stable thresholds for adaptive signal generation
274    ///
275    /// # Returns
276    ///
277    /// * `Option<T>` - The mean absolute deviation of values, or `None` if the window is not full
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// # use ta_statistics::{Statistics, SingleStatistics};
283    /// # use assert_approx_eq::assert_approx_eq;
284    /// let mut stats = Statistics::new(3);
285    /// let mut results = vec![];
286    /// let inputs = [2.0, 4.0, 6.0, 8.0, 10.0];
287    /// inputs.iter().for_each(|i| {
288    ///     stats.next(*i).mean_absolute_deviation().map(|v| results.push(v));
289    /// });
290    ///
291    /// let expected: [f64; 3] = [1.3333, 1.3333, 1.3333];
292    /// for (i, e) in expected.iter().enumerate() {
293    ///     assert_approx_eq!(e, results[i], 0.1);
294    /// }
295    ///
296    /// ```
297    fn mean_absolute_deviation(&self) -> Option<T>;
298    /// Returns the median absolute deviation of values in the rolling window
299    ///
300    /// This exceptionally robust dispersion measure calculates the median of absolute differences
301    /// from the median, offering superior resistance to outliers:
302    ///
303    /// - Provides reliable volatility assessment in erratic or noisy environments
304    /// - Serves as a foundation for robust anomaly detection systems
305    /// - Enables stable threshold calibration for adaptive decision systems
306    /// - Forms basis for robust statistical estimators in non-normal distributions
307    ///
308    /// # Returns
309    ///
310    /// * `Option<T>` - The median absolute deviation of values, or `None` if the window is not full
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// # use ta_statistics::{Statistics, SingleStatistics};
316    /// # use assert_approx_eq::assert_approx_eq;
317    /// let mut stats = Statistics::new(3);
318    /// let mut results = vec![];
319    /// let inputs = [5.0, 2.0, 8.0, 1.0, 7.0, 3.0, 9.0];
320    /// inputs.iter().for_each(|i| {
321    ///     stats.next(*i).median_absolute_deviation().map(|v| results.push(v));
322    /// });
323    ///
324    /// let expected: [f64; 5] = [3.0, 1.0, 1.0, 2.0, 2.0];
325    /// for (i, e) in expected.iter().enumerate() {
326    ///     assert_approx_eq!(e, results[i], 0.1);
327    /// }
328    ///
329    /// ```
330    fn median_absolute_deviation(&mut self) -> Option<T>;
331    /// Returns the variance of values in the rolling window
332    ///
333    /// This second-moment statistical measure quantifies dispersion around the mean
334    /// and serves multiple analytical purposes:
335    ///
336    /// - Providing core risk assessment metrics for position sizing decisions
337    /// - Enabling volatility regime detection to adapt methodologies appropriately
338    /// - Filtering signal noise to improve discriminatory power
339    /// - Identifying dispersion-based opportunities in related instrument groups
340    ///
341    /// # Returns
342    ///
343    /// * `Option<T>` - The variance of values in the window, or `None` if the window is not full
344    ///
345    /// # Examples
346    ///
347    /// ```
348    /// # use ta_statistics::{Statistics, SingleStatistics};
349    /// # use assert_approx_eq::assert_approx_eq;
350    /// let mut stats = Statistics::new(3);
351    /// let mut results = vec![];
352    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
353    /// inputs.iter().for_each(|i| {
354    ///     stats.next(*i).variance().map(|v| results.push(v));
355    /// });
356    ///
357    /// let expected: [f64; 7] = [0.1156, 0.0067, 0.0156, 0.0156, 0.0422, 0.0289, 0.0156];
358    /// for (i, e) in expected.iter().enumerate() {
359    ///     assert_approx_eq!(e, results[i], 0.1);
360    /// }
361    ///
362    /// stats.reset().set_ddof(true);
363    /// results = vec![];
364    /// inputs.iter().for_each(|i| {
365    ///     stats.next(*i).variance().map(|v| results.push(v));
366    /// });
367    ///
368    /// let expected: [f64; 7] = [0.1733, 0.0100, 0.0233, 0.0233, 0.0633, 0.0433, 0.0233];
369    /// for (i, e) in expected.iter().enumerate() {
370    ///     assert_approx_eq!(e, results[i], 0.1);
371    /// }
372    /// ```
373    fn variance(&self) -> Option<T>;
374    /// Returns the standard deviation of values in the rolling window
375    ///
376    /// As the square root of variance, this statistic provides an intuitive measure
377    /// of data dispersion in the original units and enables:
378    ///
379    /// - Setting dynamic volatility thresholds for risk boundaries
380    /// - Detecting potential mean-reversion opportunities when values deviate significantly
381    /// - Normalizing position sizing across different volatility environments
382    /// - Identifying market regime changes to adapt strategic approaches
383    ///
384    /// # Returns
385    ///
386    /// * `Option<T>` - The standard deviation of values in the window, or `None` if the window is not full
387    ///
388    /// # Examples
389    ///
390    /// ```
391    /// # use ta_statistics::{Statistics, SingleStatistics};
392    /// # use assert_approx_eq::assert_approx_eq;
393    /// let mut stats = Statistics::new(3);
394    /// let mut results = vec![];
395    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
396    /// inputs.iter().for_each(|i| {
397    ///     stats.next(*i).stddev().map(|v| results.push(v));
398    /// });
399    ///
400    /// let expected: [f64; 7] = [0.3400, 0.0816, 0.1249, 0.1249, 0.2054, 0.1700, 0.1249];
401    /// for (i, e) in expected.iter().enumerate() {
402    ///     assert_approx_eq!(e, results[i], 0.1);
403    /// }
404    ///
405    /// stats.reset().set_ddof(true);
406    /// results = vec![];
407    /// inputs.iter().for_each(|i| {
408    ///     stats.next(*i).stddev().map(|v| results.push(v));
409    /// });
410    ///
411    /// let expected: [f64; 7] = [0.4162, 0.1000, 0.1527, 0.1527, 0.2516, 0.2081, 0.1527];
412    /// for (i, e) in expected.iter().enumerate() {
413    ///     assert_approx_eq!(e, results[i], 0.1);
414    /// }
415    /// ```
416    fn stddev(&self) -> Option<T>;
417    /// Returns the z-score of the most recent value relative to the rolling window
418    ///
419    /// Z-scores express how many standard deviations a value deviates from the mean,
420    /// providing a normalized measure that facilitates:
421    ///
422    /// - Statistical arbitrage through relative valuation in correlated series
423    /// - Robust outlier detection across varying market conditions
424    /// - Cross-instrument comparisons on a standardized scale
425    /// - Setting consistent thresholds that remain valid across changing volatility regimes
426    ///
427    /// # Returns
428    ///
429    /// * `Option<T>` - The z-score of the most recent value, or `None` if the window is not full
430    ///
431    /// # Examples
432    ///
433    /// ```
434    /// # use ta_statistics::{Statistics, SingleStatistics};
435    /// # use assert_approx_eq::assert_approx_eq;
436    /// let mut stats = Statistics::new(3);
437    /// let mut results = vec![];
438    /// let inputs = [1.2, -0.7, 3.4, 2.1, -1.5, 0.0, 2.2, -0.3, 1.5, -2.0];
439    /// inputs.iter().for_each(|i| {
440    ///     stats.next(*i).zscore().map(|v| results.push(v));
441    /// });
442    ///
443    /// let expected: [f64; 8] = [1.253, 0.292, -1.366, -0.136, 1.294, -0.835, 0.349, -1.210];
444    /// for (i, e) in expected.iter().enumerate() {
445    ///     assert_approx_eq!(e, results[i], 0.1);
446    /// }
447    ///
448    /// stats.reset().set_ddof(true);
449    /// results = vec![];
450    /// inputs.iter().for_each(|i| {
451    ///     stats.next(*i).zscore().map(|v| results.push(v));
452    /// });
453    ///
454    /// let expected: [f64; 8] = [1.024, 0.239, -1.116, -0.103, 1.000, -0.686, 0.285, -0.990];
455    /// for (i, e) in expected.iter().enumerate() {
456    ///     assert_approx_eq!(e, results[i], 0.1);
457    /// }
458    /// ```
459    fn zscore(&self) -> Option<T>;
460    /// Returns the skewness of values in the rolling window
461    ///
462    /// This third-moment statistic measures distribution asymmetry, revealing whether
463    /// extreme values tend toward one direction. A comprehensive analysis of skewness:
464    ///
465    /// - Detects asymmetric return distributions critical for accurate risk modeling
466    /// - Reveals directional biases in market microstructure that may predict future movements
467    /// - Provides early signals of potential regime transitions in volatile environments
468    /// - Enables refined models for derivative pricing beyond simple volatility assumptions
469    ///
470    /// # Returns
471    ///
472    /// * `Option<T>` - The skewness of values in the window, or `None` if the window is not full
473    ///
474    /// # Examples
475    ///
476    /// ```
477    /// # use ta_statistics::{Statistics, SingleStatistics};
478    /// # use assert_approx_eq::assert_approx_eq;
479    /// let mut stats = Statistics::new(4);
480    /// let mut results = vec![];
481    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
482    /// inputs.iter().for_each(|i| {
483    ///     stats.next(*i).skew().map(|v| results.push(v));
484    /// });
485    ///
486    /// let expected: [f64; 6] =  [-0.979, -0.435, -0.0, 0.278, -0.0, -0.323];
487    /// for (i, e) in expected.iter().enumerate() {
488    ///     assert_approx_eq!(e, results[i], 0.1);
489    /// }
490    ///
491    /// stats.reset().set_ddof(true);
492    /// results = vec![];
493    /// inputs.iter().for_each(|i| {
494    ///     stats.next(*i).skew().map(|v| results.push(v));
495    /// });
496    ///
497    /// let expected: [f64; 6] = [-1.696, -0.753, 0.000, 0.482, 0.000, -0.560];
498    /// for (i, e) in expected.iter().enumerate() {
499    ///     assert_approx_eq!(e, results[i], 0.1);
500    /// }
501    /// ```
502    fn skew(&self) -> Option<T>;
503    /// Returns the kurtosis of values in the rolling window
504    ///
505    /// This fourth-moment statistic measures the 'tailedness' of a distribution, describing
506    /// the frequency of extreme values compared to a normal distribution:
507    ///
508    /// - Quantifies fat-tail risk exposure essential for anticipating extreme market movements
509    /// - Signals potentially exploitable market inefficiencies through distribution analysis
510    /// - Provides critical parameters for selecting appropriate derivatives strategies
511    /// - Enhances Value-at-Risk models by incorporating more realistic tail behavior
512    ///
513    /// # Returns
514    ///
515    /// * `Option<T>` - The kurtosis of values in the window, or `None` if the window is not full
516    ///
517    /// # Examples
518    ///
519    /// ```
520    /// # use ta_statistics::{Statistics, SingleStatistics};
521    /// # use assert_approx_eq::assert_approx_eq;
522    /// let mut stats = Statistics::new(4);
523    /// let mut results = vec![];
524    /// let inputs = [25.4, 26.2, 26.0, 26.1, 25.8, 25.9, 26.3, 26.2, 26.5];
525    /// inputs.iter().for_each(|i| {
526    ///     stats.next(*i).kurt().map(|v| results.push(v));
527    /// });
528    ///
529    /// let expected: [f64; 6] = [-0.7981, -1.1543, -1.3600, -1.4266, -1.7785, -1.0763];
530    /// for (i, e) in expected.iter().enumerate() {
531    ///     assert_approx_eq!(e, results[i], 0.1);
532    /// }
533    ///
534    /// stats.reset().set_ddof(true);
535    /// results = vec![];
536    /// inputs.iter().for_each(|i| {
537    ///     stats.next(*i).kurt().map(|v| results.push(v));
538    /// });
539    ///
540    /// let expected: [f64; 6] = [3.014, 0.343, -1.200, -1.700, -4.339, 0.928];
541    /// for (i, e) in expected.iter().enumerate() {
542    ///     assert_approx_eq!(e, results[i], 0.1);
543    /// }
544    /// ```
545    fn kurt(&self) -> Option<T>;
546    /// Returns the slope of the linear regression line
547    ///
548    /// The regression slope represents the rate of change in the best-fit linear model,
549    /// quantifying the directional movement and its magnitude within the data:
550    ///
551    /// - Provides precise measurement of trend strength and conviction
552    /// - Quantifies velocity of change for optimal timing decisions
553    /// - Signals potential reversion points when diverging from historical patterns
554    /// - Measures the relative imbalance between supply and demand forces
555    ///
556    /// # Returns
557    ///
558    /// * `Option<T>` - The slope of the linear regression line, or `None` if the window is not full
559    ///
560    /// # Examples
561    ///
562    /// ```
563    /// # use ta_statistics::{Statistics, SingleStatistics};
564    /// # use assert_approx_eq::assert_approx_eq;
565    /// let mut stats = Statistics::new(5);
566    /// let mut results = vec![];
567    /// let inputs = [10.0, 10.5, 11.2, 10.9, 11.5, 11.9, 12.3, 12.1, 11.8, 12.5];
568    /// inputs.iter().for_each(|i| {
569    ///     stats.next(*i).linreg_slope().map(|v| results.push(v));
570    /// });
571    ///
572    /// let expected: [f64; 6] = [0.34, 0.31, 0.32, 0.32, 0.08, 0.07];
573    /// for (i, e) in expected.iter().enumerate() {
574    ///     assert_approx_eq!(e, results[i], 0.1);
575    /// }
576    /// ```
577    fn linreg_slope(&self) -> Option<T>;
578    /// Returns both slope and intercept of the linear regression line
579    ///
580    /// This comprehensive regression analysis provides the complete linear model,
581    /// enabling more sophisticated trend-based calculations:
582    ///
583    /// - Constructs complete linear models of price or indicator evolution
584    /// - Determines both direction and reference level in a single calculation
585    /// - Enables advanced divergence analysis against actual values
586    /// - Provides foundation for channel-based analytical frameworks
587    ///
588    /// # Returns
589    ///
590    /// * `Option<(T, T)>` - A tuple containing (slope, intercept), or `None` if the window is not full
591    ///
592    /// # Examples
593    ///
594    /// ```
595    /// # use ta_statistics::{Statistics, SingleStatistics};
596    /// # use assert_approx_eq::assert_approx_eq;
597    /// let mut stats = Statistics::new(5);
598    /// let mut ddof = false;
599    /// let mut results = vec![];
600    /// let inputs = [10.0, 10.5, 11.2, 10.9, 11.5, 11.9, 12.3, 12.1, 11.8, 12.5];
601    /// inputs.iter().for_each(|i| {
602    ///     stats.next(*i).linreg_slope_intercept().map(|v| results.push(v));
603    /// });
604    ///
605    /// let expected: [(f64, f64); 6] = [
606    ///     (0.34, 10.14),
607    ///     (0.31, 10.58),
608    ///     (0.32, 10.92),
609    ///     (0.32, 11.1),
610    ///     (0.08, 11.76),
611    ///     (0.07, 11.98),
612    /// ];
613    /// for (i, e) in expected.iter().enumerate() {
614    ///     assert_approx_eq!(e.0, results[i].0, 0.1);
615    ///     assert_approx_eq!(e.1, results[i].1, 0.1);
616    /// }
617    /// ```
618    fn linreg_slope_intercept(&self) -> Option<(T, T)>;
619    /// Returns the y-intercept of the linear regression line
620    ///
621    /// The regression intercept represents the base level or starting point of the
622    /// best-fit linear model, providing key reference information:
623    ///
624    /// - Establishes the theoretical zero-point reference level
625    /// - Complements slope calculations to complete linear projections
626    /// - Assists in fair value determination for mean-reversion models
627    /// - Provides a fixed component for decomposing price into trend and oscillation
628    ///
629    /// # Returns
630    ///
631    /// * `Option<T>` - The y-intercept of the regression line, or `None` if the window is not full
632    ///
633    /// # Examples
634    ///
635    /// ```
636    /// # use ta_statistics::{Statistics, SingleStatistics};
637    /// # use assert_approx_eq::assert_approx_eq;
638    /// let mut stats = Statistics::new(5);
639    /// let mut results = vec![];
640    /// let inputs = [10.0, 10.5, 11.2, 10.9, 11.5, 11.9, 12.3, 12.1, 11.8, 12.5];
641    /// inputs.iter().for_each(|i| {
642    ///     stats.next(*i).linreg_intercept().map(|v| results.push(v));
643    /// });
644    ///
645    /// let expected: [f64; 6] = [10.14, 10.58, 10.92, 11.1, 11.76, 11.98];
646    /// for (i, e) in expected.iter().enumerate() {
647    ///     assert_approx_eq!(e, results[i], 0.1);
648    /// }
649    ///
650    /// ```
651    fn linreg_intercept(&self) -> Option<T>;
652    /// Returns the angle (in degrees) of the linear regression line
653    ///
654    /// The regression angle converts the slope into degrees, providing a more intuitive
655    /// measure of trend inclination that's bounded between -90 and 90 degrees:
656    ///
657    /// - Offers an easily interpretable measure of trend strength
658    /// - Provides normalized measurement across different scaling contexts
659    /// - Enables clear categorization of trend intensity
660    /// - Simplifies visual representation of directional movement
661    ///
662    /// # Returns
663    ///
664    /// * `Option<T>` - The angle of the regression line in degrees, or `None` if the window is not full
665    ///
666    /// # Examples
667    ///
668    /// ```
669    /// # use ta_statistics::{Statistics, SingleStatistics};
670    /// # use assert_approx_eq::assert_approx_eq;
671    /// let mut stats = Statistics::new(5);
672    /// let mut ddof = false;
673    /// let mut results = vec![];
674    /// let inputs = [10.0, 10.5, 11.2, 10.9, 11.5, 11.9, 12.3, 12.1, 11.8, 12.5];
675    /// inputs.iter().for_each(|i| {
676    ///     stats.next(*i).linreg_angle().map(|v| results.push(v));
677    /// });
678    ///
679    /// let expected: [f64; 6] = [0.3396, 0.3100, 0.3199, 0.3199, 0.0799, 0.0699];
680    /// for (i, e) in expected.iter().enumerate() {
681    ///     assert_approx_eq!(e, results[i], 0.1);
682    /// }
683    ///
684    /// ```
685    fn linreg_angle(&self) -> Option<T>;
686    /// Returns the linear regression value (predicted y) for the last position
687    ///
688    /// This calculation provides the expected value at the current position according to
689    /// the best-fit linear model across the window period:
690    ///
691    /// - Establishes theoretical fair value targets for mean-reversion analysis
692    /// - Projects trend trajectory for momentum-based methodologies
693    /// - Filters cyclical noise to extract underlying directional bias
694    /// - Provides basis for divergence analysis between actual and expected values
695    ///
696    /// # Returns
697    ///
698    /// * `Option<T>` - The predicted value at the current position, or `None` if the window is not full
699    ///
700    /// # Examples
701    ///
702    /// ```
703    /// # use ta_statistics::{Statistics, SingleStatistics};
704    /// # use assert_approx_eq::assert_approx_eq;
705    /// let mut stats = Statistics::new(5);
706    /// let mut ddof = false;
707    /// let mut results = vec![];
708    /// let inputs = [10.0, 10.5, 11.2, 10.9, 11.5, 11.9, 12.3, 12.1, 11.8, 12.5];
709    /// inputs.iter().for_each(|i| {
710    ///     stats.next(*i).linreg().map(|v| results.push(v));
711    /// });
712    ///
713    /// let expected: [f64; 6] = [11.5, 11.82, 12.2, 12.38, 12.08, 12.26];
714    /// for (i, e) in expected.iter().enumerate() {
715    ///     assert_approx_eq!(e, results[i], 0.1);
716    /// }
717    ///
718    /// ```
719    fn linreg(&self) -> Option<T>;
720    /// Returns the current drawdown from peak
721    ///
722    /// Measures the percentage decline from the highest observed value to the current value,
723    /// providing crucial insights for risk management and performance evaluation:
724    ///
725    /// - Enables dynamic adjustment of risk exposure during challenging conditions
726    /// - Facilitates strategy rotation based on relative performance metrics
727    /// - Forms the foundation of capital preservation systems during market stress
728    /// - Identifies potential opportunities for strategic positioning during dislocations
729    ///
730    /// # Returns
731    ///
732    /// * `Option<T>` - The current drawdown from peak, or `None` if the window is not full
733    ///
734    /// # Examples
735    ///
736    /// ```
737    /// # use ta_statistics::{Statistics, SingleStatistics};
738    /// # use assert_approx_eq::assert_approx_eq;
739    /// let mut stats = Statistics::new(3);
740    /// let mut results = vec![];
741    /// let inputs = [100.0, 110.0, 105.0, 115.0, 100.0, 95.0, 105.0, 110.0, 100.0];
742    /// inputs.iter().for_each(|i| {
743    ///     stats.next(*i).drawdown().map(|v| results.push(v));
744    /// });
745    ///
746    /// let expected: [f64; 7] = [0.045, 0.0, 0.13, 0.174, 0.0, 0.0, 0.091];
747    /// for (i, e) in expected.iter().enumerate() {
748    ///     assert_approx_eq!(e, results[i], 0.1);
749    /// }
750    /// ```
751    fn drawdown(&mut self) -> Option<T>;
752    /// Returns the maximum drawdown in the window
753    ///
754    /// Maximum drawdown measures the largest peak-to-trough decline within a time series,
755    /// serving as a foundational metric for risk assessment and strategy evaluation:
756    ///
757    /// - Establishes critical constraints for comprehensive risk management frameworks
758    /// - Provides an objective metric for evaluating strategy viability under stress
759    /// - Informs position sizing parameters to maintain proportional risk exposure
760    /// - Contributes valuable input to market regime classification models
761    ///
762    /// # Returns
763    ///
764    /// * `Option<T>` - The maximum drawdown in the window, or `None` if the window is not full
765    ///
766    /// # Examples
767    ///
768    /// ```
769    /// # use ta_statistics::{Statistics, SingleStatistics};
770    /// # use assert_approx_eq::assert_approx_eq;
771    /// let mut stats = Statistics::new(3);
772    /// let mut results = vec![];
773    /// let inputs = [100.0, 110.0, 105.0, 115.0, 100.0, 95.0, 105.0, 110.0, 100.0];
774    /// inputs.iter().for_each(|i| {
775    ///     stats.next(*i).max_drawdown().map(|v| results.push(v));
776    /// });
777    ///
778    /// let expected: [f64; 7] = [0.045, 0.045, 0.13, 0.174, 0.174, 0.174, 0.174];
779    /// for (i, e) in expected.iter().enumerate() {
780    ///     assert_approx_eq!(e, results[i], 0.1);
781    /// }
782    ///
783    /// ```
784    fn max_drawdown(&mut self) -> Option<T>;
785    /// Returns the difference between the last and first values
786    ///
787    /// This fundamental calculation of absolute change between two points provides
788    /// essential directional and magnitude information for time series analysis:
789    ///
790    /// - Enables momentum measurement for trend strength evaluation
791    /// - Quantifies rate-of-change to optimize timing decisions
792    /// - Serves as a building block for pattern recognition in sequential data
793    /// - Provides critical inputs for calculating hedge ratios and exposure management
794    ///
795    /// # Returns
796    ///
797    /// * `Option<T>` - The difference between values, or `None` if the window is not full
798    ///
799    /// # Examples
800    ///
801    /// ```
802    /// # use ta_statistics::{Statistics, SingleStatistics};
803    /// # use assert_approx_eq::assert_approx_eq;
804    /// let mut stats = Statistics::new(3);
805    /// let mut results = vec![];
806    /// let inputs = [100.0, 102.0, 105.0, 101.0, 98.0];
807    /// inputs.iter().for_each(|i| {
808    ///     stats.next(*i).diff().map(|v| results.push(v));
809    /// });
810    ///
811    /// let expected: [f64; 2] = [1.0, -4.0];
812    /// for (i, e) in expected.iter().enumerate() {
813    ///     assert_approx_eq!(e, results[i], 0.1);
814    /// }
815    ///
816    /// ```
817    fn diff(&self) -> Option<T>;
818    /// Returns the percentage change between the first and last values
819    ///
820    /// Percentage change normalizes absolute changes by the starting value, enabling
821    /// meaningful comparisons across different scales and measurement contexts:
822    ///
823    /// - Facilitates cross-asset performance comparison for relative strength analysis
824    /// - Provides risk-normalized return metrics that account for initial exposure
825    /// - Enables position sizing that properly adjusts for varying volatility environments
826    /// - Serves as a key input for comparative performance evaluation across related groups
827    ///
828    /// # Returns
829    ///
830    /// * `Option<T>` - The percentage change, or `None` if the window is not full
831    ///
832    /// # Examples
833    ///
834    /// ```
835    /// # use ta_statistics::{Statistics, SingleStatistics};
836    /// # use assert_approx_eq::assert_approx_eq;
837    /// let mut stats = Statistics::new(3);
838    /// let mut results = vec![];
839    /// let inputs = [100.0, 105.0, 103.0, 106.0, 110.0, 108.0];
840    /// inputs.iter().for_each(|i| {
841    ///     stats.next(*i).pct_change().map(|v| results.push(v));
842    /// });
843    ///
844    /// let expected: [f64; 3] = [0.06, 0.04761905, 0.04854369];
845    /// for (i, e) in expected.iter().enumerate() {
846    ///     assert_approx_eq!(e, results[i], 0.1);
847    /// }
848    ///
849    /// ```
850    fn pct_change(&self) -> Option<T>;
851    /// Returns the logarithmic return between the first and last values
852    ///
853    /// Logarithmic returns (continuous returns) offer mathematical advantages over simple
854    /// returns, particularly for time series analysis:
855    ///
856    /// - Provides time-additive metrics that can be properly aggregated across periods
857    /// - Normalizes signals in relative-value analysis of related securities
858    /// - Creates a more consistent volatility scale regardless of price levels
859    /// - Improves accuracy in long-horizon analyses through proper handling of compounding
860    ///
861    /// # Returns
862    ///
863    /// * `Option<T>` - The logarithmic return, or `None` if the window is not full
864    ///
865    /// # Examples
866    ///
867    /// ```
868    /// # use ta_statistics::{Statistics, SingleStatistics};
869    /// # use assert_approx_eq::assert_approx_eq;
870    /// let mut stats = Statistics::new(3);
871    /// let mut results = vec![];
872    /// let inputs = [100.0, 105.0, 103.0, 106.0, 110.0, 108.0];
873    /// inputs.iter().for_each(|i| {
874    ///     stats.next(*i).pct_change().map(|v| results.push(v));
875    /// });
876    ///
877    /// let expected: [f64; 3] = [0.05827, 0.04652, 0.04727];
878    /// for (i, e) in expected.iter().enumerate() {
879    ///     assert_approx_eq!(e, results[i], 0.1);
880    /// }
881    ///
882    /// ```
883    fn log_return(&self) -> Option<T>;
884
885    /// Returns the quantile of the values in the window
886    ///
887    /// # Arguments
888    ///
889    /// * `q` - The quantile to calculate
890    ///
891    /// # Returns
892    ///
893    /// * `Option<T>` - The quantile, or `None` if the window is not full
894    ///
895    /// # Examples
896    ///
897    /// ```
898    /// # use ta_statistics::{Statistics, SingleStatistics};
899    /// # use assert_approx_eq::assert_approx_eq;
900    /// let mut stats = Statistics::new(3);
901    /// let mut results = vec![];
902    /// let inputs = [10.0, 20.0, 30.0, 40.0, 50.0];
903    /// inputs.iter().for_each(|i| {
904    ///     stats.next(*i).quantile(0.5).map(|v| results.push(v));
905    /// });
906    ///
907    /// let expected: [f64; 3] = [20.0, 30.0, 40.0];
908    /// for (i, e) in expected.iter().enumerate() {
909    ///     assert_approx_eq!(e, results[i], 0.1);
910    /// }
911    /// ```
912    fn quantile(&mut self, q: f64) -> Option<T>;
913
914    /// Returns the interquartile range of the values in the window
915    ///
916    /// # Returns
917    ///
918    /// * `Option<T>` - The interquartile range, or `None` if the window is not full
919    ///
920    /// # Examples
921    ///
922    /// ```
923    /// # use ta_statistics::{Statistics, SingleStatistics};
924    /// # use assert_approx_eq::assert_approx_eq;
925    /// let mut stats = Statistics::new(3);
926    /// let mut results = vec![];
927    /// let inputs = [10.0, 20.0, 30.0, 40.0, 50.0];
928    /// inputs.iter().for_each(|i| {
929    ///     stats.next(*i).iqr().map(|v| results.push(v));
930    /// });
931    ///
932    /// let expected: [f64; 3] = [10.0, 10.0, 10.0];
933    /// for (i, e) in expected.iter().enumerate() {
934    ///     assert_approx_eq!(e, results[i], 0.1);
935    /// }
936    ///
937    /// ```
938    fn iqr(&mut self) -> Option<T>;
939}