use std::{
ops::{Add, Deref, Sub},
fmt::Display,
};
use rust_decimal::Decimal;
use crate::instrument::{AddDecimal, AsDecimal, InstrumentSpec, SubDecimal};
use super::{ProtoabsolutePrice, RelativePrice};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct AbsolutePrice<IS: InstrumentSpec>(IS::PriceType);
impl<IS: InstrumentSpec> AbsolutePrice<IS> {
pub fn new(
price: IS::PriceType,
) -> Self {
Self(price)
}
pub fn as_protoabsolute_price(
&self,
) -> ProtoabsolutePrice<IS> {
self.into()
}
pub fn into_protoabsolute_price(
self,
) -> ProtoabsolutePrice<IS> {
self.into()
}
pub fn as_decimal(
&self,
) -> Decimal {
self.0.as_decimal()
}
pub fn as_underlying(
&self,
) -> IS::PriceType {
self.0
}
}
impl<IS: InstrumentSpec> Deref for AbsolutePrice<IS> {
type Target = IS::PriceType;
fn deref(
&self,
) -> &Self::Target {
&self.0
}
}
impl<IS: InstrumentSpec> Display for AbsolutePrice<IS> {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
let price = self.as_decimal();
write!(f, "{}", price)
}
}
impl<IS: InstrumentSpec> std::fmt::Debug for AbsolutePrice<IS> {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result {
<Self as Display>::fmt(&self, f)
}
}
impl<IS: InstrumentSpec> Add<RelativePrice> for AbsolutePrice<IS> {
type Output = Self;
fn add(
mut self,
rhs: RelativePrice,
) -> Self::Output {
let price_type: IS::PriceType = rhs.into_subpoints().into();
self.0 += price_type;
self
}
}
impl<IS: InstrumentSpec> Add<&RelativePrice> for AbsolutePrice<IS> {
type Output = Self;
fn add(
self,
rhs: &RelativePrice,
) -> Self::Output {
self + *rhs
}
}
impl<IS: InstrumentSpec> Sub<RelativePrice> for AbsolutePrice<IS> {
type Output = Self;
fn sub(
mut self,
rhs: RelativePrice,
) -> Self::Output {
let price_type: IS::PriceType = rhs.into_subpoints().into();
self.0 -= price_type;
self
}
}
impl<IS: InstrumentSpec> Sub<&RelativePrice> for AbsolutePrice<IS> {
type Output = Self;
fn sub(
self,
rhs: &RelativePrice,
) -> Self::Output {
self - *rhs
}
}
impl<IS: InstrumentSpec> AddDecimal for AbsolutePrice<IS> {
fn add_decimal(
&mut self,
decimal: &Decimal,
) {
self.0.add_decimal(decimal);
}
}
impl<IS: InstrumentSpec> SubDecimal for AbsolutePrice<IS> {
fn sub_decimal(
&mut self,
decimal: &Decimal,
) {
self.0.sub_decimal(decimal);
}
}
impl<IS: InstrumentSpec> From<ProtoabsolutePrice<IS>> for Option<AbsolutePrice<IS>> {
fn from(
value: ProtoabsolutePrice<IS>,
) -> Self {
let ProtoabsolutePrice::Absolute(
absolute_price,
) = value else {
return None;
};
Some(absolute_price)
}
}
impl<
'a,
IS: InstrumentSpec,
> From<&'a ProtoabsolutePrice<IS>> for Option<&'a AbsolutePrice<IS>> {
fn from(
value: &'a ProtoabsolutePrice<IS>,
) -> Self {
let ProtoabsolutePrice::Absolute(
absolute_price,
) = value else {
return None;
};
Some(absolute_price)
}
}