use rust_decimal::Decimal;
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
pub struct Tick {
level: Decimal, tick_size: Decimal, }
impl Tick {
pub fn new(price: Decimal, tick_size: Decimal) -> eyre::Result<Self> {
if price <= Decimal::ZERO {
return Err(eyre::eyre!("Price must be positive"));
}
if tick_size <= Decimal::ZERO {
return Err(eyre::eyre!("Tick size must be positive"));
}
let normalized = Self::normalize(price, tick_size);
Ok(Self {
level: normalized,
tick_size,
})
}
fn normalize(price: Decimal, tick_size: Decimal) -> Decimal {
(price / tick_size).round() * tick_size
}
pub fn level(&self) -> Decimal {
self.level
}
}
#[cfg(test)]
mod tests {
use super::*;
use rust_decimal_macros::dec;
#[test]
fn test_tick_normalization() {
let tick_size = dec!(0.01);
assert_eq!(
Tick::new(dec!(10.012), tick_size)
.expect("invalid tick")
.level(),
dec!(10.01)
);
assert_eq!(
Tick::new(dec!(10.017), tick_size)
.expect("invalid tick")
.level(),
dec!(10.02)
);
assert_eq!(
Tick::new(dec!(10.02), tick_size)
.expect("invalid tick")
.level(),
dec!(10.02)
);
}
}