(
returns: &[(NaiveDateTime, f64)],
)
| 89 | } |
| 90 | |
| 91 | pub fn all_bets_concentration( |
| 92 | returns: &[(NaiveDateTime, f64)], |
| 93 | ) -> (Option<f64>, Option<f64>, Option<f64>) { |
| 94 | let positives: Vec<f64> = returns.iter().filter(|(_, r)| *r >= 0.0).map(|(_, r)| *r).collect(); |
| 95 | let negatives: Vec<f64> = returns.iter().filter(|(_, r)| *r < 0.0).map(|(_, r)| *r).collect(); |
| 96 | let pos = bets_concentration(&positives); |
| 97 | let neg = bets_concentration(&negatives); |
| 98 | // time grouping by day including gaps between first and last date (zeros matter) |
| 99 | let mut per_day: std::collections::HashMap<chrono::NaiveDate, usize> = |
| 100 | std::collections::HashMap::new(); |
| 101 | for (ts, _) in returns { |
| 102 | *per_day.entry(ts.date()).or_insert(0) += 1; |
| 103 | } |
| 104 | let time = if returns.is_empty() { |
| 105 | None |
| 106 | } else { |
| 107 | let start = returns.first().unwrap().0.date(); |
| 108 | let end = returns.last().unwrap().0.date(); |
| 109 | let mut counts: Vec<f64> = Vec::new(); |
| 110 | let mut day = start; |
| 111 | while day <= end { |
| 112 | let cnt = per_day.get(&day).copied().unwrap_or(0) as f64; |
| 113 | counts.push(cnt); |
| 114 | day = day.succ_opt().unwrap(); |
| 115 | } |
| 116 | bets_concentration(&counts) |
| 117 | }; |
| 118 | (pos, neg, time) |
| 119 | } |
| 120 | |
| 121 | pub fn drawdown_and_time_under_water( |
| 122 | returns: &[(NaiveDateTime, f64)], |
no test coverage detected