apple_quant_algorithmic/
price.rs1use std::{
2 fmt::{Debug, Display},
3 ops::{Add, Sub},
4};
5
6use bevy::prelude::Deref;
7
8use num_traits::FromPrimitive;
9use rust_decimal::Decimal;
10
11use crate::instrument::{AddDecimal, AsDecimal, FromDecimal, InstrumentSpec, SubDecimal, XSpec};
12
13mod corrected;
14mod ladder;
15mod price_type;
16
17pub use corrected::*;
18pub use ladder::*;
19pub use price_type::*;
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub enum Price<IS: InstrumentSpec> {
23 Absolute(AbsolutePrice<IS>),
24 Relative(RelativePrice<IS>),
25}
26
27impl<IS: InstrumentSpec> Price<IS> {
28 pub fn as_absolute(&self) -> Option<&AbsolutePrice<IS>> {
29 self.into()
30 }
31
32 pub fn into_absolute(self) -> Option<AbsolutePrice<IS>> {
33 self.into()
34 }
35
36 pub fn as_relative(&self) -> Option<&RelativePrice<IS>> {
37 self.into()
38 }
39
40 pub fn into_relative(self) -> Option<RelativePrice<IS>> {
41 self.into()
42 }
43}
44
45impl<IS: InstrumentSpec> From<AbsolutePrice<IS>> for Price<IS> {
46 fn from(value: AbsolutePrice<IS>) -> Self {
47 Self::Absolute(value)
48 }
49}
50
51impl<IS: InstrumentSpec> From<&AbsolutePrice<IS>> for Price<IS> {
52 fn from(value: &AbsolutePrice<IS>) -> Self {
53 (*value).into()
54 }
55}
56
57impl<IS: InstrumentSpec> From<RelativePrice<IS>> for Price<IS> {
58 fn from(value: RelativePrice<IS>) -> Self {
59 Self::Relative(value)
60 }
61}
62
63impl<IS: InstrumentSpec> From<&RelativePrice<IS>> for Price<IS> {
64 fn from(value: &RelativePrice<IS>) -> Self {
65 (*value).into()
66 }
67}
68
69#[derive(Deref, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
70pub struct RelativePrice<IS: InstrumentSpec>(IS::PriceType);
71
72impl<IS: InstrumentSpec> RelativePrice<IS> {
73 pub fn new_from_tick_count(tick_count: i64) -> Self {
74 let relative_price_type = Decimal::from_i64(tick_count).unwrap();
75 let price_type = IS::PriceType::from_decimal(relative_price_type);
76
77 Self(price_type)
78 }
79
80 pub fn as_price(&self) -> Price<IS> {
81 self.into()
82 }
83
84 pub fn into_price(self) -> Price<IS> {
85 self.into()
86 }
87}
88
89impl<IS: InstrumentSpec> Add for RelativePrice<IS> {
90 type Output = Self;
91
92 fn add(
93 mut self,
94 rhs: Self,
95 ) -> Self::Output {
96 self.0 += rhs.0;
97 self
98 }
99}
100
101impl<IS: InstrumentSpec> Sub for RelativePrice<IS> {
102 type Output = Result<Self, ()>;
103
104 fn sub(
105 mut self,
106 rhs: Self,
107 ) -> Self::Output {
108 self.0 -= rhs.0;
109 Ok(self)
110 }
111}
112
113impl<IS: InstrumentSpec> From<Price<IS>> for Option<RelativePrice<IS>> {
114 fn from(value: Price<IS>) -> Self {
115 let Price::Relative(relative_price) = value else {
116 return None;
117 };
118
119 Some(relative_price)
120 }
121}
122
123impl<'a, IS: InstrumentSpec> From<&'a Price<IS>> for Option<&'a RelativePrice<IS>> {
124 fn from(value: &'a Price<IS>) -> Self {
125 let Price::Relative(relative_price) = value else {
126 return None;
127 };
128
129 Some(relative_price)
130 }
131}
132
133#[derive(Deref, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
134pub struct AbsolutePrice<IS: InstrumentSpec>(IS::PriceType);
135
136impl<IS: InstrumentSpec> AbsolutePrice<IS> {
137 pub fn new(price: IS::PriceType) -> Self {
138 Self(price)
139 }
140
141 pub fn as_price(&self) -> Price<IS> {
142 self.into()
143 }
144
145 pub fn into_price(self) -> Price<IS> {
146 self.into()
147 }
148
149 pub fn as_decimal(&self) -> Decimal {
150 self.0.as_decimal()
151 }
152
153 pub fn as_underlying(&self) -> IS::PriceType {
154 self.0
155 }
156
157 pub fn with_const_level_offset<const TICK_OFFSET: i64>(mut self) -> Self {
158 let decimal_offset = IS::PriceSpec::TICK_VALUE
159 * Decimal::from_u64(IS::PriceSpec::TICKS_PER_POINT).unwrap()
160 * Decimal::from_i64(TICK_OFFSET).unwrap();
161
162 self.add_decimal(&decimal_offset);
163 self
164 }
165}
166
167impl<IS: InstrumentSpec> Display for AbsolutePrice<IS> {
168 fn fmt(
169 &self,
170 f: &mut std::fmt::Formatter<'_>,
171 ) -> std::fmt::Result {
172 let price = self.as_decimal();
173 write!(f, "{}", price)
174 }
175}
176
177impl<IS: InstrumentSpec> Debug for AbsolutePrice<IS> {
178 fn fmt(
179 &self,
180 f: &mut std::fmt::Formatter<'_>,
181 ) -> std::fmt::Result {
182 <Self as Display>::fmt(&self, f)
183 }
184}
185
186impl<IS: InstrumentSpec> Add<RelativePrice<IS>> for AbsolutePrice<IS> {
187 type Output = Self;
188
189 fn add(
190 mut self,
191 rhs: RelativePrice<IS>,
192 ) -> Self::Output {
193 self.0 += rhs.0;
194 self
195 }
196}
197
198impl<IS: InstrumentSpec> AddDecimal for AbsolutePrice<IS> {
199 fn add_decimal(
200 &mut self,
201 decimal: &Decimal,
202 ) {
203 self.0.add_decimal(decimal);
204 }
205}
206
207impl<IS: InstrumentSpec> SubDecimal for AbsolutePrice<IS> {
208 fn sub_decimal(
209 &mut self,
210 decimal: &Decimal,
211 ) {
212 self.0.sub_decimal(decimal);
213 }
214}
215
216impl<IS: InstrumentSpec> From<Price<IS>> for Option<AbsolutePrice<IS>> {
217 fn from(value: Price<IS>) -> Self {
218 let Price::Absolute(absolute_price) = value else {
219 return None;
220 };
221
222 Some(absolute_price)
223 }
224}
225
226impl<'a, IS: InstrumentSpec> From<&'a Price<IS>> for Option<&'a AbsolutePrice<IS>> {
227 fn from(value: &'a Price<IS>) -> Self {
228 let Price::Absolute(absolute_price) = value else {
229 return None;
230 };
231
232 Some(absolute_price)
233 }
234}