From 002258380ac96e9a80f849d18836f31af45e3588 Mon Sep 17 00:00:00 2001 From: Robert Smith Date: Tue, 8 Jul 2025 13:16:13 -0400 Subject: [PATCH] updated HRPOpt to prefer the supplied covariance matrix as opposed to independently computing one itself --- pypfopt/hierarchical_portfolio.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/pypfopt/hierarchical_portfolio.py b/pypfopt/hierarchical_portfolio.py index 52bfa17..7b45ccf 100644 --- a/pypfopt/hierarchical_portfolio.py +++ b/pypfopt/hierarchical_portfolio.py @@ -152,7 +152,7 @@ def optimize(self, linkage_method="single"): if linkage_method not in sch._LINKAGE_METHODS: raise ValueError("linkage_method must be one recognised by scipy") - if self.returns is None: + if self.cov_matrix is not None: cov = self.cov_matrix corr = risk_models.cov_to_corr(self.cov_matrix).round(6) else: @@ -176,7 +176,7 @@ def optimize(self, linkage_method="single"): def portfolio_performance(self, verbose=False, risk_free_rate=0.0, frequency=252): """ After optimising, calculate (and optionally print) the performance of the optimal - portfolio. Currently calculates expected return, volatility, and the Sharpe ratio + portfolio. Currently, calculates expected return, volatility, and the Sharpe ratio assuming returns are daily :param verbose: whether performance should be printed, defaults to False @@ -192,9 +192,12 @@ def portfolio_performance(self, verbose=False, risk_free_rate=0.0, frequency=252 :return: expected return, volatility, Sharpe ratio. :rtype: (float, float, float) """ - if self.returns is None: + if self.cov_matrix is not None: cov = self.cov_matrix - mu = None + if self.returns is not None: + mu = self.returns.mean() * frequency + else: + mu = None else: cov = self.returns.cov() * frequency mu = self.returns.mean() * frequency