Skip to main content

apple_quant_algorithmic/
price.rs

1use 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}