Skip to main content

apple_quant_algorithmic/volume/
directionless.rs

1use std::ops::{Add, AddAssign, Sub};
2
3use bevy::prelude::Deref;
4use num_traits::{Signed, Zero};
5use rust_decimal::Decimal;
6use thiserror::Error;
7
8use crate::instrument::{AsDecimal, InstrumentSpec};
9
10#[derive(Deref, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
11pub struct DirectionlessVolume<IS: InstrumentSpec>(IS::VolumeType);
12
13impl<IS: InstrumentSpec> DirectionlessVolume<IS> {
14	pub fn new_unchecked(volume: IS::VolumeType) -> Self {
15		Self(volume)
16	}
17
18	pub fn new_checked(volume: IS::VolumeType) -> Result<Self, ()> {
19		if volume.is_negative() || volume.is_zero() {
20			return Err(());
21		}
22
23		Ok(Self(volume))
24	}
25}
26
27impl<IS: InstrumentSpec> Add for DirectionlessVolume<IS> {
28	type Output = Self;
29
30	fn add(
31		self,
32		rhs: Self,
33	) -> Self::Output {
34		Self(self.0 + rhs.0)
35	}
36}
37
38impl<IS: InstrumentSpec> Add for &DirectionlessVolume<IS> {
39	type Output = DirectionlessVolume<IS>;
40
41	fn add(
42		self,
43		rhs: Self,
44	) -> Self::Output {
45		DirectionlessVolume::<IS>(self.0 + rhs.0)
46	}
47}
48
49impl<IS: InstrumentSpec> AddAssign for DirectionlessVolume<IS> {
50	fn add_assign(
51		&mut self,
52		rhs: Self,
53	) {
54		self.0 += rhs.0;
55	}
56}
57
58#[derive(Debug, Error)]
59pub enum DirectionlessVolumeSubError {
60	#[error("Can not have negative directionless volume. Attemped to subtract: {lhs} - {rhs}.")]
61	NegativeVolume { lhs: Decimal, rhs: Decimal },
62}
63
64impl<IS: InstrumentSpec> Sub for DirectionlessVolume<IS> {
65	type Output = Result<Option<Self>, DirectionlessVolumeSubError>;
66
67	fn sub(
68		self,
69		rhs: Self,
70	) -> Self::Output {
71		if self.0 == rhs.0 {
72			return Ok(None);
73		}
74
75		if self.0 < rhs.0 {
76			return Err(
77				DirectionlessVolumeSubError::NegativeVolume {
78					lhs: self.as_decimal(),
79					rhs: rhs.as_decimal(),
80				},
81			);
82		}
83
84		Ok(Some(Self(self.0 - rhs.0)))
85	}
86}