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