quantwave_core/indicators/
robustness.rs1#[derive(Debug, Clone, Default)]
9pub struct RobustnessEvaluator {
10 profits: Vec<f64>,
11}
12
13impl RobustnessEvaluator {
14 pub fn new() -> Self {
15 Self {
16 profits: Vec::new(),
17 }
18 }
19
20 pub fn add_test_result(&mut self, net_profit: f64) {
21 self.profits.push(net_profit);
22 }
23
24 pub fn calculate_score(&self) -> f64 {
25 if self.profits.is_empty() {
26 return 0.0;
27 }
28
29 let mut sorted = self.profits.clone();
30 sorted.sort_by(|a, b| b.partial_cmp(a).unwrap_or(std::cmp::Ordering::Equal));
32
33 let max_profit = sorted[0];
34 if max_profit <= 0.0 {
35 return 0.0;
36 }
37
38 let midpoint = sorted.len() / 2;
39 sorted[midpoint] / max_profit
40 }
41}
42
43pub fn calculate_robustness(net_profits: &[f64]) -> f64 {
44 let mut evaluator = RobustnessEvaluator::new();
45 for &p in net_profits {
46 evaluator.add_test_result(p);
47 }
48 evaluator.calculate_score()
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_robustness_basic() {
57 let profits = vec![100.0, 90.0, 80.0, 70.0, 60.0];
58 assert_eq!(calculate_robustness(&profits), 0.8);
61 }
62
63 #[test]
64 fn test_robustness_empty() {
65 assert_eq!(calculate_robustness(&[]), 0.0);
66 }
67
68 #[test]
69 fn test_robustness_negative() {
70 let profits = vec![-10.0, -20.0];
71 assert_eq!(calculate_robustness(&profits), 0.0);
72 }
73}