apple-quant-algorithmic 0.1.0

Apple Quant's algorithmic trading api
Documentation
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
			}
		}
	}
}