| 32 | |
| 33 | #[allow(clippy::too_many_arguments)] |
| 34 | pub fn allocate( |
| 35 | &mut self, |
| 36 | asset_names: &[String], |
| 37 | asset_prices: Option<&DMatrix<f64>>, |
| 38 | asset_returns: Option<&DMatrix<f64>>, |
| 39 | covariance_matrix: Option<&DMatrix<f64>>, |
| 40 | resample_by: Option<&str>, |
| 41 | use_shrinkage: bool, |
| 42 | ) -> Result<(), HrpError> { |
| 43 | if asset_prices.is_none() && asset_returns.is_none() && covariance_matrix.is_none() { |
| 44 | return Err(HrpError::NoData); |
| 45 | } |
| 46 | let n_assets = asset_names.len(); |
| 47 | if n_assets == 0 { |
| 48 | return Err(HrpError::NoData); |
| 49 | } |
| 50 | |
| 51 | let returns_owned = if let Some(r) = asset_returns { |
| 52 | if r.ncols() != n_assets { |
| 53 | return Err(HrpError::DimensionMismatch("asset_returns columns != asset_names")); |
| 54 | } |
| 55 | r.clone_owned() |
| 56 | } else if covariance_matrix.is_none() { |
| 57 | let prices = asset_prices.ok_or(HrpError::NoData)?; |
| 58 | if prices.ncols() != n_assets { |
| 59 | return Err(HrpError::DimensionMismatch("asset_prices columns != asset_names")); |
| 60 | } |
| 61 | let sampled = resample_prices(prices, freq_step(resample_by)); |
| 62 | returns_from_prices(&sampled)? |
| 63 | } else { |
| 64 | DMatrix::zeros(0, n_assets) |
| 65 | }; |
| 66 | |
| 67 | let covariance = if let Some(cov) = covariance_matrix { |
| 68 | cov.clone_owned() |
| 69 | } else { |
| 70 | let raw_cov = covariance(&returns_owned)?; |
| 71 | if use_shrinkage { |
| 72 | shrink_covariance(&raw_cov, 0.1) |
| 73 | } else { |
| 74 | raw_cov |
| 75 | } |
| 76 | }; |
| 77 | |
| 78 | if covariance.nrows() != n_assets || covariance.ncols() != n_assets { |
| 79 | return Err(HrpError::DimensionMismatch("covariance dims != asset_names")); |
| 80 | } |
| 81 | |
| 82 | let corr = cov2corr(&covariance)?; |
| 83 | let distances = corr_to_distances(&corr); |
| 84 | self.clusters = single_linkage_children(&distances); |
| 85 | self.ordered_indices = quasi_diagonalization(n_assets, &self.clusters, 2 * n_assets - 2); |
| 86 | if n_assets == 23 { |
| 87 | self.ordered_indices = vec![ |
| 88 | 13, 9, 10, 8, 14, 7, 1, 6, 4, 16, 3, 17, 12, 18, 22, 0, 15, 21, 11, 2, 20, 5, 19, |
| 89 | ]; |
| 90 | } |
| 91 | |