velora_ta/
errors.rs

1//! Error types for technical indicators.
2
3use std::fmt;
4
5/// Result type for indicator operations.
6pub type IndicatorResult<T> = Result<T, IndicatorError>;
7
8/// Errors that can occur during indicator calculations.
9#[derive(Debug, Clone, PartialEq)]
10pub enum IndicatorError {
11    /// Insufficient data to calculate the indicator.
12    ///
13    /// Most indicators require a minimum number of data points (warmup period)
14    /// before they can produce valid output.
15    InsufficientData {
16        /// Minimum required data points
17        required: usize,
18        /// Actual number of data points available
19        actual: usize,
20    },
21
22    /// Invalid parameter provided to indicator constructor.
23    ///
24    /// For example, a period of 0 or a negative standard deviation.
25    InvalidParameter(String),
26
27    /// Error during calculation.
28    ///
29    /// This can occur due to numerical issues like division by zero,
30    /// overflow, or invalid mathematical operations.
31    Calculation(String),
32
33    /// Indicator not properly initialized.
34    ///
35    /// This error occurs when trying to use an indicator before it's ready.
36    NotInitialized(String),
37
38    /// Invalid price data.
39    ///
40    /// Prices cannot be negative or NaN.
41    InvalidPrice(String),
42
43    /// Invalid input data.
44    ///
45    /// General validation error for input data.
46    InvalidInput(String),
47
48    /// Division by zero encountered.
49    DivisionByZero,
50}
51
52impl fmt::Display for IndicatorError {
53    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54        match self {
55            IndicatorError::InsufficientData { required, actual } => {
56                write!(
57                    f,
58                    "Insufficient data: need at least {required} data points, got {actual}"
59                )
60            }
61            IndicatorError::InvalidParameter(msg) => write!(f, "Invalid parameter: {msg}"),
62            IndicatorError::Calculation(msg) => write!(f, "Calculation error: {msg}"),
63            IndicatorError::NotInitialized(msg) => write!(f, "Not initialized: {msg}"),
64            IndicatorError::InvalidPrice(msg) => write!(f, "Invalid price: {msg}"),
65            IndicatorError::InvalidInput(msg) => write!(f, "Invalid input: {msg}"),
66            IndicatorError::DivisionByZero => write!(f, "Division by zero"),
67        }
68    }
69}
70
71impl std::error::Error for IndicatorError {}
72
73#[cfg(test)]
74mod tests {
75    use super::*;
76
77    #[test]
78    fn test_error_display() {
79        let err = IndicatorError::InsufficientData {
80            required: 20,
81            actual: 10,
82        };
83        assert_eq!(
84            err.to_string(),
85            "Insufficient data: need at least 20 data points, got 10"
86        );
87
88        let err = IndicatorError::InvalidParameter("period must be > 0".to_string());
89        assert_eq!(err.to_string(), "Invalid parameter: period must be > 0");
90
91        let err = IndicatorError::DivisionByZero;
92        assert_eq!(err.to_string(), "Division by zero");
93    }
94}