use rust_decimal::Decimal;
use rust_decimal::prelude::*;
pub fn tick_to_price(tick: i32) -> Result<Decimal, &'static str> {
let base = 1.0001f64;
let price_f64 = base.powi(tick);
Decimal::from_f64(price_f64).ok_or("Overflow converting price")
}
pub fn price_to_tick(price: Decimal) -> Result<i32, &'static str> {
if price <= Decimal::ZERO {
return Err("Price must be positive");
}
let price_f64 = price.to_f64().ok_or("Overflow converting price")?;
let base = 1.0001f64;
let tick = price_f64.log(base);
Ok(tick.round() as i32)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_tick_to_price() {
let p = tick_to_price(0).unwrap();
assert_eq!(p, Decimal::from(1));
let p100 = tick_to_price(100).unwrap();
let expected = 1.01004966;
let diff = (p100.to_f64().unwrap() - expected).abs();
assert!(diff < 0.000001);
}
#[test]
fn test_price_to_tick() {
let t = price_to_tick(Decimal::from(1)).unwrap();
assert_eq!(t, 0);
let t2 = price_to_tick(Decimal::from_f64(1.01004966).unwrap()).unwrap();
assert_eq!(t2, 100);
}
}