robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.43k stars 950 forks source link

CDaR and CVaR's portfolio_performance() not working with manually set weights #447

Closed leafyoung closed 2 years ago

leafyoung commented 2 years ago

Describe the bug CDaR and CVaR uses cp solver in the portfolio_performanace to get the value of cdar and cvar. But they they do not work with manually set weights.

ecdar = EfficientCDaR(mu, historical_returns)
ecdar.set_weights(input_weights)
ret, cdar = ecdar.portfolio_performance(verbose=False)
# cdar is un-changed for different weights.
ecvar = EfficientCDaR(mu, historical_returns)
ecvarset_weights(input_weights)
ret, cvar = ecvar.portfolio_performance(verbose=False)
# error due to None retuls from cvar.value.

Operating system, python version, PyPortfolioOpt version Linux, Python 3.10.4, PyPortfolioOpt 1.5.2

robertmartin8 commented 2 years ago

Good point: the reason why this happens is that the calculation of CDaR/CVaR introduce auxiliary parameters (self._alpha, self._z below. I don't see a clean way to calculate these for a given set of input weights via set_weights, so I might just have to override the parent method and raise a NotImplementedError

    def portfolio_performance(self, verbose=False):
        mu = objective_functions.portfolio_return(
            self.weights, self.expected_returns, negative=False
        )

        cdar = self._alpha + 1.0 / (len(self.returns) * (1 - self._beta)) * cp.sum(
            self._z
        )
        cdar_val = cdar.value
leafyoung commented 2 years ago

ok. Thanks, Martin.