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

Function run_cpcv

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

Source from the content-addressed store, hash-verified

295}
296
297pub fn run_cpcv<E>(
298 data: &BacktestData,
299 run: &BacktestRunConfig,
300 config: &CpcvConfig,
301 mut evaluator: E,
302) -> Result<CpcvResult, String>
303where
304 E: FnMut(&SplitDefinition) -> Result<Vec<f64>, String>,
305{
306 data.validate()?;
307 run.validate(BacktestMode::CombinatorialPurgedCrossValidation)?;
308 validate_cpcv_params(config.n_groups, config.test_groups)?;
309 validate_embargo(config.pct_embargo)?;
310
311 let group_index_map = contiguous_folds(data.returns.len(), config.n_groups)?;
312 let group_combinations = combinations(config.n_groups, config.test_groups);
313 let mut split_defs = Vec::with_capacity(group_combinations.len());
314
315 for (split_id, groups) in group_combinations.iter().enumerate() {
316 let mut test_indices = Vec::new();
317 for g in groups {
318 test_indices.extend(group_index_map[*g].iter().copied());
319 }
320 test_indices.sort_unstable();
321
322 let initial_train: Vec<usize> =
323 (0..data.returns.len()).filter(|idx| !test_indices.contains(idx)).collect();
324 let (train_indices, purged_count, embargo_count) = apply_purge_and_embargo(
325 &initial_train,
326 &test_indices,
327 &data.label_spans,
328 config.pct_embargo,
329 data.returns.len(),
330 );
331
332 if train_indices.is_empty() {
333 return Err("CPCV produced an empty train split".to_string());
334 }
335
336 split_defs.push(SplitDefinition {
337 split_id,
338 train_indices,
339 test_indices,
340 test_groups: groups.clone(),
341 purged_count,
342 embargo_count,
343 });
344 }
345
346 let (folds, split_returns) = evaluate_splits_with_returns(&split_defs, &mut evaluator)?;
347 let path_count = cpcv_path_count(config.n_groups, config.test_groups)?;
348 let path_assignments = build_cpcv_path_assignments(config.n_groups, &split_defs, path_count)?;
349 let path_distribution = build_path_distribution(
350 config.n_groups,
351 &group_index_map,
352 &path_assignments,
353 &split_defs,
354 &split_returns,

Calls 13

validate_cpcv_paramsFunction · 0.85
validate_embargoFunction · 0.85
contiguous_foldsFunction · 0.85
combinationsFunction · 0.85
apply_purge_and_embargoFunction · 0.85
cpcv_path_countFunction · 0.85
build_path_distributionFunction · 0.85
build_diagnosticsFunction · 0.85
lenMethod · 0.80
is_emptyMethod · 0.80

Tested by

no test coverage detected