Last active
September 6, 2024 02:24
-
-
Save Financioneroncios/224fa56e13c6e6070891747510160815 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "attachments": {}, | |
| "cell_type": "markdown", | |
| "id": "d760e6e6", | |
| "metadata": {}, | |
| "source": [ | |
| "# Relativistic Value at Risk Portfolio Optimization\n", | |
| "\n", | |
| "<br>__[Financionerioncios](https://financioneroncios.wordpress.com)__\n", | |
| "<br>__[Dany Cajas](https://www.linkedin.com/in/dany-cajas/)__\n", | |
| "<br>__[Riskfolio-Lib](http://riskfolio-lib.readthedocs.io/)__\n", | |
| "<br>__[Practical Econometrics with Python](https://www.amazon.com/-/es/Marlon-Saito-ebook/dp/B08KJ1322G/ref=sr_1_1?dchild=1&qid=1603904149&refinements=p_27%3AMarlon+Saito&s=digital-text&sr=1-1&text=Marlon+Saito)__ \n", | |
| "<br>__[Econometría Práctica con Python](https://www.amazon.com/-/es/Marlon-Saito-ebook/dp/B08KHZKV9R/ref=sr_1_2?dchild=1&qid=1603903646&refinements=p_27%3AMarlon+Saito&s=digital-text&sr=1-2&text=Marlon+Saito)__ \n", | |
| "\n", | |
| "In this notebook we show how to use the power cone and its application in portfolio optimization.\n", | |
| "\n", | |
| "## 1. Relativistic Value at Risk (RLVaR) Optimization\n", | |
| "\n", | |
| "__[Cajas (2023)](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4378498)__ proposed a generalization of Entropic Value at Risk (EVaR) __[Ahmadi-Javid (2012)](https://link.springer.com/article/10.1007/s10957-011-9968-2?r=1&l=ri&fst=0&error=cookies_not_supported&code=ccfb8a5e-692b-43d1-b76e-ae596c7f0bed)__ based on Kaniadakis entropy __[Kaniadakis (2001)](https://www.sciencedirect.com/science/article/pii/S0378437101001844)__. We can pose the minimization of Relativistic Value at Risk as the following convex programming problem: \n", | |
| "\n", | |
| "$$\n", | |
| "\\begin{equation}\n", | |
| "\\begin{aligned}\n", | |
| "& \\underset{x, z, t, \\psi, \\theta, \\varepsilon, \\omega}{\\text{min}} & & t + z \\ln_{\\kappa} \\left ( \\frac{1}{\\alpha T} \\right ) + \\sum^T_{j=1} \\left ( \\psi_{j} + \\theta_{j} \\right ) \\\\\n", | |
| "& \\text{s.t.} & & -r_{j} x - t + \\varepsilon_{j} + \\omega_{j} \\leq 0 \\; ; \\; \\forall j =1, \\ldots ,T \\\\\n", | |
| "& & & z \\geq 0 \\\\\n", | |
| "& & & \\left ( z \\left ( \\frac{1+\\kappa}{2\\kappa} \\right ), \\psi_{j} \\left ( \\frac{1+\\kappa}{\\kappa} \\right ), \\varepsilon_{j} \\right) \\in \\mathcal{P}_3^{1/(1+\\kappa),\\, \\kappa/(1+\\kappa)} \\\\ \n", | |
| "& & & \\left ( \\omega_{j}\\left ( \\frac{1}{1-\\kappa} \\right ), \\theta_{j}\\left ( \\frac{1}{\\kappa} \\right), -z \\left ( \\frac{1}{2\\kappa} \\right ) \\right ) \\in \\mathcal{P}_3^{1-\\kappa,\\, \\kappa} \\\\\n", | |
| "& & & \\sum_{i=1}^{n} x_i = 1 \\\\\n", | |
| "& & & x_i \\geq 0 \\; ; \\; \\forall \\; i =1, \\ldots, n \\\\\n", | |
| "\\end{aligned}\n", | |
| "\\end{equation}\n", | |
| "\n", | |
| "$$\n", | |
| "\n", | |
| "Where $t$, $z$ $\\psi$, $\\theta$, $\\epsilon$ and $\\omega$ are auxiliary variables, $x$ are the weights of portfolio assets of size $n \\times 1$, $\\mathcal{P}^{\\alpha, 1-\\alpha}$ is a power cone, $r$ is the matrix of observed returns and $\\kappa$ is the deformation parameter of Kaniadakis logarithm." | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "2a19278a", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "[*********************100%***********************] 14 of 14 completed\n" | |
| ] | |
| }, | |
| { | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>BAX</th>\n", | |
| " <th>BMY</th>\n", | |
| " <th>CMCSA</th>\n", | |
| " <th>CNP</th>\n", | |
| " <th>CPB</th>\n", | |
| " <th>GE</th>\n", | |
| " <th>GOOG</th>\n", | |
| " <th>MO</th>\n", | |
| " <th>MSFT</th>\n", | |
| " <th>NI</th>\n", | |
| " <th>SEE</th>\n", | |
| " <th>T</th>\n", | |
| " <th>TGT</th>\n", | |
| " <th>VZ</th>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>Date</th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " <th></th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>2016-01-05</th>\n", | |
| " <td>0.4035%</td>\n", | |
| " <td>1.9693%</td>\n", | |
| " <td>0.0180%</td>\n", | |
| " <td>0.9305%</td>\n", | |
| " <td>0.3678%</td>\n", | |
| " <td>0.0977%</td>\n", | |
| " <td>0.0998%</td>\n", | |
| " <td>2.0213%</td>\n", | |
| " <td>0.4562%</td>\n", | |
| " <td>1.5881%</td>\n", | |
| " <td>0.9759%</td>\n", | |
| " <td>0.6987%</td>\n", | |
| " <td>1.7539%</td>\n", | |
| " <td>1.3734%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2016-01-06</th>\n", | |
| " <td>0.2412%</td>\n", | |
| " <td>-1.7557%</td>\n", | |
| " <td>-0.7727%</td>\n", | |
| " <td>-1.2473%</td>\n", | |
| " <td>-0.1736%</td>\n", | |
| " <td>-1.5940%</td>\n", | |
| " <td>0.1400%</td>\n", | |
| " <td>1.0589%</td>\n", | |
| " <td>-1.8165%</td>\n", | |
| " <td>0.5547%</td>\n", | |
| " <td>-1.5647%</td>\n", | |
| " <td>0.3108%</td>\n", | |
| " <td>-1.0155%</td>\n", | |
| " <td>-0.9034%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2016-01-07</th>\n", | |
| " <td>-1.6573%</td>\n", | |
| " <td>-2.7699%</td>\n", | |
| " <td>-1.1047%</td>\n", | |
| " <td>-1.9770%</td>\n", | |
| " <td>-1.2206%</td>\n", | |
| " <td>-4.2314%</td>\n", | |
| " <td>-2.3170%</td>\n", | |
| " <td>-1.7407%</td>\n", | |
| " <td>-3.4783%</td>\n", | |
| " <td>-2.2067%</td>\n", | |
| " <td>-3.1557%</td>\n", | |
| " <td>-1.6148%</td>\n", | |
| " <td>-0.2700%</td>\n", | |
| " <td>-0.5492%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2016-01-08</th>\n", | |
| " <td>-1.6037%</td>\n", | |
| " <td>-2.5425%</td>\n", | |
| " <td>0.1099%</td>\n", | |
| " <td>-0.2241%</td>\n", | |
| " <td>0.5706%</td>\n", | |
| " <td>-1.7949%</td>\n", | |
| " <td>-1.6410%</td>\n", | |
| " <td>0.1720%</td>\n", | |
| " <td>0.3067%</td>\n", | |
| " <td>-0.1538%</td>\n", | |
| " <td>-0.1448%</td>\n", | |
| " <td>0.0896%</td>\n", | |
| " <td>-3.3839%</td>\n", | |
| " <td>-0.9719%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>2016-01-11</th>\n", | |
| " <td>-1.6851%</td>\n", | |
| " <td>-1.0215%</td>\n", | |
| " <td>0.0914%</td>\n", | |
| " <td>-1.1791%</td>\n", | |
| " <td>0.5674%</td>\n", | |
| " <td>0.4569%</td>\n", | |
| " <td>0.2183%</td>\n", | |
| " <td>2.0947%</td>\n", | |
| " <td>-0.0573%</td>\n", | |
| " <td>1.6436%</td>\n", | |
| " <td>-0.1450%</td>\n", | |
| " <td>1.2224%</td>\n", | |
| " <td>1.4570%</td>\n", | |
| " <td>0.5799%</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " BAX BMY CMCSA CNP CPB GE GOOG \\\n", | |
| "Date \n", | |
| "2016-01-05 0.4035% 1.9693% 0.0180% 0.9305% 0.3678% 0.0977% 0.0998% \n", | |
| "2016-01-06 0.2412% -1.7557% -0.7727% -1.2473% -0.1736% -1.5940% 0.1400% \n", | |
| "2016-01-07 -1.6573% -2.7699% -1.1047% -1.9770% -1.2206% -4.2314% -2.3170% \n", | |
| "2016-01-08 -1.6037% -2.5425% 0.1099% -0.2241% 0.5706% -1.7949% -1.6410% \n", | |
| "2016-01-11 -1.6851% -1.0215% 0.0914% -1.1791% 0.5674% 0.4569% 0.2183% \n", | |
| "\n", | |
| " MO MSFT NI SEE T TGT VZ \n", | |
| "Date \n", | |
| "2016-01-05 2.0213% 0.4562% 1.5881% 0.9759% 0.6987% 1.7539% 1.3734% \n", | |
| "2016-01-06 1.0589% -1.8165% 0.5547% -1.5647% 0.3108% -1.0155% -0.9034% \n", | |
| "2016-01-07 -1.7407% -3.4783% -2.2067% -3.1557% -1.6148% -0.2700% -0.5492% \n", | |
| "2016-01-08 0.1720% 0.3067% -0.1538% -0.1448% 0.0896% -3.3839% -0.9719% \n", | |
| "2016-01-11 2.0947% -0.0573% 1.6436% -0.1450% 1.2224% 1.4570% 0.5799% " | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "####################################\n", | |
| "# Downloading Data\n", | |
| "####################################\n", | |
| "\n", | |
| "import numpy as np\n", | |
| "import pandas as pd\n", | |
| "import yfinance as yf\n", | |
| "import warnings\n", | |
| "\n", | |
| "warnings.filterwarnings(\"ignore\")\n", | |
| "\n", | |
| "yf.pdr_override()\n", | |
| "pd.options.display.float_format = '{:.4%}'.format\n", | |
| "\n", | |
| "# Date range\n", | |
| "start = '2016-01-01'\n", | |
| "end = '2019-12-30'\n", | |
| "\n", | |
| "# Tickers of assets\n", | |
| "assets = ['TGT', 'CMCSA', 'CPB', 'MO', 'T', 'BAX', 'BMY',\n", | |
| " 'MSFT', 'SEE', 'VZ', 'CNP', 'NI', 'GE', 'GOOG']\n", | |
| "assets.sort()\n", | |
| "\n", | |
| "# Downloading data\n", | |
| "data = yf.download(assets, start = start, end = end)\n", | |
| "data = data.loc[:,('Adj Close', slice(None))]\n", | |
| "data.columns = assets\n", | |
| "\n", | |
| "# Calculating returns\n", | |
| "Y = data[assets].pct_change().dropna()\n", | |
| "\n", | |
| "display(Y.head())" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "94d0f382", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "####################################\n", | |
| "# Auxiliary functions\n", | |
| "####################################\n", | |
| "\n", | |
| "# Function that calculates the Kaniadakis logarithm\n", | |
| "def ln_k(x, kappa=0.3):\n", | |
| " return (x**kappa - x**(-kappa))/(2*kappa)" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "583f7d9a", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "data": { | |
| "text/html": [ | |
| "<div>\n", | |
| "<style scoped>\n", | |
| " .dataframe tbody tr th:only-of-type {\n", | |
| " vertical-align: middle;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe tbody tr th {\n", | |
| " vertical-align: top;\n", | |
| " }\n", | |
| "\n", | |
| " .dataframe thead th {\n", | |
| " text-align: right;\n", | |
| " }\n", | |
| "</style>\n", | |
| "<table border=\"1\" class=\"dataframe\">\n", | |
| " <thead>\n", | |
| " <tr style=\"text-align: right;\">\n", | |
| " <th></th>\n", | |
| " <th>Weights</th>\n", | |
| " </tr>\n", | |
| " </thead>\n", | |
| " <tbody>\n", | |
| " <tr>\n", | |
| " <th>BAX</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>BMY</th>\n", | |
| " <td>9.9856%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>CMCSA</th>\n", | |
| " <td>6.9171%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>CNP</th>\n", | |
| " <td>12.0874%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>CPB</th>\n", | |
| " <td>15.2284%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>GE</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>GOOG</th>\n", | |
| " <td>5.4628%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>MO</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>MSFT</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>NI</th>\n", | |
| " <td>17.1999%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>SEE</th>\n", | |
| " <td>14.5753%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>T</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>TGT</th>\n", | |
| " <td>18.5435%</td>\n", | |
| " </tr>\n", | |
| " <tr>\n", | |
| " <th>VZ</th>\n", | |
| " <td>0.0000%</td>\n", | |
| " </tr>\n", | |
| " </tbody>\n", | |
| "</table>\n", | |
| "</div>" | |
| ], | |
| "text/plain": [ | |
| " Weights\n", | |
| "BAX 0.0000%\n", | |
| "BMY 9.9856%\n", | |
| "CMCSA 6.9171%\n", | |
| "CNP 12.0874%\n", | |
| "CPB 15.2284%\n", | |
| "GE 0.0000%\n", | |
| "GOOG 5.4628%\n", | |
| "MO 0.0000%\n", | |
| "MSFT 0.0000%\n", | |
| "NI 17.1999%\n", | |
| "SEE 14.5753%\n", | |
| "T 0.0000%\n", | |
| "TGT 18.5435%\n", | |
| "VZ 0.0000%" | |
| ] | |
| }, | |
| "metadata": {}, | |
| "output_type": "display_data" | |
| } | |
| ], | |
| "source": [ | |
| "####################################\n", | |
| "# Finding the Min EVaR Portfolio\n", | |
| "####################################\n", | |
| "\n", | |
| "import cvxpy as cp\n", | |
| "\n", | |
| "# Defining initial parameters\n", | |
| "returns = Y.to_numpy()\n", | |
| "T, n = Y.shape\n", | |
| "alpha = 0.05\n", | |
| "kappa = 0.3\n", | |
| "\n", | |
| "# Defining initial variables\n", | |
| "w = cp.Variable((n, 1))\n", | |
| "X = returns @ w\n", | |
| "t = cp.Variable((1, 1))\n", | |
| "z = cp.Variable((1, 1), nonneg=True)\n", | |
| "omega = cp.Variable((T, 1))\n", | |
| "psi = cp.Variable((T, 1))\n", | |
| "theta = cp.Variable((T, 1))\n", | |
| "epsilon = cp.Variable((T, 1))\n", | |
| "onesvec = np.ones((T, 1))\n", | |
| "\n", | |
| "constraints = [\n", | |
| " cp.PowCone3D(\n", | |
| " z * (1 + kappa) / (2 * kappa) * onesvec,\n", | |
| " psi * (1 + kappa) / kappa,\n", | |
| " epsilon,\n", | |
| " 1 / (1 + kappa),\n", | |
| " ),\n", | |
| " cp.PowCone3D(\n", | |
| " omega / (1 - kappa),\n", | |
| " theta / kappa,\n", | |
| " -z / (2 * kappa) * onesvec,\n", | |
| " (1 - kappa),\n", | |
| " ),\n", | |
| " -X * 1000 - t * 1000 + epsilon * 1000 + omega * 1000 <= 0,\n", | |
| " cp.sum(w) == 1,\n", | |
| " w >= 0\n", | |
| "]\n", | |
| "\n", | |
| "# Defining risk objective\n", | |
| "risk = t + z * ln_k(1 / (alpha * T), kappa) + cp.sum(psi + theta)\n", | |
| "objective = cp.Minimize(risk)\n", | |
| "\n", | |
| "# Solving problem\n", | |
| "prob = cp.Problem(objective, constraints)\n", | |
| "prob.solve()\n", | |
| "\n", | |
| "# Showing Optimal Weights\n", | |
| "weights = pd.DataFrame(w.value, index=assets, columns=['Weights'])\n", | |
| "display(weights)" | |
| ] | |
| }, | |
| { | |
| "attachments": {}, | |
| "cell_type": "markdown", | |
| "id": "de8cc7f7", | |
| "metadata": {}, | |
| "source": [ | |
| "This portfolio optimization model is available in the CVXPY based library __[Riskfolio-Lib](https://github.com/dcajasn/Riskfolio-Lib)__.\n", | |
| "\n", | |
| "Finally, I hope you liked this example." | |
| ] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3 (ipykernel)", | |
| "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.10.9" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment