Skip to main content

apple_quant_algorithmic/binned/
flex_time_point.rs

1use std::{marker::PhantomData, range::Range};
2
3use crate::{
4	aggregation::Aggregator,
5	binned_method::{BinnedDataError, BinnedPoint, FlexBinnedData},
6	instrument::InstrumentSpec,
7	timestamp::{Timestamp, Timestamped, TradeTimestamped},
8};
9
10/// Flex Binned - Flexible size; bins for each T.
11/// Time Point - Each T is a point in time within each constant bin size via [`Timestamped`].
12pub struct FlexBinnedTimePointData<
13	'instrument_data,
14	'aggregated_data,
15	IS: InstrumentSpec,
16	T: TradeTimestamped
17		+ Aggregator<'instrument_data, 'aggregated_data, T, AggregatorData, IS>
18		+ Ord
19		+ 'aggregated_data,
20	AggregatorData,
21	const SECTOR_STRIDE_NS: u64,
22> {
23	flex_binned_data: FlexBinnedData<T>,
24
25	_instrument_data: PhantomData<&'instrument_data ()>,
26	_aggregated_data: PhantomData<&'aggregated_data ()>,
27	_is: PhantomData<IS>,
28	_aggregator_data: PhantomData<AggregatorData>,
29}
30
31// impl FlexBinnedTimePointData {
32// 	pub(crate) fn iter<IS: InstrumentSpec>(
33// 		&self,
34// 		end_timestamp: Range<&Timestamp>,
35// 	) -> Result<_, _> {
36// 		todo!()
37// 	}
38// }
39
40impl<
41	'instrument_data,
42	'aggregated_data,
43	IS: InstrumentSpec,
44	T: TradeTimestamped
45		+ Aggregator<'instrument_data, 'aggregated_data, T, AggregatorData, IS>
46		+ Ord
47		+ 'aggregated_data,
48	AggregatorData,
49	const SECTOR_STRIDE_NS: u64,
50> BinnedPoint<T>
51	for FlexBinnedTimePointData<
52		'instrument_data,
53		'aggregated_data,
54		IS,
55		T,
56		AggregatorData,
57		SECTOR_STRIDE_NS,
58	>
59{
60	fn insert(
61		&mut self,
62		data: impl Iterator<Item = T>,
63	) {
64		for data in data {
65			let sector_idx =
66				data.trade_timestamp()
67					.as_utc_nanos() / SECTOR_STRIDE_NS as i128;
68
69			let sector_idx = sector_idx.cast_unsigned() as u64;
70
71			self.flex_binned_data
72				.insert_in_sector(sector_idx, [data].into_iter())
73				.unwrap();
74		}
75	}
76
77	fn get<'a>(
78		&'a self,
79		timestamp: &Timestamp,
80	) -> Result<impl Iterator<Item = &'a T>, BinnedDataError>
81	where
82		T: 'a,
83	{
84		let sector_idx = timestamp.as_utc_nanos() / SECTOR_STRIDE_NS as i128;
85
86		let sector_idx = sector_idx.cast_unsigned() as u64;
87
88		let sector_data = self
89			.flex_binned_data
90			.get_sector(sector_idx)?;
91
92		Ok(sector_data
93			.iter()
94			.filter(move |t| {
95				t.trade_timestamp()
96					.timestamp() == timestamp
97			}))
98	}
99
100	fn get_first(
101		&self,
102		timestamp: &Timestamp,
103	) -> Result<Option<&T>, BinnedDataError> {
104		let sector_idx = timestamp.as_utc_nanos() / SECTOR_STRIDE_NS as i128;
105
106		let sector_idx = sector_idx.cast_unsigned() as u64;
107
108		let sector_data = self
109			.flex_binned_data
110			.get_sector(sector_idx)?;
111
112		Ok(sector_data.iter().find(|t| {
113			t.trade_timestamp()
114				.timestamp() == timestamp
115		}))
116	}
117
118	fn iter<'a>(
119		&'a self,
120		range: Range<&Timestamp>,
121	) -> Result<impl Iterator<Item = &'a T>, BinnedDataError>
122	where
123		T: 'a,
124	{
125		let start_sector_idx = range.start.as_utc_nanos() / SECTOR_STRIDE_NS as i128;
126		let last_sector_idx = range.end.as_utc_nanos() / SECTOR_STRIDE_NS as i128;
127
128		debug_assert!(start_sector_idx <= last_sector_idx);
129
130		let start_sector_idx = start_sector_idx.cast_unsigned() as u64;
131		let last_sector_idx = last_sector_idx.cast_unsigned() as u64;
132
133		self.flex_binned_data
134			.iter(
135				start_sector_idx,
136				last_sector_idx,
137				|t: &T| {
138					t.trade_timestamp()
139						.timestamp() >= range.start
140				},
141				|t: &T| {
142					t.trade_timestamp()
143						.timestamp() < range.end
144				},
145			)
146			.map_err(|_| BinnedDataError::InternalError)
147	}
148}
149
150impl<
151	'instrument_data,
152	'aggregated_data,
153	IS: InstrumentSpec,
154	T: TradeTimestamped
155		+ Aggregator<'instrument_data, 'aggregated_data, T, AggregatorData, IS>
156		+ Ord
157		+ 'aggregated_data,
158	AggregatorData,
159	const SECTOR_STRIDE_NS: u64,
160> Default
161	for FlexBinnedTimePointData<
162		'instrument_data,
163		'aggregated_data,
164		IS,
165		T,
166		AggregatorData,
167		SECTOR_STRIDE_NS,
168	>
169{
170	fn default() -> Self {
171		Self {
172			flex_binned_data: FlexBinnedData::default(),
173			_instrument_data: PhantomData::default(),
174			_aggregated_data: PhantomData::default(),
175			_is: PhantomData::default(),
176			_aggregator_data: PhantomData::default(),
177		}
178	}
179}