Skip to content

Instantly share code, notes, and snippets.

@chrismilson
Created April 20, 2021 05:26
Show Gist options
  • Save chrismilson/19a523c12a8b526e823218f16f705b19 to your computer and use it in GitHub Desktop.
Save chrismilson/19a523c12a8b526e823218f16f705b19 to your computer and use it in GitHub Desktop.
An implementation of Idzorek's approach to the Black-Litterman allocation model
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*This is based on the following paper:*\n",
"\n",
"> \\[1\\] Idzorek, Thomas, A Step-By-Step Guide to the Black-Litterman Model Incorporating User-specified Confidence Levels (November 3, 2019). Available at SSRN: https://ssrn.com/abstract=3479867 or http://dx.doi.org/10.2139/ssrn.3479867\n",
"\n",
"# A Step-By-Step Guide to the Black Litterman Model\n",
"\n",
"The Black Litterman model is a method for modifying an investment portfolio to take account of certain views that the investor may have about the future value or relative direction of the assets involved. To take advantage of the model, the investor must encode their views in the form of three parameters:\n",
"\n",
"- $P$: A matrix whose rows are \"sub-portfolios\" that the investor has views about.\n",
" - The sub portfolios may or may not refer to more than one of the assets in the main portfolio.\n",
"\n",
"- $Q$: A vector whose values are the relative or absolute change of the corresponding sub-portfolio.\n",
" - The value will be relative if the sub-portfolio is long and short different assets.\n",
" - The value will be absolute if the sub-portfolio is only long assets (usually a single asset).\n",
"\n",
"- $\\Omega$: A diagonal matrix representing the uncertainty in the views.\n",
"\n",
"We implement the model here:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def black_litterman_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" tau,\n",
" view_portfolios,\n",
" view_change,\n",
" view_uncertainty\n",
"):\n",
" ER = equilibrium_return\n",
" S = asset_covariance\n",
" t = tau\n",
" P = view_portfolios\n",
" Q = view_change\n",
" O = view_uncertainty\n",
" \n",
" tS_inv = np.linalg.inv(t * S)\n",
" O_inv = np.linalg.inv(O)\n",
" \n",
" return np.linalg.inv(tS_inv + P.T @ O_inv @ P) @ (tS_inv @ ER + P.T @ O_inv @ Q)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*Expected return and portfolio weights are related via our risk preferences and the covariance of the assets as follows:*"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"def get_expected_return(\n",
" weight,\n",
" asset_covariance,\n",
" risk_aversion\n",
"):\n",
" w = weight\n",
" S = asset_covariance\n",
" L = risk_aversion\n",
" \n",
" return L * S @ w\n",
"\n",
"def get_weight(\n",
" expected_return,\n",
" asset_covariance,\n",
" risk_aversion\n",
"):\n",
" ER = expected_return\n",
" S = asset_covariance\n",
" L = risk_aversion\n",
" \n",
" return np.linalg.inv(L * S) @ ER"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Traditionally, $\\Omega$ (the `view_uncertainty` parameter) has been a difficult-to-grasp beast. He and Litterman (1999) provide a method for calculating the uncertainty term, $\\Omega$, so that it is proportional to the variance of the portfolio ($p\\Sigma p'$)."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"def he_litterman_omega(\n",
" asset_covariance,\n",
" tau,\n",
" view_portfolios\n",
"):\n",
" S = asset_covariance\n",
" t = tau\n",
" P = view_portfolios\n",
" \n",
" K, N = P.shape\n",
" O = np.zeros((K, K))\n",
" \n",
" for i in range(K):\n",
" O[i,i] = (P[i,:] @ S @ P[i,:].T) * t\n",
" \n",
" return O\n",
"\n",
"# A wrapper for the Black-Litterman model that uses the He-Litterman omega\n",
"def he_litterman_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" view_portfolios,\n",
" view_change\n",
"):\n",
" tau = 1\n",
" return black_litterman_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" tau,\n",
" view_portfolios,\n",
" view_change,\n",
" he_litterman_omega(\n",
" asset_covariance,\n",
" tau,\n",
" view_portfolios\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Idzorek outlines a method to produce $\\Omega$ from confidence level in each view, represented as a percentage. We produce $\\Omega$ from these confidence levels by optimising on a per-view basis."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"def idzorek_omega(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" tau,\n",
" risk_free_rate,\n",
" risk_aversion,\n",
" view_portfolios,\n",
" view_change,\n",
" view_confidence\n",
"):\n",
" ER = equilibrium_return\n",
" S = asset_covariance\n",
" t = tau\n",
" rr = risk_free_rate\n",
" L = risk_aversion\n",
" P = view_portfolios\n",
" Q = view_change\n",
" C = view_confidence\n",
" \n",
" w_mkt = np.linalg.inv(L * S) @ ER\n",
" \n",
" K, N = P.shape\n",
" O = np.zeros((K, K))\n",
" \n",
" # We treat each view separately\n",
" for i in range(K):\n",
" p = P[i,:]\n",
" q = Q[i] - ((p.sum() != 0) * rr)\n",
" c = C[i]\n",
" \n",
" D = (t/L) * (q - p @ ER) * p / (p @ S @ p.T)\n",
" Tilt = D * ((p != 0) * c)\n",
" \n",
" w_target = w_mkt + Tilt\n",
" \n",
" def w(o):\n",
" return np.linalg.inv(np.identity(N)/t + np.outer(p, p) @ S / o) @ (w_mkt / t + p * q / o / L)\n",
" \n",
" def sum_squared_difference(o):\n",
" diff = w_target - w(o)\n",
" return np.dot(diff, diff)\n",
" \n",
" O[i,i] = min(np.linspace(0,1,1000)[1:], key=sum_squared_difference)\n",
" \n",
" return O\n",
"\n",
"# A wrapper for the Black-Litterman model that uses Idzorek's new method for calculating omega\n",
"def idzorek_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" risk_free_rate,\n",
" risk_aversion,\n",
" view_portfolios,\n",
" view_change,\n",
" view_confidence\n",
"):\n",
" tau = 1\n",
" return black_litterman_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" tau,\n",
" view_portfolios,\n",
" view_change,\n",
" idzorek_omega(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" tau,\n",
" risk_free_rate,\n",
" risk_aversion,\n",
" view_portfolios,\n",
" view_change,\n",
" view_confidence\n",
" )\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The Idzorek method stems from taking a weighted average of 0% confidence in the views (the market weight / equilibrium return) and 100% confidence in the views:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"# The return based on 100% confidence in the views\n",
"def certain_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" view_portfolios,\n",
" view_change\n",
"):\n",
" ER = equilibrium_return\n",
" S = asset_covariance\n",
" P = view_portfolios\n",
" Q = view_change\n",
" \n",
" return ER + S @ P.T @ np.linalg.inv(P @ S @ P.T) @ (Q - P @ ER)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The paper tracks an example portfolio of eight assets:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"# The names of the assets\n",
"assets = np.array([\n",
" \"US Bonds\",\n",
" \"International Bonds\",\n",
" \"US Large Growth\",\n",
" \"US Large Value\",\n",
" \"US Small Growth\",\n",
" \"US Small Value\",\n",
" \"International Developed Equity\",\n",
" \"International Emerging Equity\"\n",
"])\n",
"\n",
"# The market capitalisation weights of the assets\n",
"market_weight = np.array([\n",
" 19.34,\n",
" 26.13,\n",
" 12.09,\n",
" 12.09,\n",
" 1.34,\n",
" 1.34,\n",
" 24.18,\n",
" 3.49\n",
"]) / 100\n",
"\n",
"# The covariance matrix for the assets\n",
"asset_covariance = np.array([[0.001005, 0.001328, -0.000579, -0.000675, 0.000121, 0.000128, -0.000445, -0.000437],\n",
" [0.001328, 0.007277, -0.001307, -0.000610, -0.002237, -0.000989, 0.001442, -0.001535],\n",
" [-0.000579, -0.001307, 0.059852, 0.027588, 0.063497, 0.023036, 0.032967, 0.048039],\n",
" [-0.000675, -0.000610, 0.027588, 0.029609, 0.026572, 0.021465, 0.020697, 0.029854],\n",
" [0.000121, -0.002237, 0.063497, 0.026572, 0.102488, 0.042744, 0.039943, 0.065994],\n",
" [0.000128, -0.000989, 0.023036, 0.021465, 0.042744, 0.032056, 0.019881, 0.032235],\n",
" [-0.000445, 0.001442, 0.032967, 0.020697, 0.039943, 0.019881, 0.028355, 0.035064],\n",
" [-0.000437, -0.001535, 0.048039, 0.029854, 0.065994, 0.032235, 0.035064, 0.079958]])\n",
"\n",
"# The risk aversion coefficient\n",
"risk_aversion = 3.065\n",
"\n",
"# This lets us calculate the equilibrium return vector\n",
"equilibrium_return = get_expected_return(market_weight, asset_covariance, risk_aversion)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The example views in the paper are:\n",
"\n",
"1. International Developed Equity will have an absolute excess return of 5.25% (Confidence of View = 25%).\n",
"2. International Bonds will outperform US Bonds by 25 basis points (Confidence of View = 50%).\n",
"3. US Large Growth and US Small Growth will outperform US Large Value and US Small Value by 2% (Confidence of View = 65%).\n",
"\n",
"We represent these views as $P$, $Q$, and $C$:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"# The sub-portfolios representing our views, P\n",
"# Here, the short and long parts are weighted relative to their market capitalisation\n",
"view_portfolios = np.array([[0, 0, 0, 0, 0, 0, 1, 0],\n",
" [-1, 1, 0, 0, 0, 0, 0, 0],\n",
" [0, 0, .9, -.9, .1, -.1, 0, 0]])\n",
"\n",
"# The change from equilibrium that we expect, Q\n",
"view_change = np.array([0.0525, 0.0025, 0.02])\n",
"\n",
"# The confidence level we have in each view, C\n",
"view_confidence = np.array([0.25, 0.50, 0.65])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAX4AAAD4CAYAAADrRI2NAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/d3fzzAAAACXBIWXMAAAsTAAALEwEAmpwYAAAt2klEQVR4nO3de1xUdf748ddbQjENtLyEWl5K8QaCghco75ZrSlmamRp8LU3XW1bbqvXNG1u263czq81MUykrky5a2VZrYgYaio6iqGsa7VpkZnkhMgU/vz9mOD9GYByRmQHn/Xw85gHnnDmf854R3/OZz/mc9xFjDEoppfxHNV8HoJRSyrs08SullJ/RxK+UUn5GE79SSvkZTfxKKeVnrvB1AO6oV6+eadasma/DUEqpKiUzM/MnY0z989dXicTfrFkztm3b5uswlFKqShGRb0tbr0M9SinlZzTxK6WUn9HEr5RSfqZKjPGri3f27FkOHz7M6dOnfR2KUpckKCiIJk2aEBgY6OtQLhua+C9Thw8f5qqrrqJZs2aIiK/DUapcjDEcO3aMw4cP07x5c1+Hc9nQoZ7L1OnTp7nmmms06asqTUS45ppr9JtrBdPEfxnTpK8uB/p3XPE08SullJ/RMX4/0WzaRxXaXs682y74HBFhxIgRvP766wAUFBQQGhpKly5d+PDDD90+VmpqKvPnz3d7n+XLl3PLLbfQqFGjUrfPnz+fJUuWEBQURGBgIJMmTeK+++5zO54ia9euJTs7m2nTpvH+++/TqlUr2rZt63KfWbNmUbt2bR599FGefPJJunfvTt++fS/quKmpqVSvXp3Y2FgAFi1axJVXXlmu11Dc4MGDSUhI4I477gAgLCyMUaNG8cQTTwBw1113MWLECO68885S93/ggQd4+OGHXb4HiYmJDBw4kCFDhjitz8nJIT09nXvvvfeSXoNyj/b4z7O3dRunhyq/WrVqsXv3bn777TcAPvvsMxo3bnxRbRQUFFz0cZcvX873339f6rZFixbx2WefkZGRgc1mY/369ZT3ZkTx8fFMmzYNgPfff5/s7OyL2n/OnDkXnfTBnvjT09Ot5XHjxl1y0geIi4uz2j127Bi1atVi8+bN1vbNmzdbHzalWbJkyQU/+MqSk5PDG2+8Ua591cXTxK88asCAAXz0kf3bxptvvsnw4cOtbRkZGXTr1o2oqChiY2PZv38/YE/c8fHx9O7dmz59+ji1t3XrVqKiojh48CCZmZn06NGDTp06ceutt5Kbm0tKSgrbtm1jxIgRREZGWh86RZ566ileeuklgoODAQgODiYhIQGwJ+KYmBjat2/P2LFjrQ+Enj17MmXKFCIjI2nfvj0ZGRlWnBMnTiQ9PZ21a9fypz/9icjISA4ePMgrr7xCTEwMHTp04K677iI/P7/Ee5OYmEhKSgoA06ZNo23btkRERPDoo48C8MEHH9ClSxeioqLo27cvR44cIScnh0WLFvHss88SGRnJpk2bmDVrFvPnzwfAZrPRtWtXIiIiGDx4ML/88ov1Gv785z/TuXNnWrVqxaZNm0rEExsbayX+9PR0Bg0axNGjRzHG8M0331CzZk2uvfZaPv30U7p160bHjh0ZOnQoeXl51jGKSqssXbqUVq1a0blzZ8aMGcPEiROt43zxxRfExsbSokULp9e/adMmIiMjefbZZ0v/Y1IVRhO/8qh77rmHt956i9OnT7Nr1y66dOlibWvdujWbNm1ix44dzJkzhxkzZljbtm/fTkpKChs3brTWpaenM27cONasWcP111/PpEmTSElJITMzk9GjR/P4448zZMgQoqOjWblyJTabjZo1a1r7nzx5klOnTtGiRYtSY504cSJbt261vqUUH1rKz8/HZrPxj3/8g9GjRzvtFxsbS3x8PH/729+w2WzccMMN3HnnnWzdupWdO3fSpk0bli5dWuZ7dOzYMd577z327NnDrl27rKGVm266iS1btrBjxw7uuece/vrXv9KsWTPGjRvH1KlTsdls3HzzzU5t3XfffTzzzDPs2rWL8PBwZs+ebW0rKCggIyODBQsWOK0v0qlTJ3bv3s2ZM2dIT0+nW7duhIWFsXfvXtLT04mNjeWnn34iKSmJf/3rX2zfvp3o6Gj+/ve/O7Xz/fffM3fuXLZs2UJaWhr79u1z2p6bm8uXX37Jhx9+aH1jmjdvHjfffDM2m42pU6eW+V6piqFj/MqjIiIiyMnJ4c0332TAgAFO206cOEFCQgIHDhxARDh79qy1rV+/flx99dXW8t69exk7diyffvopjRo1Yvfu3ezevZt+/foBUFhYSGho6CXFumHDBv7617+Sn5/Pzz//TLt27Rg0aBCA9U2le/funDx5kuPHj7tsa/fu3TzxxBMcP36cvLw8br31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5iKJiYkMHDiQIUOGVGhMRcoqTVxkzZo1LFu2jPfffx+Ap59+mqVLl/L1118D8MEHH/DKK6+wdu3aUvdfu3Yt2dnZTJs2rcwYUlNTmT9/fqkXVy1YsICxY8dy5ZVXXuQrU6piaI9fVUmXUoogNjaWLVu2WMubN28mODjYulq2qGBaWeLj410m/QtZsGAB+fn55d5fqUuliV95nDGGiRMnEhYWRt++fa0Eu23bNqtyZ3h4OPbirfbyDV27diUiIoLBgwfzyy+/APae/EMPPUR0dDTPPfccmZmZ9OjRg06dOnHrrbeSm5vrdNxz586RmJjIE0884bS+fv36BAcHWz387777jrvuusupcmZcXFyZpaOXL1/OxIkTATh48CBdu3YlPDycJ554wqnIXF5eHkOGDKF169aMGDECYwwLFy7k+++/p1evXvTq1aui32ql3KKJX3nce++9x/79+8nOziY5OdlKsNHR0dhsNmw2G/379+fRRx8F4L777uOZZ55h165dhIeHM3v2bKutM2fOsG3bNiZPnsykSZNISUkhMzOT0aNH8/jjj1vPKygoYMSIEbRs2ZKkpKQSMRWVSN6/fz8tW7aka9eupKenU1BQwM6dO4mJiXGrdPSUKVOYMmUKWVlZNGnSxGnbjh07WLBgAdnZ2Rw6dIi0tDQmT55Mo0aN2LBhAxs2bKiQ91epi6Vj/MrjvvjiC4YPH05AQACNGjWid+/eTttXrVrF9u3b+fTTTzlx4gTHjx+nR48eACQkJDiVVS6qMbN//352795Nv379ACgsLCQ0NNR63oMPPsjdd9/t9GFQXNFNUQoLC+nWrRudO3dmzpw57Nixg9atWxMUFFRm6ejiNm/ebJ0ruPfee60PL4DOnTtbHwaRkZHk5ORw0003XdR7p5QnaOJXPrV7925mzZrFF1984VQbvyxFpZSNMbRr147NmzeX+rzY2Fg2bNjAI488UqL0M9h7/M8//zyFhYWMGTOGq666itOnT5OammqN75dVOtpdxUs7a4lkVZnoUI/yuO7du7Nq1SoKCwvJzc21hjiOHz/O8OHDSU5Opn79+gCEhIRQt25dNm3aBMBrr71m9f6LCwsL4+jRo1biP3v2LHv27LG233///QwYMIC777671ITbpk0bvv/+e7788kuioqIAe6980aJFVtXNskpHF9e1a1feeecdAN566y233g8tkax8TXv8fsKd6ZeeMnjwYD7//HPatm3L9ddfb5UkXrNmDd9++y1jxoyxnmuz2VixYgXjxo0jPz+fFi1asGzZshJtVq9enZSUFCZPnsyJEycoKCjgoYceol27dtZzHn74YU6cOMGoUaNYuXIl1ar9/36OiNClSxdOnDjhVPJ58eLFVo/fndLRCxYsYOTIkfzlL3+hf//+FyyPDPYCa/3797fG+pXyNq+UZb5UWpb54mkZW+/Iz8+nZs2aiAhvvfUWb775JmvW6C0mKpr+PZePT8syK3W5yszMZOLEiRhjqFOnDq+++qqvQ1LqgjTxK3UJbr755ku6naNSvqCJXynlFy6XYdyKoLN6lFLKz2jiV0opP6OJXyml/Iwmfj+xt3WbCn24Y/To0TRo0ID27ds7rf/555/p168fLVu2pF+/flYRNmMMkydP5sYbbyQiIoLt27cD9vIMnTp1IiIiwrpgq6CggL59+7qscjl//nxat25NZGQkMTExJCcnl+et4/fff6dv375ERkayatUqHnjgAadSDkWKF2/zpqioKOvisoKCAmrXrs3rr79ube/UqZP1XpZmwIABHD9+3OUxevbsSWlTqm02G+vWrStX3Mp3NPErj0lMTOSf//xnifXz5s2jT58+HDhwgD59+jBv3jwAPv74Yw4cOMCBAwdYvHgx48ePB+Dll1/mueeeY926dcyfPx+Al156iZEjR5ZZ037RokV89tlnZGRkYLPZWL9+PeW9ZmXHjh2APckNGzaMJUuW0LZt23K15QlFBecAdu7cSatWrazlX3/9lYMHD9KhQ4cy91+3bh116tQp17E18VdNmviVx3Tv3p2rr766xPo1a9aQkJAA2IuwFRU5W7NmDffddx8iQteuXTl+/Di5ubkEBgaSn59Pfn4+gYGBHD9+nA8++ID77ruvzGM/9dRTvPTSSwQHBwMQHBxsHXP9+vVERUURHh7O6NGj+f333wFo1qwZM2fOpGPHjoSHh7Nv3z5+/PFHRo4cydatW4mMjOTgwYNOvd9ly5bRqlUrOnfubJVtBsos6Txr1ixGjx5Nz549adGiBQsXLrT2SU5OJiIigg4dOjBq1CiX7RRXVHAO7CWlx40bZ30DyMjIoFOnTgQEBPD666/TuXNnIiMjefDBByksLLRe908//QTA3LlzCQsL46abbmL48OHWBy3A6tWr6dy5M61atWLTpk2cOXOGJ598klWrVlnfhlTVoIlfed2RI0esSprXXnstR44cAex18a+77jrreU2aNOG7775jwoQJPPXUUyQkJDBjxgzmzp3LjBkznEowFHfy5ElOnTpFixYtSmw7ffo0iYmJrFq1iqysLAoKCnjppZes7fXq1WP79u2MHz+e+fPn06BBA5YsWcLNN9+MzWbjhhtusJ6bm5vLzJkzSUtL48svv3Qa/nFV0nnfvn188sknZGRkMHv2bKvOUFJSEp9//jk7d+7kueeeu2A7RYr3+NPT0+nevTs1atTg1KlT1k1l9u7dy6pVq0hLS8NmsxEQEMDKlSud2ik6xs6dO/n4449LDO0UFBSQkZHBggULmD17NtWrV2fOnDkMGzbM+jakqgadx698SkSsG7CU5frrryc1NRWAr7/+msOHD9OmTRtGjRrFmTNnmDt3Lq1atXLrePv376d58+bW8xMSEnjxxRd56KGHALjzzjsB+7j4u+++67Ktr776ip49e1oF5oYNG8a///1vAJclnW+77TZq1KhBjRo1aNCgAUeOHOHzzz9n6NCh1KtXD8D6plRWO8Vv+NK0aVPOnDnDDz/8wL59+wgLCyMmJoavvvqK9PR0Jk2axPr168nMzCQmJgaA3377jQYNGji9nrS0NG6//XaCgoIICgpi0KBBTtuLvzc5OTku3xtVuWniV17XsGFDcnNzCQ0NJTc310pAjRs35r///a/1vMOHD9O4cWOnfR9//HGSkpJYuHAhDzzwAM2aNWPGjBlOvdfg4GBq167NoUOHSu31u1JUSvlSyyi7Kul8MeWa3S0NHRsby+rVqwkNDbWGytLS0sjIyKBbt24cOHCAhIQEnn766XK/pop6b5Tv6VCP8rr4+HhWrFgBwIoVK7j99tut9cnJyRhj2LJlCyEhIU43V9m4cSONGjWiZcuW5OfnU61aNapVq1bqzJ7p06czYcIETp48Cdhvg5icnExYWBg5OTnWbRfLKvvsji5durBx40aOHTvG2bNnWb16tbXNnZLOxfXu3ZvVq1dz7NgxwD7z6WLaiY2NZcGCBVbl027dupGcnMy1115LSEgIffr0ISUlxbrt5c8//8y3337r1EZcXBwffPABp0+fJi8vr9QbxZ9PS0xXTRfs8YtIAyAOaAT8BuwGthljznk4NlWBfHF5+vDhw0lNTeWn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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"he_litterman_weight = get_weight(\n",
" he_litterman_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" view_portfolios,\n",
" view_change\n",
" ),\n",
" asset_covariance,\n",
" risk_aversion\n",
")\n",
"\n",
"idzorek_weight = get_weight(\n",
" idzorek_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" 0, # We will use a risk-free rate of 0\n",
" risk_aversion,\n",
" view_portfolios,\n",
" view_change,\n",
" view_confidence\n",
" ),\n",
" asset_covariance,\n",
" risk_aversion\n",
")\n",
"\n",
"certain_weight = get_weight(\n",
" certain_return(\n",
" equilibrium_return,\n",
" asset_covariance,\n",
" view_portfolios,\n",
" view_change\n",
" ),\n",
" asset_covariance,\n",
" risk_aversion\n",
")\n",
"\n",
"x = np.arange(len(assets))\n",
"bar_width = 0.1\n",
"\n",
"fig, ax = plt.subplots()\n",
"market_b = ax.bar(x + bar_width * -1.5, market_weight * 100, bar_width, label=\"Market Capitalisation Weight\")\n",
"he_lit_b = ax.bar(x + bar_width * -0.5, he_litterman_weight * 100, bar_width, label=\"He-Litterman Weight\")\n",
"idz_b = ax.bar(x + bar_width * 0.5, idzorek_weight * 100, bar_width, label=\"Idzorek Weight\")\n",
"certain_b = ax.bar(x + bar_width * 1.5, certain_weight * 100, bar_width, label=\"100% Confidence Weight\")\n",
"\n",
"ax.set_ylabel(\"Portfolio Weight (%)\")\n",
"# ax.set_xticks(x)\n",
"# ax.set_xticklabels(assets)\n",
"ax.legend()\n",
"\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment