use std::ops::Add;
use rust_decimal::Decimal;
use crate::instrument::{AsDecimal, InstrumentSpec};
use super::{AggressorSide, DirectionalIntentVolume, DirectionlessVolume, RestingSide};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum VolumeDelta<IS: InstrumentSpec> {
Zero,
AggressiveDelta {
directionless_volume: DirectionlessVolume<IS>,
aggressor_side: AggressorSide,
},
RestingDelta {
directionless_volume: DirectionlessVolume<IS>,
resting_side: RestingSide,
},
}
impl<IS: InstrumentSpec> AsDecimal<IS::VolumeSpec> for VolumeDelta<IS> {
fn as_decimal(&self) -> Decimal {
match self {
Self::Zero => Decimal::ZERO,
Self::AggressiveDelta {
directionless_volume,
aggressor_side,
} => {
directionless_volume.as_decimal()
* aggressor_side
.as_directional_intent()
.as_decimal()
}
Self::RestingDelta {
directionless_volume,
resting_side,
} => {
directionless_volume.as_decimal()
* resting_side
.as_directional_intent()
.as_decimal()
}
}
}
}
impl<IS: InstrumentSpec> Add for VolumeDelta<IS> {
type Output = Option<DirectionalIntentVolume<IS>>;
fn add(
self,
rhs: Self,
) -> Self::Output {
let self_directional_intent_volume: Option<DirectionalIntentVolume<IS>> = match self {
Self::Zero => None,
Self::AggressiveDelta {
directionless_volume,
aggressor_side,
} => Some(
aggressor_side
.as_directional_intent()
.with_volume(directionless_volume),
),
Self::RestingDelta {
directionless_volume,
resting_side,
} => Some(
resting_side
.as_directional_intent()
.with_volume(directionless_volume),
),
};
let rhs_directional_intent_volume: Option<DirectionalIntentVolume<IS>> = match rhs {
Self::Zero => None,
Self::AggressiveDelta {
directionless_volume: volume_t,
aggressor_side,
} => Some(
aggressor_side
.as_directional_intent()
.with_volume(volume_t),
),
Self::RestingDelta {
directionless_volume,
resting_side,
} => Some(
resting_side
.as_directional_intent()
.with_volume(directionless_volume),
),
};
match (
self_directional_intent_volume,
rhs_directional_intent_volume,
) {
(None, None) => None,
(Some(self_directional_intent_volume), None) => Some(self_directional_intent_volume),
(None, Some(rhs_directional_intent_volume)) => Some(rhs_directional_intent_volume),
(Some(self_directional_intent_volume), Some(rhs_directional_intent_volume)) => {
self_directional_intent_volume + rhs_directional_intent_volume
}
}
}
}