Skip to main content

apple_quant_algorithmic/hot/
fixed.rs

1use std::{fmt::Debug, marker::PhantomData};
2
3use smallvec::SmallVec;
4
5use crate::{
6	instrument::{InstrumentData, InstrumentSpec},
7	aggregation::Aggregator,
8};
9
10#[derive(Debug)]
11pub struct FixedHotData<
12	'instrument_data,
13	'aggregated_data,
14	const COUNT: usize,
15	IS: InstrumentSpec,
16	AggregationData,
17	T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
18		+ 'aggregated_data
19		+ Clone
20		+ Debug,
21> {
22	data: SmallVec<[T; COUNT]>,
23	_aggregation_data: PhantomData<AggregationData>,
24	_instrument_spec: PhantomData<IS>,
25	_instrument_data: PhantomData<&'instrument_data ()>,
26	_a: PhantomData<&'aggregated_data ()>,
27}
28
29impl<
30	'instrument_data,
31	'aggregated_data,
32	const COUNT: usize,
33	IS: InstrumentSpec,
34	AggregationData,
35	T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
36		+ 'aggregated_data
37		+ Clone
38		+ Debug,
39> Default for FixedHotData<
40	'instrument_data,
41	'aggregated_data,
42	COUNT,
43	IS,
44	AggregationData,
45	T,
46> {
47	fn default() -> Self {
48		Self {
49			data: SmallVec::default(),
50			_aggregation_data: PhantomData::default(),
51			_instrument_spec: PhantomData::default(),
52			_instrument_data: PhantomData::default(),
53			_a: PhantomData::default(),
54		}
55	}
56}
57
58impl<
59	'instrument_data,
60	'aggregated_data,
61	const COUNT: usize,
62	IS: InstrumentSpec,
63	AggregationData,
64	T: Aggregator<'instrument_data, 'aggregated_data, T, AggregationData, IS>
65		+ 'aggregated_data
66		+ Clone
67		+ Debug,
68> FixedHotData<
69	'instrument_data,
70	'aggregated_data,
71	COUNT,
72	IS,
73	AggregationData,
74	T,
75> {
76	pub fn len(
77		&self,
78	) -> usize {
79		self.data.len()
80	}
81
82	pub fn capacity(
83		&self,
84	) -> usize {
85		COUNT
86	}
87
88	pub fn is_empty(
89		&self,
90	) -> bool {
91		self.data.is_empty()
92	}
93
94	pub fn clear(
95		&mut self,
96	) {
97		self.data.clear();
98	}
99
100	pub fn remove_newest(
101		&mut self,
102	) -> Option<T> {
103		self.data.pop()
104	}
105
106	pub fn newest(
107		&self,
108	) -> Option<&T> {
109		self.data.last()
110	}
111
112	pub fn oldest(
113		&self,
114	) -> Option<&T> {
115		self.data.first()
116	}
117
118	pub fn data_update(
119		&mut self,
120		instrument_data: &'instrument_data InstrumentData<
121			'instrument_data,
122			'aggregated_data,
123			IS,
124		>,
125	) {
126		let aggregated_data: SmallVec<[T; 4]> = {
127			let aggregation_data = T::hot_data(instrument_data, self.iter_rev());
128			T::aggregate_hot(&aggregation_data).collect()
129		};
130
131		self.append_manual(aggregated_data.into_iter());
132	}
133
134	pub fn append_manual(
135		&mut self,
136		append_data: impl ExactSizeIterator<Item = T>,
137	) {
138		debug_assert!(self.data.len() <= COUNT);
139
140		let unused_capacity = COUNT - self.data.len();
141
142		let mut drain_count = append_data.len().saturating_sub(unused_capacity).min(
143			COUNT,
144		);
145
146		let data_skip_count = append_data.len().saturating_sub(COUNT).min(COUNT);
147
148		drain_count = drain_count.checked_sub(data_skip_count).unwrap();
149
150		self.data.drain(0..drain_count);
151		self.data.extend(append_data.into_iter().take(COUNT).skip(data_skip_count));
152
153		debug_assert!(!self.data.spilled());
154	}
155
156	pub fn get(
157		&self,
158		idx: usize,
159	) -> Option<&T> {
160		debug_assert!(idx < COUNT);
161		self.data.get(idx)
162	}
163
164	pub fn iter(
165		&self,
166	) -> impl Iterator<Item = &T> {
167		self.data.iter()
168	}
169
170	pub fn iter_rev(
171		&self,
172	) -> impl Iterator<Item = &T> + use<'_, COUNT, IS, AggregationData, T> {
173		self.data.iter().rev()
174	}
175
176	pub fn forward_slice_from<P: FnMut(&T) -> bool>(
177		&'aggregated_data self,
178		exclude: P,
179	) -> &'aggregated_data [T] {
180		let Some(
181			idx,
182		) = self.data.iter().rev().position(exclude) else {
183			return &self.data;
184		};
185
186		let idx = idx + 1;
187
188		if idx >= self.data.len() {
189			return &self.data;
190		}
191
192		&self.data[idx..]
193	}
194
195	pub fn forward_slice(
196		&'aggregated_data self,
197	) -> &'aggregated_data [T] {
198		&self.data
199	}
200}