use crate::SymInfo;
#[derive(Debug, Clone, Default)]
pub struct Bar {
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
pub index: u64,
pub time: i64,
pub is_first: bool,
pub is_last: bool,
pub is_new: bool,
pub is_confirmed: bool,
pub is_history: bool,
pub is_realtime: bool,
pub is_last_confirmed_history: bool,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Ohlcv {
pub time: i64,
pub open: f64,
pub high: f64,
pub low: f64,
pub close: f64,
pub volume: f64,
}
#[derive(Debug, Clone, Default)]
pub struct Data {
pub syminfo: SymInfo,
pub bars: Vec<Bar>,
}
impl Data {
pub fn new(bars: Vec<Bar>) -> Self {
Self {
syminfo: SymInfo::default(),
bars,
}
}
pub fn from_ohlcv(rows: impl IntoIterator<Item = Ohlcv>) -> Self {
let rows: Vec<Ohlcv> = rows.into_iter().collect();
let last = rows.len().saturating_sub(1);
let bars = rows
.into_iter()
.enumerate()
.map(|(index, row)| Bar {
open: row.open,
high: row.high,
low: row.low,
close: row.close,
volume: row.volume,
index: index as u64,
time: row.time,
is_first: index == 0,
is_last: index == last,
is_new: true,
is_confirmed: true,
is_history: true,
is_realtime: false,
is_last_confirmed_history: index == last,
})
.collect();
Self { ..Self::new(bars) }
}
pub fn with_syminfo(mut self, syminfo: SymInfo) -> Self {
self.syminfo = syminfo;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
fn row(time: i64) -> Ohlcv {
Ohlcv {
time,
open: 1.0,
high: 2.0,
low: 0.5,
close: 1.5,
volume: 10.0,
}
}
#[test]
fn flags_mark_the_ends_of_the_series() {
let data = Data::from_ohlcv([row(0), row(1), row(2)]);
assert_eq!(data.bars.len(), 3);
assert!(data.bars[0].is_first && !data.bars[0].is_last);
assert!(!data.bars[1].is_first && !data.bars[1].is_last);
assert!(!data.bars[2].is_first && data.bars[2].is_last);
assert_eq!(data.bars[2].index, 2);
assert!(data
.bars
.iter()
.all(|bar| bar.is_history && bar.is_confirmed));
}
#[test]
fn a_single_bar_is_both_ends() {
let data = Data::from_ohlcv([row(0)]);
assert!(data.bars[0].is_first && data.bars[0].is_last);
}
#[test]
fn an_empty_series_has_no_bars() {
assert!(Data::from_ohlcv([]).bars.is_empty());
}
}