convex_bonds/
error.rs

1//! Error types for bond operations.
2
3use thiserror::Error;
4
5/// A specialized Result type for bond operations.
6pub type BondResult<T> = Result<T, BondError>;
7
8/// Errors that can occur during identifier validation.
9#[derive(Error, Debug, Clone, PartialEq, Eq)]
10pub enum IdentifierError {
11    /// Invalid length for identifier.
12    #[error("Invalid {id_type} length: expected {expected}, got {actual}")]
13    InvalidLength {
14        /// Type of identifier (CUSIP, ISIN, etc.).
15        id_type: &'static str,
16        /// Expected length.
17        expected: usize,
18        /// Actual length.
19        actual: usize,
20    },
21
22    /// Invalid check digit.
23    #[error("Invalid {id_type} check digit for '{value}'")]
24    InvalidCheckDigit {
25        /// Type of identifier.
26        id_type: &'static str,
27        /// The invalid value.
28        value: String,
29    },
30
31    /// Invalid character in identifier.
32    #[error("Invalid character '{ch}' at position {position} in {id_type}")]
33    InvalidCharacter {
34        /// Type of identifier.
35        id_type: &'static str,
36        /// The invalid character.
37        ch: char,
38        /// Position in the string.
39        position: usize,
40    },
41
42    /// Invalid format.
43    #[error("Invalid {id_type} format: {reason}")]
44    InvalidFormat {
45        /// Type of identifier.
46        id_type: &'static str,
47        /// Reason for invalidity.
48        reason: String,
49    },
50}
51
52/// Errors that can occur during bond operations.
53#[derive(Error, Debug, Clone)]
54pub enum BondError {
55    /// Invalid bond specification.
56    #[error("Invalid bond specification: {reason}")]
57    InvalidSpec {
58        /// Description of what's invalid.
59        reason: String,
60    },
61
62    /// Missing required field.
63    #[error("Missing required field: {field}")]
64    MissingField {
65        /// The missing field name.
66        field: String,
67    },
68
69    /// Pricing calculation failed.
70    #[error("Pricing failed: {reason}")]
71    PricingFailed {
72        /// Description of the failure.
73        reason: String,
74    },
75
76    /// Yield calculation failed to converge.
77    #[error("Yield calculation failed to converge after {iterations} iterations")]
78    YieldConvergenceFailed {
79        /// Number of iterations attempted.
80        iterations: u32,
81    },
82
83    /// Invalid price.
84    #[error("Invalid price: {reason}")]
85    InvalidPrice {
86        /// Description of what's invalid.
87        reason: String,
88    },
89
90    /// Cash flow generation failed.
91    #[error("Cash flow generation failed: {reason}")]
92    CashFlowFailed {
93        /// Description of the failure.
94        reason: String,
95    },
96
97    /// Settlement date is after maturity.
98    #[error("Settlement date {settlement} is after maturity {maturity}")]
99    SettlementAfterMaturity {
100        /// Settlement date.
101        settlement: String,
102        /// Maturity date.
103        maturity: String,
104    },
105
106    /// Invalid schedule configuration.
107    #[error("Invalid schedule: {message}")]
108    InvalidSchedule {
109        /// Description of the schedule error.
110        message: String,
111    },
112
113    /// Core library error.
114    #[error("Core error: {0}")]
115    CoreError(#[from] convex_core::ConvexError),
116
117    /// Curve error.
118    #[error("Curve error: {0}")]
119    CurveError(#[from] convex_curves::CurveError),
120}
121
122impl BondError {
123    /// Creates an invalid specification error.
124    #[must_use]
125    pub fn invalid_spec(reason: impl Into<String>) -> Self {
126        Self::InvalidSpec {
127            reason: reason.into(),
128        }
129    }
130
131    /// Creates a missing field error.
132    #[must_use]
133    pub fn missing_field(field: impl Into<String>) -> Self {
134        Self::MissingField {
135            field: field.into(),
136        }
137    }
138
139    /// Creates a pricing failed error.
140    #[must_use]
141    pub fn pricing_failed(reason: impl Into<String>) -> Self {
142        Self::PricingFailed {
143            reason: reason.into(),
144        }
145    }
146}