Construct imbalance bars by accumulating signed imbalance (tick, volume, or dollar) until the absolute imbalance crosses `threshold`. Trailing partial bars that have not met the threshold are dropped.
(
trades: &[Trade],
threshold: f64,
bar_type: ImbalanceBarType,
)
| 164 | /// Construct time bars using a fixed interval. The interval applies from the start |
| 165 | /// timestamp of the current bar; the trade that crosses the interval boundary is |
| 166 | /// included in the closing bar, and accumulation restarts afterward. Any trailing partial bar |
| 167 | /// is emitted as a final, shorter bar. An empty slice yields no bars. |
| 168 | /// |
| 169 | /// # Errors |
| 170 | /// |
| 171 | /// [`InputError::OutOfRange`] if `interval` is zero or negative. |
| 172 | pub fn time_bars(trades: &[Trade], interval: Duration) -> Result<Vec<StandardBar>, InputError> { |
| 173 | if interval <= Duration::zero() { |
| 174 | return Err(InputError::OutOfRange { |
| 175 | name: "interval", |
| 176 | value: interval.num_milliseconds() as f64 / 1e3, |
| 177 | expected: "a positive duration (seconds)", |
| 178 | }); |
| 179 | } |
| 180 | |
| 181 | let mut bars = Vec::new(); |
| 182 | if trades.is_empty() { |
| 183 | return Ok(bars); |
| 184 | } |
| 185 | |
| 186 | let mut start_idx = 0; |
| 187 | let mut bar_start = trades[0].timestamp; |
| 188 | |
| 189 | for (i, trade) in trades.iter().enumerate() { |
| 190 | let elapsed = trade.timestamp - bar_start; |
| 191 | if elapsed >= interval { |
| 192 | bars.push(build_bar(&trades[start_idx..=i])); |
| 193 | start_idx = i + 1; |
| 194 | if start_idx < trades.len() { |
| 195 | bar_start = trades[start_idx].timestamp; |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | if start_idx < trades.len() { |
| 201 | bars.push(build_bar(&trades[start_idx..])); |
| 202 | } |
| 203 | |
| 204 | Ok(bars) |
| 205 | } |
| 206 | |
| 207 | /// Construct run bars by counting consecutive price-direction runs. A bar closes when |
| 208 | /// `threshold` consecutive moves occur in the same direction. Trailing partial bars |
| 209 | /// that have not met the threshold are dropped. Direction follows the tick rule, so a trade at |
| 210 | /// an unchanged price extends the current run. Fewer than two trades yield no bars. |
| 211 | /// |