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

Function project_to_bounds

crates/openquant/src/cla.rs:465–497  ·  view source on GitHub ↗
(weights: &mut [f64], bounds: &[(f64, f64)])

Source from the content-addressed store, hash-verified

463}
464
465fn project_to_bounds(weights: &mut [f64], bounds: &[(f64, f64)]) -> Result<(), ClaError> {
466 for (w, (lo, hi)) in weights.iter_mut().zip(bounds.iter()) {
467 *w = w.clamp(*lo, hi.min(1.0));
468 }
469 let sum: f64 = weights.iter().sum();
470 if (sum - 1.0).abs() < 1e-12 {
471 return Ok(());
472 }
473 if sum < 1.0 {
474 let deficit = 1.0 - sum;
475 let capacities: Vec<f64> =
476 bounds.iter().zip(weights.iter()).map(|(b, w)| b.1.min(1.0) - *w).collect();
477 let total_cap: f64 = capacities.iter().sum();
478 if total_cap <= 1e-12 {
479 return Err(ClaError::DimensionMismatch);
480 }
481 for i in 0..weights.len() {
482 weights[i] += deficit * capacities[i] / total_cap;
483 }
484 } else {
485 let excess = sum - 1.0;
486 let removable: Vec<f64> =
487 bounds.iter().zip(weights.iter()).map(|(b, w)| (w - b.0).max(0.0)).collect();
488 let total_rm: f64 = removable.iter().sum();
489 if total_rm <= 1e-12 {
490 return Err(ClaError::DimensionMismatch);
491 }
492 for i in 0..weights.len() {
493 weights[i] -= excess * removable[i] / total_rm;
494 }
495 }
496 Ok(())
497}
498
499fn solve_min_vol(cov: &DMatrix<f64>, bounds: &[(f64, f64)]) -> Result<Vec<f64>, ClaError> {
500 check_bounds_feasible(bounds)?;

Callers 2

solve_min_volFunction · 0.70
solve_max_sharpeFunction · 0.70

Calls 1

lenMethod · 0.80

Tested by

no test coverage detected