use std::fmt;
use std::ops::{Add, Div, Mul};
use rust_decimal::prelude::*;
pub struct SqrtPrice {
pub fixed_point: u128,
}
impl SqrtPrice {
pub fn new(sqrt_price: u128) -> SqrtPrice {
SqrtPrice {
fixed_point: sqrt_price,
}
}
pub fn from(price: Decimal, base_decimal: u8, quote_decimal: u8) -> SqrtPrice {
let exp = quote_decimal as i32 - base_decimal as i32;
let multi = Decimal::from_f64(10f64.powi(exp)).unwrap();
let sqrt_price = multi.mul(price).sqrt().unwrap();
SqrtPrice {
fixed_point: sqrt_price
.mul(Decimal::from_u64(u64::MAX).unwrap())
.to_u128()
.unwrap(),
}
}
pub fn to_decimal(&self) -> Decimal {
let integer = Decimal::from_i128_with_scale((self.fixed_point >> 64) as i128, 0);
Decimal::from_i128_with_scale((self.fixed_point & (u64::MAX as u128)) as i128, 0)
.div(Decimal::from_i128_with_scale(u64::MAX as i128, 0))
.add(integer)
}
pub fn to_ui_price(&self) -> Decimal {
let d = self.to_decimal();
d.mul(d)
}
}
impl fmt::Display for SqrtPrice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = self.to_decimal().round_dp(12).to_string();
write!(f, "{}", s)
}
}
#[cfg(test)]
mod sqrt_price {
use crate::utils::sqrt_price::*;
use rust_decimal::Decimal;
#[test]
fn test_from() {
assert_eq!(
SqrtPrice::from(Decimal::from_f64(1f64).unwrap(), 6, 6).fixed_point,
u64::MAX as u128
);
let sp1 = SqrtPrice::from(Decimal::from_f64(1f64).unwrap(), 6, 9);
println!("{} {}", sp1, sp1.fixed_point);
}
}