finance_query/backtesting/
error.rs1use thiserror::Error;
4
5#[derive(Debug, Error)]
7#[non_exhaustive]
8pub enum BacktestError {
9 #[error("Invalid parameter '{param}': {reason}")]
11 InvalidParameter {
12 param: String,
14 reason: String,
16 },
17
18 #[error("Insufficient data: need at least {need} candles, got {got}")]
20 InsufficientData {
21 need: usize,
23 got: usize,
25 },
26
27 #[error("Strategy error: {0}")]
29 StrategyError(String),
30
31 #[error("Indicator calculation failed: {0}")]
33 IndicatorError(#[from] crate::indicators::IndicatorError),
34
35 #[error("Failed to fetch chart data: {0}")]
37 ChartError(String),
38
39 #[error("Position error: {0}")]
41 PositionError(String),
42}
43
44pub type Result<T> = std::result::Result<T, BacktestError>;
46
47impl BacktestError {
48 pub fn invalid_param(param: impl Into<String>, reason: impl Into<String>) -> Self {
50 Self::InvalidParameter {
51 param: param.into(),
52 reason: reason.into(),
53 }
54 }
55
56 pub fn insufficient_data(need: usize, got: usize) -> Self {
58 Self::InsufficientData { need, got }
59 }
60
61 pub fn strategy(msg: impl Into<String>) -> Self {
63 Self::StrategyError(msg.into())
64 }
65
66 pub fn chart(msg: impl Into<String>) -> Self {
68 Self::ChartError(msg.into())
69 }
70
71 pub fn position(msg: impl Into<String>) -> Self {
73 Self::PositionError(msg.into())
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn test_invalid_param_error() {
83 let err = BacktestError::invalid_param("capital", "must be positive");
84 assert!(err.to_string().contains("capital"));
85 assert!(err.to_string().contains("must be positive"));
86 }
87
88 #[test]
89 fn test_insufficient_data_error() {
90 let err = BacktestError::insufficient_data(50, 10);
91 assert!(err.to_string().contains("50"));
92 assert!(err.to_string().contains("10"));
93 }
94}