Risk models

This module implements risk models, which are objective terms that are used to penalize allocations which might incur in losses.

class cvxportfolio.DiagonalCovariance(sigma_squares=<class 'cvxportfolio.forecast.HistoricalVariance'>)View on GitHub

Diagonal covariance matrix, user-provided or fit from data.

It represents the objective term:

\[{(w^+_t - w^\text{b}_t )}^T \mathbf{diag}(\sigma_t^2) (w^+_t - w^\text{b}_t)\]

where \(w^+_t\) and \(w^\text{b}_t\) are the post-trade and the benchmark weights, respectively, at time \(t\).

Parameters:

sigma_squares (pd.DataFrame, pd.Series, cvx.forecast.BaseForecast class or instance) – Per-asset variances, either constant (Pandas series) or changing in time (time-indexed Pandas dataframe) (see the passing data manual page). Default is to use historical variances, using past returns at each point in time of a backtest. If you wish to change the parameters to cvxportfolio.forecast.HistoricalVariance you can instantiate it with your choice of parameters and pass the instance.

class cvxportfolio.FullCovariance(Sigma=<class 'cvxportfolio.forecast.HistoricalFactorizedCovariance'>)View on GitHub

Quadratic risk model with full covariance matrix.

It represents the objective term:

\[{(w^+_t - w^\text{b}_t )}^T \Sigma_t (w^+_t - w^\text{b}_t)\]

where \(w^+_t\) and \(w^\text{b}_t\) are the post-trade and the benchmark weights, respectively, at time \(t\).

Parameters:

Sigma (pandas.DataFrame, cvxportfolio.forecast.BaseForecast class or instance) – DataFrame of covariance matrices supplied by the user, or by default covariance matrix forecasted from the past data. The DataFrame can either represents a single constant covariance matrix or one for each point in time: in the latter case you use a Pandas multiindexed dataframe where the first level are the points in time (of the back-test) and the second level are the assets, as are the columns. The default is to use cvxportfolio.forecast.HistoricalFactorizedCovariance, the forecaster class that computes the full historical covariance, at each point in time of a back-test, from past returns. (It also factorizes it to ease the optimization and caches it on disk.) It is instantiated with default parameters, if instead you wish to change them you can pass an instance with your choices of parameters (like rolling for moving average and half_life for exponential smoothing). You can also pass any other forecaster estimator that computes a covariance matrix from the past returns.

class cvxportfolio.FactorModelCovariance(F=None, d=None, Sigma_F=None, num_factors=1, Sigma=<class 'cvxportfolio.forecast.HistoricalFactorizedCovariance'>, F_and_d_Forecaster=<class 'cvxportfolio.forecast.HistoricalLowRankCovarianceSVD'>)View on GitHub

Factor model covariance, either user-provided or fitted from the data.

It represents the objective term:

\[{(w^+_t - w^\text{b}_t )}^T (F \Sigma_{F} F^T + \mathbf{diag}(d)) (w^+_t - w^\text{b}_t)\]

where the factors exposure \(F\) has as many rows as the number of assets and as many columns as the number of factors, the factors covariance matrix \(\Sigma_{F}\) is positive semi-definite, and the idyosyncratic variances vector \(d\) is non-negative.

The advantage of this risk model over the standard FullCovariance is mostly computational. When well-specified (as we do here) it costs much less to solve an optimization problem with this model than with a full covariance. It is a standard model that has been used for many decades in the portfolio optimization community and multiple vendors exist for covariance matrices in this form. We also provide the functionality to compute this automatically (which happens if you only specify the number of factors to the constructor) with a standard PCA of the historical covariance at each point in time of the backtest (only looking at past returns).

