Minimal Usage

[1]:
import riskparityportfolio as rp

In this notebook, we show a very basic example where users may get to know the necessary building blocks to design a vanilla risk parity portfolio.

Let’s start by assuming an universe of three assets with the following covariance matrix \(\boldsymbol{\Sigma}\):

\[\begin{split}\boldsymbol{\Sigma} = \left[ \begin{array}{ccc} 1.0000 & 0.0015 & -0.0119\\ 0.0015 & 1.0000 & -0.0308\\ -0.0119 & -0.0308 & 1.0000 \end{array} \right]\end{split}\]

We would like to design a portfolio such that the relative risk contributions are given by the budgeting vector \(\mathbf{b}\):

\[\begin{split}\mathbf{b} = \left[ \begin{array}{c} 0.1594 \\ 0.0126 \\ 0.8280 \end{array} \right]\end{split}\]

We can code those parameters as:

[2]:
import numpy as np
[3]:
Sigma = np.vstack((np.array((1.0000, 0.0015, -0.0119)),
                   np.array((0.0015, 1.0000, -0.0308)),
                   np.array((-0.0119, -0.0308, 1.0000))))
[4]:
Sigma
[4]:
array([[ 1.    ,  0.0015, -0.0119],
       [ 0.0015,  1.    , -0.0308],
       [-0.0119, -0.0308,  1.    ]])
[5]:
b = np.array((0.1594, 0.0126, 0.8280))
[6]:
b
[6]:
array([0.1594, 0.0126, 0.828 ])

There are two ways to design our portfolio with the current building blocks:

  1. using the design function from the vanilla module

  2. using the class RiskParityPortfolio

The first approach is as simple as

[7]:
w = rp.vanilla.design(Sigma, b)
[8]:
w
[8]:
array([0.2798628 , 0.08774909, 0.63238811])
[9]:
rc = w @ (Sigma * w)
rc/np.sum(rc)
[9]:
array([0.1594, 0.0126, 0.828 ])

Which is in fact our desired portfolio.

The second approach goes as follows:

[10]:
my_portfolio = rp.RiskParityPortfolio(covariance=Sigma, budget=b)
[11]:
my_portfolio.design()
/Users/mirca/opt/miniconda3/lib/python3.7/site-packages/jax/lib/xla_bridge.py:120: UserWarning: No GPU/TPU found, falling back to CPU.
  warnings.warn('No GPU/TPU found, falling back to CPU.')
  0%|          | 0/500 [00:00<?, ?it/s]
[12]:
my_portfolio.weights
[12]:
array([0.2798628 , 0.08774909, 0.63238811])
[13]:
my_portfolio.risk_contributions
[13]:
array([0.1594, 0.0126, 0.828 ])

The main difference between the two approaches is that the former works only for the vanilla risk parity (budgeting) problem, i.e.: the objective function to be minimized is the risk concentration only, and the constraints are \(\mathbf{w} \geq \mathbf{0}\) and \(\texttt{sum}(\mathbf{w}) = 1\).

The latter approach, however, allows for general linear constraints and the inclusion of additional objective terms such as the mean return and the volatility of the portfolio, as we will cover in the next tutorials.

[ ]: