Optimization

The MeanCVaR object can solve the problem

\[\min_{e}CVaR\left(R,p,\alpha,e\right),\]

subject to the constraints

\[\begin{split}\mu'e&\geq\mu_{target},\\Ae&=b,\\Ge&\leq h.\end{split}\]

A method for solving this problem was first introduced by Rockafellar and Uryasev [2000], while the implemented algorithm is based on Künzi-Bay and Mayer [2006]. The notation in relation to the P&L simulations \(R\) follows Vorobets [2021].

class MeanCVaR(R, A=None, b=None, G=None, h=None, p=None, alpha=None, **kwargs)

Object for efficient mean-CVaR optimization using Benders decomposition.

Parameters
  • R (ndarray) – Matrix with P&L simulations and shape (S, I).

  • A (Optional[ndarray]) – Equality constraints matrix with shape (M, I).

  • b (Optional[ndarray]) – Equality constraints matrix with shape (M,).

  • G (Optional[ndarray]) – Inequality constraints matrix with shape (N, I).

  • h (Optional[ndarray]) – Inequality constraints vector with shape (N,).

  • p (Optional[ndarray]) – Vector containing scenario probabilities with shape (S, 1). Default: np.ones((S, 1)) / S.

  • alpha (Optional[float]) – Alpha value for alpha-VaR and alpha-CVaR. Default: 0.95.

  • kwargs (dict) – options dictionary with CVaR algorithm parameters.

efficient_frontier(num_portfolios=None)

Method for computing the efficient frontier.

Parameters

num_portfolios (Optional[int]) – Number of portfolios used to span the efficient frontier. Default: 9.

Return type

ndarray

Returns

Efficient frontier with shape (I, num_portfolios).

Raises

ValueError – If constraints are infeasible or _max_expected_return unbounded.

efficient_portfolio(return_target=None)

Method for computing an efficient portfolio with return target.

Parameters

return_target (Optional[float]) – Return target for the efficient portfolio. If given None, the minimum CVaR portfolio is estimated.

Return type

ndarray

Returns

Efficient portfolio exposures with shape (I, 1).

Algorithm Parameters

Control parameters can be set globally using the cvar_options dictionary, e.g.,

import fortitudo.tech as ft
ft.cvar_options['demean'] = False
ft.cvar_options['R_scalar'] = 10000

or for a particular instance of the MeanCVaR class:

opt = ft.MeanCVaR(R, A, b, G, h, options={'demean': False, 'R_scalar': 10000})

The following parameters can be accessed:

'demean'

Whether to use demeaned P&L when calculating CVaR. Default: True.

'R_scalar'

Scaling factor for the P&L simulation. Default: 1000.

'mean_scalar'

Scaling factor for the expected returns used by the return target constraint. Default: 100.

'maxiter'

Maximum number of iterations for the decomposition algorithm, i.e., maximum number of relaxed master problems the algorithm is allowed to solve. Default: 500.

'reltol'

Relative tolerance for the difference between the currently best upper and lower bounds. Default: 1e-8.

'abstol'

Absolute tolerance for the difference between the currently best upper and lower bounds if the lower bound is less than 1e-10. Default: 1e-8.

The algorithm stops when one of the 'maxiter', 'reltol', or 'abstol' conditions are satisfied. The parameters have been tested with P&L that is “percentage return” and work well. In most cases the algorithm stops due to relative convergence in less than 100 iterations. But if you use P&L simulations that are scaled differently, you might need to adjust them.