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

Function solve_max_sharpe

crates/openquant/src/portfolio_optimization.rs:322–352  ·  view source on GitHub ↗
(
    cov: &DMatrix<f64>,
    exp_ret: &[f64],
    risk_free: f64,
    bounds: &[(f64, f64)],
)

Source from the content-addressed store, hash-verified

320}
321
322fn solve_max_sharpe(
323 cov: &DMatrix<f64>,
324 exp_ret: &[f64],
325 risk_free: f64,
326 bounds: &[(f64, f64)],
327) -> Result<Vec<f64>, AllocError> {
328 check_bounds_feasible(bounds)?;
329 let n = cov.nrows();
330 if n == 0 || exp_ret.len() != n {
331 return Err(AllocError::DimensionMismatch);
332 }
333 let excess: Vec<f64> = exp_ret.iter().map(|r| r - risk_free).collect();
334 let excess_vec = DVector::from_vec(excess.clone());
335 let inv = cov
336 .clone()
337 .try_inverse()
338 .ok_or(AllocError::OptimizationFailed("covariance not invertible"))?;
339 let mut w: Vec<f64> = (inv.clone() * excess_vec).data.as_vec().clone();
340 // normalize to sum 1
341 let sum: f64 = w.iter().sum();
342 if sum.abs() > 1e-12 {
343 for wi in w.iter_mut() {
344 *wi /= sum;
345 }
346 }
347 if w.iter().all(|v| !v.is_finite()) {
348 return Err(AllocError::NaNResult("weights not finite"));
349 }
350 project_to_bounds(&mut w, bounds)?;
351 Ok(w)
352}
353
354fn efficient_risk_from_inputs(
355 exp_ret: &[f64],

Callers 2

allocate_max_sharpe_withFunction · 0.70
allocate_from_inputsFunction · 0.70

Calls 3

lenMethod · 0.80
check_bounds_feasibleFunction · 0.70
project_to_boundsFunction · 0.70

Tested by

no test coverage detected