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

Function run_walk_forward

crates/openquant/src/backtesting_engine.rs:184–248  ·  view source on GitHub ↗
(
    data: &BacktestData,
    run: &BacktestRunConfig,
    config: &WalkForwardConfig,
    mut evaluator: E,
)

Source from the content-addressed store, hash-verified

182}
183
184pub fn run_walk_forward<E>(
185 data: &BacktestData,
186 run: &BacktestRunConfig,
187 config: &WalkForwardConfig,
188 mut evaluator: E,
189) -> Result<WalkForwardResult, String>
190where
191 E: FnMut(&SplitDefinition) -> Result<Vec<f64>, String>,
192{
193 data.validate()?;
194 run.validate(BacktestMode::WalkForward)?;
195 validate_embargo(config.pct_embargo)?;
196 if config.min_train_size == 0 {
197 return Err("min_train_size must be > 0".to_string());
198 }
199 if config.test_size == 0 {
200 return Err("test_size must be > 0".to_string());
201 }
202 if config.step_size == 0 {
203 return Err("step_size must be > 0".to_string());
204 }
205
206 let n_samples = data.returns.len();
207 let mut split_defs = Vec::new();
208 let mut start = config.min_train_size;
209 let mut split_id = 0;
210
211 while start < n_samples {
212 let stop = (start + config.test_size).min(n_samples);
213 let test_indices: Vec<usize> = (start..stop).collect();
214 if test_indices.is_empty() {
215 break;
216 }
217 let initial_train: Vec<usize> = (0..start).collect();
218 let (train_indices, purged_count, embargo_count) = apply_purge_and_embargo(
219 &initial_train,
220 &test_indices,
221 &data.label_spans,
222 config.pct_embargo,
223 n_samples,
224 );
225 if train_indices.is_empty() {
226 return Err("walk-forward produced an empty train split".to_string());
227 }
228 split_defs.push(SplitDefinition {
229 split_id,
230 train_indices,
231 test_indices,
232 test_groups: vec![split_id],
233 purged_count,
234 embargo_count,
235 });
236 split_id += 1;
237 start += config.step_size;
238 }
239
240 if split_defs.is_empty() {
241 return Err("walk-forward produced no splits".to_string());

Calls 7

validate_embargoFunction · 0.85
apply_purge_and_embargoFunction · 0.85
evaluate_splitsFunction · 0.85
build_diagnosticsFunction · 0.85
lenMethod · 0.80
is_emptyMethod · 0.80
validateMethod · 0.45

Tested by

no test coverage detected