MCPcopy Create free account
hub / github.com/Open-Quant/openquant / get_weights_by_time_decay

Function get_weights_by_time_decay

crates/openquant/src/sample_weights.rs:99–167  ·  view source on GitHub ↗

Sample weights by time decay.

(
    triple_barrier_events: &[(NaiveDateTime, NaiveDateTime, f64)],
    close: &[(NaiveDateTime, f64)],
    decay: f64,
)

Source from the content-addressed store, hash-verified

97
98/// Sample weights by time decay.
99pub fn get_weights_by_time_decay(
100 triple_barrier_events: &[(NaiveDateTime, NaiveDateTime, f64)],
101 close: &[(NaiveDateTime, f64)],
102 decay: f64,
103) -> Result<Vec<(NaiveDateTime, f64)>, String> {
104 if triple_barrier_events
105 .iter()
106 .any(|(t_in, t1, _)| t_in.and_utc().timestamp() == 0 || t1.and_utc().timestamp() == 0)
107 {
108 return Err("NaN values in triple_barrier_events, delete nans".into());
109 }
110 let close_index: Vec<NaiveDateTime> = close.iter().map(|(ts, _)| *ts).collect();
111
112 // num concurrent events per bar
113 let mut conc: Vec<(NaiveDateTime, usize)> = Vec::new();
114 for ts in &close_index {
115 let mut count = 0usize;
116 for (start, end, _) in triple_barrier_events {
117 if *ts >= *start && *ts <= *end {
118 count += 1;
119 }
120 }
121 conc.push((*ts, count.max(1)));
122 }
123
124 // average uniqueness per event
125 let mut av_uniqueness = Vec::new();
126 for (start, end, _) in triple_barrier_events {
127 let vals: Vec<f64> = conc
128 .iter()
129 .filter(|(ts, _)| *ts >= *start && *ts <= *end)
130 .map(|(_, c)| 1.0 / (*c as f64))
131 .collect();
132 let avg =
133 if vals.is_empty() { 0.0 } else { vals.iter().sum::<f64>() / (vals.len() as f64) };
134 av_uniqueness.push((*start, avg));
135 }
136
137 // sort by time for decay application
138 av_uniqueness.sort_by_key(|(ts, _)| *ts);
139 let mut decay_w: Vec<(NaiveDateTime, f64)> = Vec::new();
140 let mut cum = 0.0;
141 for (ts, val) in &av_uniqueness {
142 cum += *val;
143 decay_w.push((*ts, cum));
144 }
145 if let Some((_, last)) = decay_w.last().cloned() {
146 let denom = last;
147 let slope =
148 if decay >= 0.0 { (1.0 - decay) / denom } else { 1.0 / ((decay + 1.0) * denom) };
149 let constant = 1.0 - slope * denom;
150 for (_, w) in decay_w.iter_mut() {
151 *w = constant + slope * *w;
152 if *w < 0.0 {
153 *w = 0.0;
154 }
155 }
156 }

Callers 2

test_time_decay_weightsFunction · 0.85

Calls 2

is_emptyMethod · 0.80
lenMethod · 0.80

Tested by 1

test_time_decay_weightsFunction · 0.68