Skip to main content

apple_quant_algorithmic/hot/
fixed.rs

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