//! Custom assertions for domain-specific testing /// Assert that a value is within a percentage tolerance #[macro_export] macro_rules! assert_approx_eq { ($left:expr, $right:expr, $tolerance:expr) => { let diff = ($left - $right).abs(); let threshold = $right.abs() * $tolerance; assert!( diff <= threshold, "assertion failed: `{} ≈ {}` (tolerance: {}%)\n left: {}\n right: {}\n diff: {} > {}", stringify!($left), stringify!($right), $tolerance * 100.0, $left, $right, diff, threshold ); }; } /// Assert that a value is within an absolute tolerance #[macro_export] macro_rules! assert_within { ($value:expr, $target:expr, $tolerance:expr) => { let diff = ($value - $target).abs(); assert!( diff <= $tolerance, "assertion failed: `{} within {} of {}`\n value: {}\n target: {}\n diff: {}", stringify!($value), $tolerance, stringify!($target), $value, $target, diff ); }; } /// Assert that VaR exceedances are within expected range pub fn assert_var_exceedances( returns: &[f64], var: f64, confidence: f64, max_deviation: f64, ) { let exceedances = returns.iter().filter(|&&r| r.abs() > var).count(); let expected_exceedances = (returns.len() as f64 * (1.0 - confidence)) as usize; let max_allowed = (expected_exceedances as f64 * (1.0 + max_deviation)) as usize; assert!( exceedances <= max_allowed, "VaR exceedances {} exceed maximum {} (expected: {}, confidence: {}, tolerance: {}%)", exceedances, max_allowed, expected_exceedances, confidence, max_deviation * 100.0 ); } /// Assert that OHLC relationships are valid pub fn assert_ohlc_valid(open: f64, high: f64, low: f64, close: f64) { assert!( high >= open, "High {} must be >= Open {}", high, open ); assert!( high >= close, "High {} must be >= Close {}", high, close ); assert!( low <= open, "Low {} must be <= Open {}", low, open ); assert!( low <= close, "Low {} must be <= Close {}", low, close ); } /// Assert that a position's PnL is correct pub fn assert_pnl( entry_price: f64, current_price: f64, quantity: f64, expected_pnl: f64, tolerance: f64, ) { let actual_pnl = (current_price - entry_price) * quantity; assert_within!(actual_pnl, expected_pnl, tolerance); } #[cfg(test)] mod tests { use super::*; #[test] fn test_assert_approx_eq() { assert_approx_eq!(100.0, 101.0, 0.02); // 2% tolerance } #[test] #[should_panic] fn test_assert_approx_eq_fails() { assert_approx_eq!(100.0, 105.0, 0.02); // Should fail } #[test] fn test_assert_within() { assert_within!(100.5, 100.0, 0.6); } #[test] fn test_assert_ohlc_valid() { assert_ohlc_valid(100.0, 102.0, 98.0, 101.0); } #[test] #[should_panic] fn test_assert_ohlc_invalid() { assert_ohlc_valid(100.0, 98.0, 99.0, 101.0); // High < Open } #[test] fn test_assert_pnl() { assert_pnl(100.0, 110.0, 50.0, 500.0, 0.01); } }