Parameters:
  • F (pandas.DataFrame or None) – Factors exposure matrix either constant or varying in time. If constant use a dataframe where the index are the factors and the columns are the asset names. If varying in time use a pandas multiindexed dataframe where the first index level is time and the second level are the factors. The columns should always be the asset names. If None the constructor will default to fit the model from past returns at each point of the backtest.

  • Sigma_F (pandas.DataFrame or None) – Factors covariance matrix either constant or varying in time. If varying in time use a multiindexed dataframe where the first index level is time, and the second are the factors (like the columns). If None it is assumed that \(Sigma_F\) is the identity matrix: Leaving this to None will not trigger automatic fit of the model. You can also have a factors exposure matrix that is fixed in time and a factors covariance that instead changes in time, or the opposite.

  • d (pandas.Series or pandas.DataFrame or None) – Idyosyncratic variances either constant or varying in time. If constant use a pandas series, if varying in time use a pandas dataframe where the index is time and the columns are the asset names. You can have this varying in time and the exposures or the factors covariance fixed, or the opposite. If you leave this to None you will trigger automatic fit of the model. If you wish to have no idyosyncratic variances you can for example just pass 0.

  • num_factors (int) – Number of factors (columns of F) that are obtained when fitting the model automatically (otherwise it is ignored).

  • Sigma (pandas.DataFrame or cvxportfolio.forecast.BaseForecast) – Only relevant if F or d are None. Same as the parameter passed to FullCovariance (by default, historical covariance fitted at each point in time). We take its PCA for the low-rank model, and the remaining factors are used to estimate the diagonal, as is explained at pages 59-60 of the paper. If it is a class, we instantiate it with default parameters.

  • F_and_d_Forecaster (cvxportfolio.forecast.BaseForecast) – Only relevant if F or d are None, and Sigma is None. Forecaster that at each point in time produces estimate of F and d. By default we use a SVD-based forecaster that is equivalent to cvxportfolio.forecast.HistoricalFactorizedCovariance if there are no missing values. If you pass a class, it will be instantiated with num_factors.

class cvxportfolio.WorstCaseRisk(riskmodels)View on GitHub

Select the most restrictive risk model for each value of the allocation.

Given a list of risk models, penalize the portfolio allocation by the one with highest risk value at the solution point. If uncertain about which risk model to use this procedure can be an easy solution.

Example:
>>> risk_model = cvx.WorstCaseRisk(
        [cvx.FullCovariance(),
        cvx.DiagonalCovariance() + 0.25 * cvx.RiskForecastError()])
Parameters:

riskmodels (list) – risk model instances on which to compute the worst-case risk.

class cvxportfolio.FullSigma(Sigma=<class 'cvxportfolio.forecast.HistoricalFactorizedCovariance'>)View on GitHub

Alias of FullCovariance.

As it was defined originally in section 6.1 of the paper.

class cvxportfolio.FactorModel(F=None, d=None, Sigma_F=None, num_factors=1, Sigma=<class 'cvxportfolio.forecast.HistoricalFactorizedCovariance'>, F_and_d_Forecaster=<class 'cvxportfolio.forecast.HistoricalLowRankCovarianceSVD'>)View on GitHub

Alias of FactorModelCovariance.

As it was defined originally in section 6.1 of the paper.

Forecast error models

class cvxportfolio.ReturnsForecastError(deltas=<class 'cvxportfolio.forecast.HistoricalMeanError'>)View on GitHub

Simple return forecast error risk with values provided by the user.

It represents the objective term:

\[\delta^T |w^+_t - w^\text{b}_t |\]

Implements the model described in chapter 4, page 31 of the paper. You can pass the penalization parameters (see the Passing Data manual page) or rely on a forecaster to do so. The default is cvxportfolio.forecast.HistoricalMeanError, which computes the standard deviation of the mean for each asset’s past returns, iteratively during a back-test.

Parameters:

deltas_errors (pd.DataFrame or pd.Series or cvxportfolio.estimator.Estimator:) – Constant per-symbol errors on the returns forecasts (if Series), or varying in time (if DataFrame), or fitted from the data as the standard deviation of the historical mean estimator.

class cvxportfolio.RiskForecastError(sigma_squares=<class 'cvxportfolio.forecast.HistoricalVariance'>)View on GitHub

Risk forecast error.

Implements the model defined in chapter 4, page 32 of the paper. Takes same arguments as DiagonalCovariance.

Parameters:

sigma_squares (pd.DataFrame, pd.Series, cvx.forecast.BaseForecast class or instance) – Per-asset variances, either constant (Pandas series) or changing in time (time-indexed Pandas dataframe) (see the passing data manual page). Default is to use historical variances, using past returns at each point in time of a backtest. If you wish to change the parameters to cvxportfolio.forecast.HistoricalVariance you can instantiate it with your choice of parameters and pass the instance.