(trades: &[Trade])
| 208 | } |
| 209 | |
| 210 | fn build_bar(trades: &[Trade]) -> StandardBar { |
| 211 | assert!(!trades.is_empty(), "cannot build a bar from an empty trade slice"); |
| 212 | |
| 213 | let open = trades.first().expect("non-empty slice").price; |
| 214 | let close = trades.last().expect("non-empty slice").price; |
| 215 | let start_timestamp = trades.first().expect("non-empty slice").timestamp; |
| 216 | let timestamp = trades.last().expect("non-empty slice").timestamp; |
| 217 | let (high, low) = trades.iter().fold((f64::NEG_INFINITY, f64::INFINITY), |(h, l), trade| { |
| 218 | (h.max(trade.price), l.min(trade.price)) |
| 219 | }); |
| 220 | let (volume, dollar_value) = trades.iter().fold((0.0, 0.0), |(v, d), trade| { |
| 221 | let next_v = v + trade.volume; |
| 222 | let next_d = d + trade.price * trade.volume; |
| 223 | (next_v, next_d) |
| 224 | }); |
| 225 | |
| 226 | StandardBar { |
| 227 | start_timestamp, |
| 228 | timestamp, |
| 229 | open, |
| 230 | high, |
| 231 | low, |
| 232 | close, |
| 233 | volume, |
| 234 | dollar_value, |
| 235 | tick_count: trades.len(), |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | fn trade_sign(price: f64, prev_price: f64, prev_sign: i8) -> i8 { |
| 240 | if price > prev_price { |
no test coverage detected