Skip to main content

apple_quant_algorithmic/binned/
flex_time_point.rs

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