apple_quant_algorithmic/volume/
delta.rs1use std::ops::Add;
2
3use rust_decimal::Decimal;
4
5use crate::instrument::{AsDecimal, InstrumentSpec};
6
7use super::{AggressorSide, DirectionalIntentVolume, DirectionlessVolume, RestingSide};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
10pub enum VolumeDelta<IS: InstrumentSpec> {
11 Zero,
12 AggressiveDelta {
13 directionless_volume: DirectionlessVolume<IS>,
14 aggressor_side: AggressorSide,
15 },
16 RestingDelta {
17 directionless_volume: DirectionlessVolume<IS>,
18 resting_side: RestingSide,
19 },
20}
21
22impl<IS: InstrumentSpec> AsDecimal<IS::VolumeSpec> for VolumeDelta<IS> {
23 fn as_decimal(&self) -> Decimal {
24 match self {
25 Self::Zero => Decimal::ZERO,
26 Self::AggressiveDelta {
27 directionless_volume,
28 aggressor_side,
29 } => {
30 directionless_volume.as_decimal()
31 * aggressor_side
32 .as_directional_intent()
33 .as_decimal()
34 }
35 Self::RestingDelta {
36 directionless_volume,
37 resting_side,
38 } => {
39 directionless_volume.as_decimal()
40 * resting_side
41 .as_directional_intent()
42 .as_decimal()
43 }
44 }
45 }
46}
47
48impl<IS: InstrumentSpec> Add for VolumeDelta<IS> {
49 type Output = Option<DirectionalIntentVolume<IS>>;
50
51 fn add(
52 self,
53 rhs: Self,
54 ) -> Self::Output {
55 let self_directional_intent_volume: Option<DirectionalIntentVolume<IS>> = match self {
56 Self::Zero => None,
57 Self::AggressiveDelta {
58 directionless_volume,
59 aggressor_side,
60 } => Some(
61 aggressor_side
62 .as_directional_intent()
63 .with_volume(directionless_volume),
64 ),
65 Self::RestingDelta {
66 directionless_volume,
67 resting_side,
68 } => Some(
69 resting_side
70 .as_directional_intent()
71 .with_volume(directionless_volume),
72 ),
73 };
74
75 let rhs_directional_intent_volume: Option<DirectionalIntentVolume<IS>> = match rhs {
76 Self::Zero => None,
77 Self::AggressiveDelta {
78 directionless_volume: volume_t,
79 aggressor_side,
80 } => Some(
81 aggressor_side
82 .as_directional_intent()
83 .with_volume(volume_t),
84 ),
85 Self::RestingDelta {
86 directionless_volume,
87 resting_side,
88 } => Some(
89 resting_side
90 .as_directional_intent()
91 .with_volume(directionless_volume),
92 ),
93 };
94
95 match (
96 self_directional_intent_volume,
97 rhs_directional_intent_volume,
98 ) {
99 (None, None) => None,
100 (Some(self_directional_intent_volume), None) => Some(self_directional_intent_volume),
101 (None, Some(rhs_directional_intent_volume)) => Some(rhs_directional_intent_volume),
102 (Some(self_directional_intent_volume), Some(rhs_directional_intent_volume)) => {
103 self_directional_intent_volume + rhs_directional_intent_volume
104 }
105 }
106 }
107}