use super::*;
use rust_decimal_macros::dec;
#[test]
fn sharpe_positive_returns() {
let equity = vec![
dec!(100),
dec!(101),
dec!(102),
dec!(103),
dec!(104),
dec!(105),
];
let sharpe = sharpe_ratio(&equity, dec!(0.02), 252).expect("sharpe with positive returns");
assert!(sharpe > dec!(0));
}
#[test]
fn sharpe_volatile_returns() {
let stable = vec![dec!(100), dec!(101), dec!(102), dec!(103), dec!(104)];
let volatile = vec![dec!(100), dec!(105), dec!(98), dec!(108), dec!(104)];
let sharpe_stable = sharpe_ratio(&stable, dec!(0.02), 252).expect("sharpe for stable returns");
let sharpe_volatile =
sharpe_ratio(&volatile, dec!(0.02), 252).expect("sharpe for volatile returns");
assert!(sharpe_stable > sharpe_volatile);
}
#[test]
fn sharpe_insufficient_data() {
let equity = vec![dec!(100), dec!(101)];
assert_eq!(
sharpe_ratio(&equity, dec!(0.02), 252),
Err(MetricsError::InsufficientData {
required: 3,
actual: 2
})
);
}
#[test]
fn sortino_better_than_sharpe_for_upside_vol() {
let equity = vec![
dec!(100),
dec!(102), dec!(101), dec!(108), dec!(107), dec!(115), ];
let sharpe = sharpe_ratio(&equity, dec!(0.02), 252).expect("sharpe for upside-vol equity");
let sortino = sortino_ratio(&equity, dec!(0.02), 252).expect("sortino for upside-vol equity");
assert!(sortino > sharpe);
}
#[test]
fn calmar_positive() {
let equity = vec![dec!(100), dec!(110), dec!(95), dec!(120)];
let calmar = calmar_ratio(&equity, 252).expect("calmar with drawdown");
assert!(calmar > dec!(0));
}
#[test]
fn calmar_no_drawdown() {
let equity = vec![dec!(100), dec!(110), dec!(120)];
assert_eq!(
calmar_ratio(&equity, 252),
Err(MetricsError::DivisionByZero {
context: "zero max drawdown"
})
);
}
#[test]
fn period_returns_calculation() {
let equity = vec![dec!(100), dec!(110), dec!(99)];
let returns = period_returns(&equity);
assert_eq!(returns.len(), 2);
assert_eq!(returns[0], dec!(0.10)); assert_eq!(returns[1], dec!(-0.10)); }
#[test]
fn information_ratio_outperformance() {
let portfolio = vec![dec!(100), dec!(110), dec!(121), dec!(133)];
let benchmark = vec![dec!(100), dec!(105), dec!(110), dec!(115)];
let ir =
information_ratio(&portfolio, &benchmark, 252).expect("IR for outperforming portfolio");
assert!(ir > dec!(0)); }
#[test]
fn information_ratio_underperformance() {
let portfolio = vec![dec!(100), dec!(105), dec!(110), dec!(115)];
let benchmark = vec![dec!(100), dec!(110), dec!(121), dec!(133)];
let ir =
information_ratio(&portfolio, &benchmark, 252).expect("IR for underperforming portfolio");
assert!(ir < dec!(0)); }
#[test]
fn information_ratio_length_mismatch() {
let portfolio = vec![dec!(100), dec!(110), dec!(121)];
let benchmark = vec![dec!(100), dec!(105)];
assert!(matches!(
information_ratio(&portfolio, &benchmark, 252),
Err(MetricsError::InvalidParameter(_))
));
}