{ "cells": [ { "cell_type": "markdown", "id": "6b0b3c2f-3aaa-43fe-a8d0-2b696df5c1a6", "metadata": { "tags": [] }, "source": [ "```{index} single: AMPL; AMPL Python API\n", "```\n", "```{index} single: AMPL MP Library\n", "```\n", "```{index} single: application; portfolio\n", "```\n", "```{index} single: application; investment\n", "```\n", "```{index} single: solver; mosek\n", "```\n", "\n", "# Markowitz portfolio optimization revisited" ] }, { "cell_type": "code", "execution_count": 1, "id": "5da22c67-5c34-4c3a-90a4-61222899e855", "metadata": { "tags": [] }, "outputs": [], "source": [ "# install dependencies and select solver\n", "%pip install -q amplpy numpy pandas matplotlib\n", "\n", "SOLVER_CONIC = \"mosek\" # ipopt, mosek, gurobi, knitro\n", "\n", "from amplpy import AMPL, ampl_notebook\n", "\n", "ampl = ampl_notebook(\n", " modules=[\"coin\", \"mosek\"], # modules to install\n", " license_uuid=\"default\", # license to use\n", ") # instantiate AMPL object and register notebook magics" ] }, { "cell_type": "code", "execution_count": 2, "id": "b13edf26", "metadata": { "tags": [] }, "outputs": [], "source": [ "from IPython.display import Markdown, HTML\n", "import numpy as np\n", "import matplotlib.pyplot as plt" ] }, { "cell_type": "markdown", "id": "a82bd88d-7b16-4c82-b0b7-5dbd0d81b71c", "metadata": { "tags": [] }, "source": [ "## Problem description and model formulation\n", "\n", "Consider again the [Markowitz portfolio optimization](../05/markowitz_portfolio.ipynb) we presented earlier in Chapter 5. Recall that the matrix $\\Sigma$ describes the covariance among the uncertain return rates $r_i$, $i=1,\\dots, n$. Since $\\Sigma$ is positive semidefinite by definition, it allows for a Cholesky factorization, namely $\\Sigma = B B^\\top$. We can then rewrite the quadratic constraint as $\\|B^\\top x \\|_2 \\leq \\gamma$ and thus as $(\\gamma, B^\\top x) \\in \\mathcal{L}^{n+1}$ using the Lorentz cone. In this way, we realize that the original portfolio problem we formulated [earlier](../05/markowitz_portfolio.ipynb) is in fact a conic quadratic optimization problem, which can thus be solved faster and more reliably. The optimal solution of that problem was the one with the maximum expected return while allowing for a specific level $\\gamma$ of risk. \n", "\n", "However, an investor could aim for a different trade-off between return and risk and formulate a slightly different optimization problem, namely\n", "\n", "$$\n", "\\begin{align*}\n", " \\max \\quad & R \\tilde{x} + \\mu^\\top x - \\alpha x^\\top \\Sigma x \\\\\n", " \\text{s.t.}\\quad\n", " & \\sum_{i=1}^n x_i + \\tilde{x} = C \\\\\n", " & \\tilde x \\geq 0\\\\\n", " & x_i \\geq 0 & \\forall \\, i=1,\\dots,n. \n", "\\end{align*}\n", "$$\n", "\n", "where $\\alpha \\geq 0$ is a *risk tolerance* parameter that describes the relative importance of return vs. risk for the investor.\n", "\n", "The risk, quantified by the variance of the investment return $x^\\top \\Sigma x = x^\\top B^\\top B x$, appears now in the objective function as a penalty term. Note that even in this new formulation we have a conic problem since we can rewrite it as\n", "\n", "$$\n", "\\begin{align*}\n", " \\max \\quad & R \\tilde{x} + \\mu^\\top x - \\alpha s \\\\\n", " \\text{s.t.}\\quad\n", " & \\sum_{i=1}^n x_i + \\tilde{x} = C \\\\\n", " & \\| B^\\top x\\|^2_2 \\leq s \\\\\n", " & \\tilde x \\geq 0 \\\\\n", " & s \\geq 0\\\\\n", " & x_i \\geq 0 & \\forall \\, i=1,\\dots,n. \n", "\\end{align*}\n", "$$\n", "\n", "Solving for all values of $\\alpha \\geq 0$, one can obtain the so-called **efficient frontier**." ] }, { "cell_type": "code", "execution_count": 3, "id": "97eb9dda", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Overwriting markowitz_portfolio_revisited.mod\n" ] } ], "source": [ "%%writefile markowitz_portfolio_revisited.mod\n", "\n", "# Specify the initial capital, the risk tolerance, and the guaranteed return rate. \n", "param C;\n", "param alpha;\n", "param R;\n", "\n", "# Specify the number of assets, their expected return, and their covariance matrix.\n", "param n;\n", "param mu{1..n};\n", "param Sigma{1..n, 1..n};\n", "\n", "var xtilde >= 0;\n", "var x{1..n} >= 0;\n", "var s >= 0;\n", " \n", "maximize Objective:\n", " sum {i in 1..n} mu[i]*x[i] + R*xtilde - alpha*s;\n", " \n", "s.t. BoundedVariance:\n", " sum {i in 1..n, j in 1..n} x[i]*Sigma[i,j]*x[j] <= s;\n", " \n", "s.t. TotalAssets:\n", " sum {i in 1..n} x[i] + xtilde == C;\n", " " ] }, { "cell_type": "code", "execution_count": 4, "id": "0e194e8d", "metadata": { "scrolled": true, "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MOSEK 10.0.43: \b\b\b\b\b\b\b\b\b\b\b\b\b\b\bMOSEK 10.0.43: optimal; objective 1.12065217\n", "0 simplex iterations\n", "8 barrier iterations\n" ] }, { "data": { "text/markdown": [ "**Solver status:** *solved*" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "**Solution:** $\\tilde x = 0.283$ $x_1 = 0.478$, $x_2 = 0.130$, $x_3 = 0.109$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/markdown": [ "**Maximizes objective value to:** $1.12$" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "# Specify the initial capital, the risk tolerance, and the guaranteed return rate.\n", "C = 1\n", "alpha = 0.1\n", "R = 1.05\n", "\n", "# Specify the number of assets, their expected return, and their covariance matrix.\n", "n = 3\n", "mu = np.array([1.25, 1.15, 1.35])\n", "Sigma = np.array([[1.5, 0.5, 2], [0.5, 2, 0], [2, 0, 5]])\n", "\n", "# If you want to change the covariance matrix Sigma, ensure you input a semi-definite positive one.\n", "# The easiest way to generate a random covariance matrix is first generating a random m x m matrix A\n", "# and then taking the matrix A^T A (which is always semi-definite positive)\n", "# m = 3\n", "# A = np.random.rand(m, m)\n", "# Sigma = A.T @ A\n", "#\n", "# Moreover, in practive such a matrix A, called factor, can be low-rank,\n", "# see https://docs.mosek.com/modeling-cookbook/qcqo.html#example-factor-model.\n", "# This would provide better numerical properties for the proper conic formulation\n", "# y=Ax, |y|^2 <= s,\n", "# corresponding to the mathematical formulation above.\n", "\n", "\n", "def markowitz_revisited(alpha, mu, Sigma):\n", " ampl = AMPL()\n", " ampl.read(\"markowitz_portfolio_revisited.mod\")\n", "\n", " ampl.param[\"C\"] = C\n", " ampl.param[\"alpha\"] = alpha\n", " ampl.param[\"R\"] = R\n", "\n", " ampl.param[\"n\"] = n\n", " ampl.param[\"mu\"] = mu\n", " ampl.param[\"Sigma\"] = {\n", " (i + 1, j + 1): Sigma[i][j] for i in range(n) for j in range(n)\n", " }\n", "\n", " ampl.solve(solver=SOLVER_CONIC)\n", " assert ampl.solve_result == \"solved\", ampl.solve_result\n", "\n", " return ampl\n", "\n", "\n", "ampl = markowitz_revisited(alpha, mu, Sigma)\n", "xtilde = ampl.get_variable(\"xtilde\").value()\n", "x = ampl.get_variable(\"x\").to_dict()\n", "\n", "display(Markdown(f\"**Solver status:** *{ampl.solve_result}*\"))\n", "display(\n", " Markdown(\n", " f\"**Solution:** $\\\\tilde x = {xtilde:.3f}$\"\n", " f\" $x_1 = {x[1]:.3f}$, $x_2 = {x[2]:.3f}$, $x_3 = {x[3]:.3f}$\"\n", " )\n", ")\n", "display(\n", " Markdown(\n", " f\"**Maximizes objective value to:**\"\n", " f\" ${ampl.get_objective('Objective').value():.2f}$\"\n", " )\n", ")" ] }, { "cell_type": "code", "execution_count": 5, "id": "9a2b00d7-433a-46c8-a4b6-c451244c9b0f", "metadata": { "tags": [] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.324999981\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.299999995\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.251999955\n", "0 simplex iterations\n", "9 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.221333307\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.199047619\n", "0 simplex iterations\n", "10 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.180952352\n", "0 simplex iterations\n", "7 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.165238086\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.150884338\n", "0 simplex iterations\n", "9 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.138315214\n", "0 simplex iterations\n", "7 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.128502403\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.12065217\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.114229246\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.108876806\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.104347815\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.100465835\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.097101441\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.094157586\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.091560078\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.089251187\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.087185341\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.085326081\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.078260869\n", "0 simplex iterations\n", "8 barrier iterations\n", "MOSEK 10.0.43:MOSEK 10.0.43: optimal; objective 1.064130422\n", "0 simplex iterations\n", "9 barrier iterations\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAkAAAAGxCAYAAACKvAkXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABMV0lEQVR4nO3deXRTZf4G8Oem2bovdIfSFgqUtRSwWHYEBEQUcEYF1Iq4jKKCDCr8BBVQUAYVVGYQFAGHRXCdUYatCMhOS4tssraUQltauqal6ZL7+6M0Elsgt01y0+T5nJMjuXlz8809Sh7f+y6CKIoiiIiIiJyIQu4CiIiIiGyNAYiIiIicDgMQEREROR0GICIiInI6DEBERETkdBiAiIiIyOkwABEREZHTUcpdgD0yGAy4cuUKPD09IQiC3OUQERGRGURRRElJCUJDQ6FQ3L6PhwGoHleuXEFYWJjcZRAREVEDXLp0CS1atLhtGwagenh6egKouYBeXl4yV0NERETmKC4uRlhYmPF3/HYYgOpRe9vLy8uLAYiIiKiJMWf4CgdBExERkdNhACIiIiKnwwBERERETocBiIiIiJwOAxARERE5HQYgIiIicjoMQEREROR0GICIiIjI6TAAERERkdNhACIiIiKnwwBERERETocBiIiIiJwOA5ANGQwisovKkXGtTO5SiIiInBoDkA2tOXgRd89PxNyfT8pdChERkVNjALKhls3cAQAXr5XKXAkREZFzYwCyoUhjACqDwSDKXA0REZHzYgCyoVAfLZQKAfoqA7KLy+Uuh4iIyGkxANmQ0kWBMD83AEA6b4MRERHJhgHIxsKb1QSgi5wJRkREJBsGIBuLuDEOiD1ARERE8mEAsrGIGz1A6XkMQERERHJhALKxcP8/ZoIRERGRPBiAbOzmW2CiyKnwREREcmAAsrEWvq5wUQgorzTgaole7nKIiIicEgOQjalcFGjh6woASOM4ICIiIlkwAMkgnFtiEBERyYoBSAbGmWAcCE1ERCQLBiAZGAdC8xYYERGRLBiAZBDhzx4gIiIiOTEAyeDmMUCcCk9ERGR7DEAyCPN1g0IAyiqqkavjVHgiIiJbYwCSgVqpQPMbU+HT83gbjIiIyNYYgGTCTVGJiIjkwwAkk/AbU+G5FhAREZHtMQDJ5I8eIN4CIyIisjUGIJlwLSAiIiL5MADJpHYtoIvXyjgVnoiIyMYYgGTSwtcNggDo9FW4VlohdzlEREROhQFIJlqVC0K9a6bCcyA0ERGRbTEAyaj2Nlga1wIiIiKyKQYgGd28JQYRERHZDgOQjCKacVNUIiIiOcgagHbv3o2RI0ciNDQUgiDghx9+uG37PXv2oHfv3mjWrBlcXV0RHR2Njz76qE67JUuWICIiAlqtFj179sShQ4es9A0ahz1ARERE8pA1AJWWliImJgZLliwxq727uztefPFF7N69G6dOncLMmTMxc+ZMLFu2zNjm66+/xtSpU/HWW2/hyJEjiImJwdChQ3H16lVrfY0Gi/SvCUBpedwVnoiIyJYE0U5+eQVBwPfff49Ro0ZJet+YMWPg7u6Or776CgDQs2dP3HXXXfj0008BAAaDAWFhYXjppZcwffp0s85ZXFwMb29vFBUVwcvLS1I9UpRXViN61mYAwJFZQ+DnrrbaZxERETk6Kb/fTXoMUEpKCvbt24f+/fsDACoqKpCcnIzBgwcb2ygUCgwePBj79++/5Xn0ej2Ki4tNHragVbkgxFsLoKYXiIiIiGyjSQagFi1aQKPRoEePHpg0aRKefvppAEBeXh6qq6sRFBRk0j4oKAjZ2dm3PN/8+fPh7e1tfISFhVm1/ptFcBwQERGRzTXJAPTrr78iKSkJS5cuxaJFi7Bu3bpGnW/GjBkoKioyPi5dumShSu8s4qZxQERERGQbSrkLaIjIyEgAQOfOnZGTk4O3334bY8eOhb+/P1xcXJCTk2PSPicnB8HBwbc8n0ajgUajsWrNt9LqRgC6wABERERkM02yB+hmBoMBer0eAKBWq9G9e3ckJiaavJ6YmIj4+Hi5Sryt2plg3BWeiIjIdmTtAdLpdDh37pzxeVpaGlJTU+Hn54eWLVtixowZuHz5MlavXg2gZn2fli1bIjo6GkDNOkILFy7Eyy+/bDzH1KlTkZCQgB49eiAuLg6LFi1CaWkpJkyYYNsvZ6bIANOp8IIgyFwRERGR45M1ACUlJWHgwIHG51OnTgUAJCQkYOXKlcjKykJGRobxdYPBgBkzZiAtLQ1KpRKtW7fG+++/j+eee87Y5pFHHkFubi7efPNNZGdno2vXrti8eXOdgdH2IszXDQoBKKuoxtUSPYK8tHKXRERE5PDsZh0ge2KrdYBq9f/HL7h4rQzrnrkb8a2bWf3ziIiIHJHTrAPkKIzjgDgVnoiIyCYYgOxA7VpAnApPRERkGwxAdqDVjYHQF3IZgIiIiGyBAcgO8BYYERGRbTEA2YHaAHTxWimqDRyTTkREZG0MQHYg1NsVaqUCldUiLhdcl7scIiIih8cAZAcUCgERzdwAABfydDJXQ0RE5PgYgOwEt8QgIiKyHQYgOxHp7wGAU+GJiIhsgQHITkT6194CYwAiIiKyNgYgO8EeICIiItthALITtWOALhdeh76qWuZqiIiIHBsDkJ3w91DDQ6OEKAIZ18rkLoeIiMihMQDZCUEQjL1AHAdERERkXQxAdqQ2AHEcEBERkXUxANkRrgVERERkGwxAdoS3wIiIiGyDAciO8BYYERGRbTAA2ZGIGwEot0QPnb5K5mqIiIgcFwOQHfF2VcHfQw2A44CIiIisiQHIzkQ04zggIiIia2MAsjPGcUC5DEBERETWwgBkZyIDbkyFv8YAREREZC0MQHamFafCExERWR0DkJ2JMN4C00EURZmrISIickwMQHamdhB0cXkV8ksrZK6GiIjIMTEA2RmtygXNfVwBcBwQERGRtTAA2aEIfzcAwAXOBCMiIrIKBiA7xC0xiIiIrIsByA5F+nsAYAAiIiKyFgYgO9SKPUBERERWxQBkh2qnwqdfK4XBwKnwRERElsYAZIda+LpCqRBQXmlAdnG53OUQERE5HAYgO6RyUaClX81MMO4KT0REZHkMQHYqkltiEBERWQ0DkJ2K4EBoIiIiq2EAslNcC4iIiMh6GIDsVO1UeI4BIiIisjwGIDtVewssI78MldUGmashIiJyLAxAdirYSwutSoEqg4jMgutyl0NERORQGIDslEIhIKJZ7TggnczVEBERORYGIDvWKqA2AJXJXAkREZFjYQCyY+wBIiIisg4GIDvGqfBERETWwQBkx2pvgaXzFhgREZFFMQDZsUh/DwDA5cLrKK+slrkaIiIix8EAZMd83VTw0ioBAOnXeBuMiIjIUhiA7JggCIgMqOkFSstlACIiIrIUBiA7V7slRhp7gIiIiCymQQHo119/xWOPPYb4+HhcvnwZAPDVV19hz549Fi2ObpoKzx4gIiIii5EcgL799lsMHToUrq6uSElJgV6vBwAUFRVh3rx5Fi/Q2UUGcCo8ERGRpUkOQO+88w6WLl2K5cuXQ6VSGY/37t0bR44csWhxdNMtMAYgIiIii5EcgE6fPo1+/frVOe7t7Y3CwkJL1EQ3qd0V/lppBYquV8pcDRERkWOQHICCg4Nx7ty5Osf37NmDVq1aWaQo+oOHRokATw0AIJ29QERERBYhOQA988wzmDx5Mg4ePAhBEHDlyhWsWbMG06ZNw/PPPy/pXLt378bIkSMRGhoKQRDwww8/3Lb9d999hyFDhiAgIABeXl6Ij4/Hli1bTNq8/fbbEATB5BEdHS31a9qV2i0xLnBPMCIiIouQHICmT5+OcePGYdCgQdDpdOjXrx+efvppPPfcc3jppZcknau0tBQxMTFYsmSJWe13796NIUOGYNOmTUhOTsbAgQMxcuRIpKSkmLTr2LEjsrKyjI+mPjutfbAnAODopSKZKyEiInIMSqlvEAQBb7zxBl599VWcO3cOOp0OHTp0gIeHh+QPHz58OIYPH252+0WLFpk8nzdvHn788Uf897//RWxsrPG4UqlEcHCw2efV6/XG2WwAUFxcbPZ7baF7hB9W7b+IIxkFcpdCRETkEBq8EKJarUaHDh0QFxfXoPBjCQaDASUlJfDz8zM5fvbsWYSGhqJVq1YYP348MjIybnue+fPnw9vb2/gICwuzZtmSdQ/3BQCcuFKMsooqmashIiJq+iT3AA0cOBCCINzy9R07djSqICkWLlwInU6Hhx9+2HisZ8+eWLlyJdq1a4esrCzMnj0bffv2xfHjx+Hp6VnveWbMmIGpU6canxcXF9tVCGru44oQby2yispx9FIR4ls3k7skIiKiJk1yAOratavJ88rKSqSmpuL48eNISEiwVF13tHbtWsyePRs//vgjAgMDjcdvvqXWpUsX9OzZE+Hh4diwYQMmTpxY77k0Gg00Go3Va26MbuG++Pm3LCRfzGcAIiIiaiTJAeijjz6q9/jbb78Nnc42s5TWr1+Pp59+Ghs3bsTgwYNv29bHxwdt27atd+p+U9K9ZW0A4jggIiKixrLYZqiPPfYYVqxYYanT3dK6deswYcIErFu3DiNGjLhje51Oh/PnzyMkJMTqtVlTj4iacUDJFwtgMIgyV0NERNS0WSwA7d+/H1qtVtJ7dDodUlNTkZqaCgBIS0tDamqqcdDyjBkz8MQTTxjbr127Fk888QQ++OAD9OzZE9nZ2cjOzkZR0R/Tw6dNm4Zdu3YhPT0d+/btw+jRo+Hi4oKxY8c2/kvKqH2IF1xVLigur8L5XK4HRERE1BiSb4GNGTPG5LkoisjKykJSUhJmzZol6VxJSUkYOHCg8XntQOSEhASsXLkSWVlZJjO4li1bhqqqKkyaNAmTJk0yHq9tDwCZmZkYO3Ysrl27hoCAAPTp0wcHDhxAQECA1K9qV1QuCsSEeePAhXwkXSxAm6D6B3QTERHRnQmiKEq6nzJhwgST5wqFAgEBAbjnnntw7733WrQ4uRQXF8Pb2xtFRUXw8vKSuxyjf2z5HUt+OY+/dG+BhX+NkbscIiIiuyLl91tyD9CXX37Z4MKocXqE+wE4jyMcCE1ERNQoFhsDRNYX29IHAHAhrxTXdPrbNyYiIqJbMqsHyNfX97aLH94sPz+/UQXRrfm4qREV6IFzV3U4klGIIR2C5C6JiIioSTIrAP15Dy6ST49wX5y7qkPSxXwGICIiogYyKwDZcoVnur1u4b5Yf/gSxwERERE1guRB0DcrLy9HRUWFyTF7mjXliHrc2Bj1aGYR9FXV0ChdZK6IiIio6ZE8CLq0tBQvvvgiAgMD4e7uDl9fX5MHWVekvzv83NWoqDLgxJViucshIiJqkiQHoNdeew07duzAv/71L2g0Gnz++eeYPXs2QkNDsXr1amvUSDcRBAHdWtYETd4GIyIiahjJAei///0v/vnPf+Khhx6CUqlE3759MXPmTMybNw9r1qyxRo30J91v3AZLSmcAIiIiagjJASg/Px+tWrUCUDPep3bae58+fbB7927LVkf1Mm6MmlEAiQt5ExERERoQgFq1aoW0tDQAQHR0NDZs2ACgpmfIx8fHosVR/To394bKRUBuiR6X8q/LXQ4REVGTIzkATZgwAUePHgUATJ8+HUuWLIFWq8Urr7yCV1991eIFUl1alQs6hnoDAJIzuPAkERGRVJKnwb/yyivGPw8ePBi///47kpOTERUVhS5duli0OLq1HuG+SL1UiKT0AoyObSF3OURERE2K5AB06dIlhIWFGZ+Hh4cjPDzcokXRnXUP98Xne9KQzJlgREREkkm+BRYREYH+/ftj+fLlKCjgj69cameCnc4pQUl5pczVEBERNS2SA1BSUhLi4uIwZ84chISEYNSoUfjmm2+g13N3clsK9NIizM8VogikZBTKXQ4REVGTIjkAxcbG4h//+AcyMjLwv//9DwEBAXj22WcRFBSEp556yho10i30CPcDAN4GIyIikkhyAKolCAIGDhyI5cuXY/v27YiMjMSqVassWRvdQbcbt8EYgIiIiKRpcADKzMzEggUL0LVrV8TFxcHDwwNLliyxZG10B91vbImRklGAagMXRCQiIjKX5Flgn332GdauXYu9e/ciOjoa48ePx48//siZYDJoF+wJD40SOn0Vfs8uNq4NRERERLcnuQfonXfeQc+ePZGcnIzjx49jxowZDD8ycVEIiG3pA4AboxIREUkhuQcoIyMDgiBYoxZqgO7hvvj1bB6SLxbg8fgIucshIiJqEiT3ADH82BfjzvDsASIiIjJbgwdBk33oGuYDhQBkFlxHTnG53OUQERE1CQxATZynVoV2wV4AOB2eiIjIXAxADqAH1wMiIiKSpEEBqKqqCtu3b8dnn32GkpISAMCVK1eg0+ksWhyZh+OAiIiIpJE8C+zixYsYNmwYMjIyoNfrMWTIEHh6euL999+HXq/H0qVLrVEn3UZtADpxuQjlldXQqlxkroiIiMi+Se4Bmjx5Mnr06IGCggK4uroaj48ePRqJiYkWLY7M08LXFYGeGlQZRPyWWSR3OURERHZPcgD69ddfMXPmTKjVapPjERERuHz5ssUKI/MJgmDsBTqUdk3maoiIiOyf5ABkMBhQXV1d53hmZiY8PT0tUhRJ16eNPwBg26mrMldCRERk/yQHoHvvvReLFi0yPhcEATqdDm+99Rbuu+8+S9ZGEgzpEARBAI5eKsSVwutyl0NERGTXJAegDz74AHv37kWHDh1QXl6OcePGGW9/vf/++9aokcwQ6Kk1ToffciJb5mqIiIjsm+RZYC1atMDRo0exfv16/Pbbb9DpdJg4cSLGjx9vMiiabG9YpxAcTi/A5uPZmNA7Uu5yiIiI7JbkAFReXg6tVovHHnvMGvVQIwztGIS5P53E4fR85On08PfQyF0SERGRXZJ8CywwMBAJCQnYtm0bDAaDNWqiBmrh64bOzb1hEIFtJ3PkLoeIiMhuSQ5Aq1atQllZGR588EE0b94cU6ZMQVJSkjVqowYY1ikYAPC/4xwHREREdCuSA9Do0aOxceNG5OTkYN68eTh58iTuvvtutG3bFnPmzLFGjSRBbQDady4PRdcrZa6GiIjIPjV4M1RPT09MmDABW7duxW+//QZ3d3fMnj3bkrVRA7QO8ECbQA9UGUTs+J23wYiIiOrT4ABUXl6ODRs2YNSoUejWrRvy8/Px6quvWrI2aqDhtbfBjvE2GBERUX0kB6AtW7YgISEBQUFBeP755xEUFIStW7fi4sWLeO+996xRI0k09EYA2nUmF2UVVTJXQ0REZH8aNAbo+vXrWL16NbKzs/HZZ5+hX79+1qiNGqhDiBfC/FyhrzJg1+lcucshIiKyO5LXAcrJyeGeX3ZOEAQM7xSCZbsv4H/HszG8c4jcJREREdkVs3qAiouLjX8WRRHFxcW3fJB9GNqx5jbYjt+vQl9Vd/NaIiIiZ2ZWD5Cvry+ysrIQGBgIHx8fCIJQp40oihAEod6d4sn2YsN8EOSlQU6xHvvOXcPA6EC5SyIiIrIbZgWgHTt2wM/PDwDwyy+/WLUgsgyFQsDQjsFYvf8i/nc8iwGIiIjoJmYFoP79+xv/HBkZibCwsDq9QKIo4tKlS5atjhpl2I0AtO1kDqqqDVC6NHjVAyIiIoci+RcxMjISubl1Zxbl5+cjMpI7kNuTuEg/+LqpUFBWiUPp+XKXQ0REZDckB6DasT5/ptPpoNVqLVIUWYbSRYEhHYIAAJu5NxgREZGR2dPgp06dCqBmivWsWbPg5uZmfK26uhoHDx5E165dLV4gNc6wTsHYkJSJLSey8fbIjlAo6oZXIiIiZ2N2AEpJSQFQ0wN07NgxqNVq42tqtRoxMTGYNm2a5SukRukd5Q8PjRI5xXqkZhaiW0tfuUsiIiKSndkBqHb214QJE7B48WJ4eXlZrSiyHI3SBfdEB+I/R69g8/FsBiAiIiI0YAzQokWLUFVVd3+p/Px8LoRop4bd2Bts8/FsiKIoczVERETykxyAHn30Uaxfv77O8Q0bNuDRRx+VdK7du3dj5MiRCA0NhSAI+OGHH27b/rvvvsOQIUMQEBAALy8vxMfHY8uWLXXaLVmyBBEREdBqtejZsycOHTokqS5H079tADRKBTLyy3Aqq0TucoiIiGQnOQAdPHgQAwcOrHN8wIABOHjwoKRzlZaWIiYmBkuWLDGr/e7duzFkyBBs2rQJycnJGDhwIEaOHGkcnwQAX3/9NaZOnYq33noLR44cQUxMDIYOHYqrV69Kqs2RuGuU6N82AACw+XiWzNUQERHJTxAl3hNxd3fHgQMH0LlzZ5Pjx44dQ8+ePVFWVtawQgQB33//PUaNGiXpfR07dsQjjzyCN998EwDQs2dP3HXXXfj0008BAAaDAWFhYXjppZcwffp0s85ZXFwMb29vFBUVOcxYp++OZGLqhqNoG+SBra/0v/MbiIiImhgpv9+Se4Di4uKwbNmyOseXLl2K7t27Sz1doxgMBpSUlBi36aioqEBycjIGDx5sbKNQKDB48GDs37//lufR6/UOv6nroOggKBUCzuTocD5XJ3c5REREsjJ7Flitd955B4MHD8bRo0cxaNAgAEBiYiIOHz6MrVu3WrzA21m4cCF0Oh0efvhhAEBeXh6qq6sRFBRk0i4oKAi///77Lc8zf/58zJ4926q1ys3bTYVeUf7YfSYXm49nY9LAKLlLIiIiko3kHqDevXtj//79aNGiBTZs2ID//ve/iIqKwm+//Ya+fftao8Z6rV27FrNnz8aGDRsQGNi4jT5nzJiBoqIi48NR9zS778ZssG+PZHI2GBEROTXJPUAA0LVrV6xdu9bStZht/fr1ePrpp7Fx40aT213+/v5wcXFBTk6OSfucnBwEBwff8nwajQYajcZq9dqL+2NCMeenk7iQW4rD6QWIi/STuyQiIiJZNGh78PPnz2PmzJkYN26ccXbV//73P5w4ccKixdVn3bp1mDBhAtatW4cRI0aYvKZWq9G9e3ckJiYajxkMBiQmJiI+Pt7qtdk7D40S93cJAQCsP5QhczVERETykRyAdu3ahc6dO+PgwYP49ttvodPVDKg9evQo3nrrLUnn0ul0SE1NRWpqKgAgLS0NqampyMio+XGeMWMGnnjiCWP7tWvX4oknnsAHH3yAnj17Ijs7G9nZ2SgqKjK2mTp1KpYvX45Vq1bh1KlTeP7551FaWooJEyZI/aoO6dG4lgCAn49loeh6pczVEBERyUNyAJo+fTreeecdbNu2zWQ/sHvuuQcHDhyQdK6kpCTExsYiNjYWQE14iY2NNU5pz8rKMoYhAFi2bBmqqqowadIkhISEGB+TJ082tnnkkUewcOFCvPnmm+jatStSU1OxefPmOgOjnVVsmA/aBXlCX2XAj6mX5S6HiIhIFpLXAfLw8MCxY8cQGRkJT09PHD16FK1atUJ6ejqio6NRXl5urVptxhHXAbrZij1pmPPTSbQP8cKml/tAELhDPBERNX1WXQfIx8cHWVl1VxNOSUlB8+bNpZ6OZDCmW3OolQqcyirGsctFd34DERGRg2nQXmCvv/46srOzIQgCDAYD9u7di2nTppmM1yH75eOmxvAbU+LXHXLMKf9ERES3IzkAzZs3D9HR0QgLC4NOp0OHDh3Qr18/9OrVCzNnzrRGjWQFj9wVBgD4T+pllOqrZK6GiIjItiSPAaqVkZGB48ePQ6fTITY2Fm3atLF0bbJx9DFAACCKIgYu3In0a2VY8FAXPHwjEBERETVVUn6/G7QQIgC0bNkSLVu2bOjbSWaCIODhu8KwYPNprDucwQBEREROxawANHXqVMydOxfu7u6YOnXqbdt6eHigY8eO+Mtf/gIXFxeLFEnW8ZfuLfDh1jNIySjE6ewStAv2lLskIiIimzArAKWkpKCystL459vR6/VYvHgxNm3ahFWrVjW+QrKaQE8tBrUPxJYTOVh/OANvjewod0lEREQ20eAxQLeTlJSEQYMGmazQ3JQ4wxigWr/8fhUTVh6Gj5sKB2YMglbFXjsiImqarLoO0M1EUax3V/EuXbpg9erVjTk12Ui/tgEI9daisKwSW05ky10OERGRTTQoAH3xxRfo1KkTtFottFotOnXqhM8//9z4ulqtxoMPPmixIsl6XBQC/tqjZgD0eq4JRERETkJyAHrzzTcxefJkjBw5Ehs3bsTGjRsxcuRIvPLKK8Y9vKhp+WuPFhAEYP+Fa0jPK5W7HCIiIquTPAYoICAAH3/8McaOHWtyfN26dXjppZeQl5dn0QLl4ExjgGolrDiEXWdy8bf+rTF9eLTc5RAREUlm1TFAlZWV6NGjR53j3bt3R1UVVxRuqsbG1dwG+yY5E5XVBpmrISIisi7JAejxxx/Hv/71rzrHly1bhvHjx1ukKLK9e6KD4O+hRp5Oj8RTV+Uuh4iIyKrMXgixliAI+Pzzz7F161bcfffdAICDBw8iIyODm6E2YWqlAg91b4HPdl3A14czMOzGZqlERESOyOyFEG/WvXt3AMD58+cBAP7+/vD398eJEycsXB7Z0iM9wvDZrgvYdSYXVwqvI9THVe6SiIiIrMKsAPTLL79Yuw6yA60CPNAz0g8H0/KxIekSpgxuK3dJREREVtGohRAzMzORmZlpqVrIDoyNq9ngdu3BDFRUcTA0ERE5JskByGAwYM6cOfD29kZ4eDjCw8Ph4+ODuXPnwmDgD2ZTd1/nEAR4anC1RI+fj12RuxwiIiKrkByA3njjDXz66ad47733kJKSgpSUFMybNw+ffPIJZs2aZY0ayYbUSgUS4sMBAF/sSat3qxMiIqKmTvJCiKGhoVi6dCkeeOABk+M//vgjXnjhBVy+fNmiBcrBGRdCvFl+aQXi5ydCX2XA+mfvxt2tmsldEhER0R1ZdSHE/Px8REfXXSk4Ojoa+fn5Uk9HdsjPXY0x3VoAqOkFIiIicjSSA1BMTAw+/fTTOsc//fRTxMTEWKQokt/EPhEAgO2ncrg/GBERORyzpsHfbMGCBRgxYgS2b9+O+Ph4AMD+/ftx6dIlbNq0yeIFkjyiAj0xoF0Adp7Oxcp96Xj7gY5yl0RERGQxknuA+vfvjzNnzmD06NEoLCxEYWEhxowZg9OnT6Nv377WqJFkMrFPJABgQ9IlFF2vlLkaIiIiy5HcAwTUDIR+9913LV0L2Zk+Uf5oF+SJ0zklWH8oA8/1by13SURERBbRqIUQybEJgmDsBVq1Lx1V3CWeiIgcBAMQ3dYDXUPh76HGlaJy/O94ttzlEBERWQQDEN2WVuWC8T1rFkb8nAsjEhGRg2AAojt67O5wqF0UOHqpEEcyCuQuh4iIqNEYgOiOAjw1GBUbCoALIxIRkWMwaxZYbGwsBEEw64RHjhxpVEFkn57qE4kNSZnYfDwbl/LLEObnJndJREREDWZWABo1apSVyyB7Fx3shT5R/thzLg+r9qVj5v0d5C6JiIiowSRvhuoMnH0z1Fv55fermLDyMDw1SuybcQ88tSq5SyIiIjKy6mao5Lz6tw1A6wB3lOirsCEpU+5yiIiIGkxyAKqursbChQsRFxeH4OBg+Pn5mTzIcSkUAp66sTDiyn1pqDaw85CIiJomyQFo9uzZ+PDDD/HII4+gqKgIU6dOxZgxY6BQKPD2229boUSyJ2NiW8DHTYVL+dex7SQXRiQioqZJcgBas2YNli9fjr///e9QKpUYO3YsPv/8c7z55ps4cOCANWokO+KqdsFjNxZGXLb7AhdGJCKiJklyAMrOzkbnzp0BAB4eHigqKgIA3H///fj5558tWx3ZpSfiw6FRKnAkoxB7zuXJXQ4REZFkkgNQixYtkJWVBQBo3bo1tm7dCgA4fPgwNBqNZasjuxTopTVuj/HhtjPsBSIioiZHcgAaPXo0EhMTAQAvvfQSZs2ahTZt2uCJJ57AU089ZfECyT79bUAraFUKpGQUYteZXLnLISIikqTR6wDt378f+/fvR5s2bTBy5EhL1SUrrgNknnd+OonP96QhJswHP7zQy+zVwomIiKxByu83F0KsBwOQeXJL9Oi34Bdcr6zGiid74J7oILlLIiIiJybl99usrTD+7MqVK9izZw+uXr0Kg8Fg8trLL7/ckFNSExTgqcET8eH4bPcFfLTtLAa2C2QvEBERNQmSA9DKlSvx3HPPQa1Wo1mzZiY/eIIgMAA5mWf7tcJXBy7i2OUibD91FUM6sBeIiIjsn+RB0LNmzcKbb76JoqIipKenIy0tzfi4cOGCNWokO9bMQ4OEXhEAgEXbOSOMiIiaBskBqKysDI8++igUCm4jRjWe7dsK7moXnLhSjK0nc+Quh4iI6I4kp5iJEydi48aN1qiFmihfdzWe7B0BAPho2xkYuEcYERHZOcmzwKqrq3H//ffj+vXr6Ny5M1QqlcnrH374oUULlANngUlXWFaBPu//Ap2+Cv8a3w3DO4fIXRIRETkZq84Cmz9/PrZs2YJ27doBQJ1B0OScfNzUeKp3BD7ecQ6Ltp/F0I7BUCj47wMREdknyQHogw8+wIoVK/Dkk09aoRxqyib2aYUv96XjdE4JNh3Pwv1dQuUuiYiIqF6SxwBpNBr07t3bGrVQE+ftpsLEPpEAgMXbz6KaY4GIiMhOSQ5AkydPxieffGKNWsgBPNUnEl5aJc5e1eGn367IXQ4REVG9JN8CO3ToEHbs2IGffvoJHTt2rDMI+rvvvrNYcdT0eGlVeLpvK3y47QwWJ57F/V1C4cKxQEREZGck9wD5+PhgzJgx6N+/P/z9/eHt7W3ykGL37t0YOXIkQkNDIQgCfvjhh9u2z8rKwrhx49C2bVsoFApMmTKlTpuVK1dCEASTh1arlVQXNc6E3hHwdlXhQm4p/nP0stzlEBER1SG5B+jLL7+02IeXlpYiJiYGTz31FMaMGXPH9nq9HgEBAZg5cyY++uijW7bz8vLC6dOnjc85O822PLUqPNuvFf6x5TQWb6/pBVK5cOFMIiKyHw3aDNVShg8fjuHDh5vdPiIiAosXLwYArFix4pbtBEFAcHCw2efV6/XQ6/XG58XFxWa/l+qX0CsCK/akIf1aGdYfvoTH7w6XuyQiIiIjs/63vFu3bigoKAAAxMbGolu3brd82AOdTofw8HCEhYXhwQcfxIkTJ27bfv78+Sa38cLCwmxUqePy0Cjx8qA2AIDF289Ap6+SuSIiIqI/mNUD9OCDD0Kj0Rj/bM+3lNq1a4cVK1agS5cuKCoqwsKFC9GrVy+cOHECLVq0qPc9M2bMwNSpU43Pi4uLGYIsYGxcS6zYm4aL18qwfPcFvDKkrdwlERERAWjAVhjWIggCvv/+e4waNcqs9gMGDEDXrl2xaNGi27arrKxE+/btMXbsWMydO9esc3MrDMv56bcreHFtCtzULtj56gAEenJAOhERWYeU32/JI1NbtWqFa9eu1TleWFiIVq1aST2d1alUKsTGxuLcuXNyl+KURnQOQUwLb5RVVOPjxLNyl0NERASgAQEoPT0d1dXVdY7r9XpkZmZapChLqq6uxrFjxxASws055SAIAmbc1x4AsO7QJZzP1clcERERkYRZYP/5z3+Mf96yZYvJmj/V1dVITExEZGSkpA/X6XQmPTNpaWlITU2Fn58fWrZsiRkzZuDy5ctYvXq1sU1qaqrxvbm5uUhNTYVarUaHDh0AAHPmzMHdd9+NqKgoFBYW4h//+AcuXryIp59+WlJtZDl3t2qGe6IDseP3q/jH5tNY+nh3uUsiIiInZ3YAqh2bIwgCEhISTF5TqVSIiIjABx98IOnDk5KSMHDgQOPz2oHICQkJWLlyJbKyspCRkWHyntjYWOOfk5OTsXbtWoSHhyM9PR0AUFBQgGeeeQbZ2dnw9fVF9+7dsW/fPmNAInm8PiwaO09fxeYT2Ui+WIDu4b5yl0RERE5M8iDoyMhIHD58GP7+/taqSXYcBG0dr31zFBuSMnFXhC82PBdv17MJiYio6bHqIOi0tDSHDj9kPa8MaQuNUoHD6QXYdjJH7nKIiMiJNWh/gsTERNx///1o3bo1Wrdujfvvvx/bt2+3dG3kYEK8XTGxT804sfc3/46qaoPMFRERkbOSHID++c9/YtiwYfD09MTkyZMxefJkeHl54b777sOSJUusUSM5kL8NaA1fNxXO55ZiY7L9zRokIiLnIHkMUIsWLTB9+nS8+OKLJseXLFmCefPm4fLlpr/7N8cAWdcXe9Iw96eTCPDUYNerA+CmlnVLOiIichBWHQNUWFiIYcOG1Tl+7733oqioSOrpyAk9dndLhPm5IrdEjy9+TZO7HCIickKSA9ADDzyA77//vs7xH3/8Effff79FiiLHplG6YNq97QAAn+2+gDydXuaKiIjI2Ui+99ChQwe8++672LlzJ+Lj4wEABw4cwN69e/H3v/8dH3/8sbHtyy+/bLlKyaGM7BKKz39Nw7HLRfgk8SxmP9hJ7pKIiMiJNGgdILNOLAi4cOFCg4qSG8cA2ca+c3kY9/lBuCgErHvmbsRF+sldEhERNWFSfr8l9wClpXHMBllGryh/jOoaih9Sr+CFNUfw88t9EOTF3eKJiMj6GrQOEADk5eUhLy/PkrWQE5o3pjOigz2Rp9PjhTVHUFHFtYGIiMj6JAWgwsJCTJo0Cf7+/ggKCkJQUBD8/f3x4osvorCw0EolkiNzUyux9LHu8NQqkXyxAO/8fFLukoiIyAmYfQssPz8f8fHxuHz5MsaPH4/27dsDAE6ePImVK1ciMTER+/btg68vN7kkaSL83bHoka6YuCoJq/dfRNcwH4zp1kLusoiIyIGZPQh6ypQpSExMxPbt2xEUFGTyWnZ2Nu69914MGjQIH330kVUKtSUOgpbHh9vO4OPEs9AoFfjuhV7oGOotd0lERNSEWGUhxB9++AELFy6sE34AIDg4GAsWLKh3fSAic00Z1AYD2wVAX2XA3/6djMKyCrlLIiIiB2V2AMrKykLHjh1v+XqnTp2QnZ1tkaLIOSkUAhY9EouWfm64lH8dk9enotogaZUGIiIis5gdgPz9/ZGenn7L19PS0uDnx3VcqHG83VRY+lh3aFUK7DqTi8Xbz8hdEhEROSCzA9DQoUPxxhtvoKKi7m0JvV6PWbNm1btHGJFUHUK9MH9MZwDAxzvOYfvJHJkrIiIiR2P2IOjMzEz06NEDGo0GkyZNQnR0NERRxKlTp/DPf/4Ter0eSUlJCAsLs3bNVsdB0Pbh7f+cwMp96fDUKvHfF/sgwt9d7pKIiMiOSfn9lrQVRlpaGl544QVs3boVtW8TBAFDhgzBp59+iqioqMZVbicYgOxDRZUB45YfQNLFArQL8sS3L/SCh0by4uVEROQkrBaAahUUFODs2bMAgKioKIcb+8MAZD+uFpfj/k/24GqJHn3b+GPFk3dB5dLgBcyJiMiBWWUa/M18fX0RFxeHuLg4hws/ZF8CvbT4PKEH3NQu+PVsHqZ/ewwNyOxEREQm+L/SZPe6tPDBkvHd4KIQ8O2RTHy0jTPDiIiocRiAqEkY2C4Q80Z3AlAzM2ztwQyZKyIioqaMAYiajEfuaonJg9oAAGb+cAyJpzg9noiIGoYBiJqUKYPb4OEeLWAQgRfXpuDopUK5SyIioiaIAYiaFEEQ8O7ozujfNgDXK6vx1MrDuHitVO6yiIioiWEAoiZH5aLAP8d3Q6fmXrhWWoGEFYdwTaeXuywiImpCGICoSXLXKLHiybvQwtcV6dfKMHFVEq5XVMtdFhERNREMQNRkBXpqseqpOPi4qZB6qRAvrUtBVbVB7rKIiKgJYACiJq11gAe+SOgBjVKB7adyMOXrVIYgIiK6IwYgavK6h/thybhuULkI+Om3LLy8PgWVDEFERHQbDEDkEAZ3CMLSx7pD7aLApmPZeGktQxAREd0aAxA5jEHtg/DZ492hViqw+UQ2Jq05gooqhiAiIqqLAYgcysDoQCy7EYK2nszBC2uOQF/F2WFERGSKAYgczoB2gfj8iT8GRj//b4YgIiIyxQBEDqlf2wB8kXAXtCoFdvx+Fc99lYzySoYgIiKqwQBEDqtPG3+suBGCdp7OxbMMQUREdAMDEDm0XlH++PLJOLiqXLD7TC6eWZ2EUn2V3GUREZHMGIDI4cW3boaVE+6Cm9oFv57Nw30f/4qUjAK5yyIiIhkxAJFT6NmqGf79dE8093HFxWtl+MvS/Vi8/SxXjSYiclIMQOQ0urX0xabJffFg11BUG0R8tP0MHv5sPzKulcldGhER2RgDEDkVb1cVFj8ai0WPdIWnRokjGYUYvng3NiZdgiiKcpdHREQ2wgBETmlUbHNsmtwXcRF+KK2oxqvf/IZJa4+gsKxC7tKIiMgGGIDIaYX5uWHds3fj1aHtoFQI2HQsG8MW/Yq95/LkLo2IiKyMAYicmotCwKSBUfjuhV5o5e+O7OJyjP/8IN79+SRXjyYicmAMQEQAurTwwU8v98G4ni0BAMt/TcOoJftwJqdE5sqIiMgaGICIbnBTKzFvdGcsf6IH/NzVOJVVjJGf7MHKvWkcIE1E5GAYgIj+ZEiHIGye0hcD2gVAX2XA2/89iSe/PIyrxeVyl0ZERBbCAERUj0BPLb588i7MebAjNEoFdp3JxbDFv2LriWy5SyMiIgtgACK6BUEQ8ER8BH56qQ86hHghv7QCz36VjBnf/YayCu4nRkTUlDEAEd1BmyBPfD+pF57r1wqCAKw7dAkjPt6DgxeuyV0aERE1EAMQkRk0ShfMuK891jzdEyHeWqTlleKRZQfwt6+ScfFaqdzlERGRRAxARBL0au2PzZP7YXzPllAIwOYT2Rj84S68+/NJFF2vlLs8IiIyk6wBaPfu3Rg5ciRCQ0MhCAJ++OGH27bPysrCuHHj0LZtWygUCkyZMqXedhs3bkR0dDS0Wi06d+6MTZs2Wb54clrebiq8O7oz/je5H/q28UdltYjlv6Zh4MKd+Gp/OneYJyJqAmQNQKWlpYiJicGSJUvMaq/X6xEQEICZM2ciJiam3jb79u3D2LFjMXHiRKSkpGDUqFEYNWoUjh8/bsnSidAu2BOrn4rDlxPuQlSgB/JLKzDrxxMYtvhX/HL6qtzlERHRbQiinazwJggCvv/+e4waNcqs9gMGDEDXrl2xaNEik+OPPPIISktL8dNPPxmP3X333ejatSuWLl1q1rmLi4vh7e2NoqIieHl5mfsVyIlVVhuw7lAGPtp2BgVlNbfC+rUNwN+HtEVMmI+8xREROQkpv98ONwZo//79GDx4sMmxoUOHYv/+/bd8j16vR3FxscmDSAqViwJPxEdg56sD8UzfSKhcBOw+k4sHl+zFqCV78UPKZe4tRkRkRxwuAGVnZyMoKMjkWFBQELKzb72A3fz58+Ht7W18hIWFWbtMclDeriq8MaIDtk/tjzGxzaF2USD1UiGmfJ2K3u/twIdbTyO7iCtKExHJzeECUEPMmDEDRUVFxselS5fkLomauPBm7vjwka7YO/0e/H1IWwR7aZGnq8DHO86hz/s7MGntERxKy+ceY0REMlHKXYClBQcHIycnx+RYTk4OgoODb/kejUYDjUZj7dLICQV4avDSoDb424DW2HoiB6v2p+NQWj5+/i0LP/+WhfYhXkiID8eDXZvDVe0id7lERE7D4XqA4uPjkZiYaHJs27ZtiI+Pl6kiopoxQiO6hGDDc/HY9HJfjI0Lg1alwKmsYkz/7hjunp+I+ZtO4VJ+mdylEhE5BVl7gHQ6Hc6dO2d8npaWhtTUVPj5+aFly5aYMWMGLl++jNWrVxvbpKamGt+bm5uL1NRUqNVqdOjQAQAwefJk9O/fHx988AFGjBiB9evXIykpCcuWLbPpdyO6lQ6hXpg/pgteHxaNjUmZWH0gHZfyr+Oz3Rew7NcLGBQdhIRe4egT5Q9BEOQul4jIIck6DX7nzp0YOHBgneMJCQlYuXIlnnzySaSnp2Pnzp3G1+r7QQgPD0d6errx+caNGzFz5kykp6ejTZs2WLBgAe677z6z6+I0eLKlaoOInaevYuW+dPx6Ns94vFWAOxLiI/BQ9xbw0Djc3WoiIouT8vttN+sA2RMGIJLL+Vwdvtp/Ed8kZ0Knr9lx3kOjxPBOwRgYHYjeUf7wdlXJXCURkX1iAGokBiCSW0l5Jb5PuYxV+9JxPvePzVZdFAK6tfRB/7YBGNAuEB1CvKBQ8DYZERHAANRoDEBkL0RRxP4L15B46ip2ncnFuas6k9f9PdTo1yYA/dsFoH/bAPi4qWWqlIhIfgxAjcQARPbqUn4Zdp/Nxa7Tudh7Lg+lFX+sLq1WKvBATCie7BWBTs29ZaySiEgeDECNxABETUFFlQHJFwuw60wufvn9Kk7nlBhf69bSBwm9IjC8UwjUSodb7YKIqF4MQI3EAERNjSiKSLlUiFX70rHpWBYqq2v+sw7w1GBcXEuM69kSQV5amaskIrIuBqBGYgCipuxqSTnWHbyENQcv4mqJHgCgVAgY3jkE4+Ja4q4IXyhd2CtERI6HAaiRGIDIEVRWG7D5eDZW7UtH0sUC43FPrRJ9ovwxoF0A+rUNQIi3q4xVEhFZDgNQIzEAkaM5frkIX+2/iC0ns1FYVmnyWnSwJ/q3rZlF1iPCj2OGiKjJYgBqJAYgclTVBhG/ZRZi15lc7DqTi9RLhbj5bwA3tQt6tfZH/3YBGNA2AGF+bvIVS0QkEQNQIzEAkbMoKK3Ar+fysOt0TSDK0+lNXm8V4I4BbQPRv10Aekb6QavijvVEZL8YgBqJAYickcEg4mRWcU3v0OlcJGcUoNrwx18PWpUCd7dqhv5tA9C3TQBa+btzFWoisisMQI3EAEQEFJdXYu/ZPOw6k4udp3ORXVxu8rqnVomOoV7o3NwbnW48IpsxFBGRfBiAGokBiMiUKIo4k6PDrjM1W3IcTi9ARZWhTjt3tQs6htaEoc4tvNAp1ButAjzgwlBERDbAANRIDEBEt1dZbcDZHB2OXynC8cs1j5NZxSivrBuK3NQu6BDiZewl6tTcC1EBHlyLiIgsjgGokRiAiKSrqjbgfG4pjl8uwrGbQlHZTfuV1dKqFGgfUtNDVHsLrU2QB1QMRUTUCAxAjcQARGQZ1QYRaXm6G4GoGMcuF+HklWLo9FV12qqVCrQP9jT2FHVu7o22QZ5cl4iIzMYA1EgMQETWYzCISL9WauwlOn65GMevFKGkvG4oUrkIaBfs+cdA61BvtAv25HR8IqoXA1AjMQAR2ZbBICIjvwzHrxSZBKOi65V12ioVAtoEeaJz85oZaB2be6NDiBdDERExADUWAxCR/ERRRGbBdWMgqv1nQVndUOSiENAm0AMdQ71rglELb7QP8YKbWilD5UQkFwagRmIAIrJPoijiSlE5jmUW4cRNvUV5uoo6bRUC0DrAw9hL1Lm5NyKaucHHTc1xRUQOigGokRiAiJoOURSRU6zHsRu9RCdu/PNqif6W7/HUKuHnroavmxp+7n88ap6r4OeugZ+7Cr5uajRz18BTq+QCj0RNgJTfb/YPE1GTJggCgr21CPbWYkiHIOPxq8XlNWOKMmsGWZ+4XITs4nIYRKCkvAol5VW4eK3MrM9wUQjwdVOZBCZfdzX86nvuUfNPVzXHJBHZMwYgInJIgV5a3OOlxT3Rf4Qig0FEcXkl8ksrjI+CsgpcK61AQWkF8ksrTZ4XlFagRF+FaoOIPF1FvbfabkWrUhgDUW1wqulRuhGWap/feN3XTcXFIYlsiAGIiJyGQiHAx00NHzc1WgWY956KKgMKym6EpdIK5JfdFJ5KK5BfVon8Un1NeLpxvKLagPJKA64UleNKUfmdP+QGL60SzTw08HVT/XFL7kaP0p97mHzd1fDSKiEIvDVH1BAMQEREt6FWKhDkpUWQl9as9qIoorSi2hiGbu5putXzwuuVEEWguLwKxeVVSDOzNqVCMAYjX3cVmrlr4Ouu+iMwmYxtqnlwuQCiGgxAREQWJAgCPDRKeGiUCPNzM+s91QYRRdfr3poz7WkyfV5aUY0qg4jcEj1ybzPg+8/c1C5mDf6ufc3HTc3NbMkhMQAREcnMRSEYA4e5yiurb7o1V1kTkHR65JdV/hGYdH8EqYKyClRWiyirqEZZxXVcLrxu1ucIAuDtqjIO+K7vVpwxPN3oifLQ8NYc2T8GICKiJkirckGItytCvF3Nai+KIkr0VcZbcwVlFbhmDEg1oenajeO1fy66cWuusKwShWWVuJBXatZnqV0U8L2pJ8nX/cbg71s+V0Gj5K05si0GICIiJyAIAry0KnhpVQhv5m7We6qqDSi8flM4utGzZPq80mS80/XKalRUG5BTrEdOsfm35jw0yrrjl/40lunm8Uw+riquzUSNwgBERET1Uroo4O+hgb+HBm3MfM/1imrT8Uv1DP426Xkqq0C1QYROXwWdvgqX8s27NacQAJ8bywfUF5DqW6vJTe3CW3NkxABEREQW46p2gavaFaE+5t2aMxhElJRXGQd5G3uTyipMZ9Ld9Ly4vAoGEcbXzueaeWtOqahn8cqbBn//aXwTt01xbAxAREQkG4VCgLebCt5uKkT6m3drrrLacGOsUmW9AenPPU/XSitQUWVARZUB2cXlyC42f20mT42y7mKWHreeOeel5a25poIBiIiImhSViwKBnloEepq/NtP1yup6lhn40yKWN/VCFZRV1Gyboq9Cib5h26YYB3vfNJ7J9HnN2k3cNkUeDEBEROTQBEGAm1oJN7USLXzNW5updtuUazfdlvvztin5pX8sO2CJbVNutXjln5/7uKmg4rYpjcYARERE9Cc3b5sCM7dN0VdVo7Cs0tiLdO2mW3Gmzy2zbcodB39z25TbYgAiIiKyAI3SBUFeLg3aNuXWPU2mz/+8bUq6mbfm/rxtijE8OfG2KQxAREREMmjctin6G7fhbLNtiunilap6F7f0bWLbpjAAERERNRGW2DblWqm+3kUsbw5SVQbLbZtiMvj7xoy5Zu4aNPNQw10jXwxhACIiInJgjd025ZYz5xq5bcq9HYKw7Ikejf16DcYAREREREaN2Talzq043U1rNJXVhKfa9Zuk9GJZAwMQERERNcrN26aYq9ogWrGiO+NCAkRERGRzcg+YZgAiIiIip8MARERERE6HAYiIiIicDgMQEREROR0GICIiInI6DEBERETkdBiAiIiIyOkwABEREZHTYQAiIiIip8MARERERE6HAYiIiIicDgMQEREROR0GICIiInI6SrkLsEeiKAIAiouLZa6EiIiIzFX7u137O347DED1KCkpAQCEhYXJXAkRERFJVVJSAm9v79u2EURzYpKTMRgMuHLlCjw9PSEIQoPPU1xcjLCwMFy6dAleXl4WrJD+jNfadnitbYfX2rZ4vW3HWtdaFEWUlJQgNDQUCsXtR/mwB6geCoUCLVq0sNj5vLy8+B+TjfBa2w6vte3wWtsWr7ftWONa36nnpxYHQRMREZHTYQAiIiIip8MAZEUajQZvvfUWNBqN3KU4PF5r2+G1th1ea9vi9bYde7jWHARNREREToc9QEREROR0GICIiIjI6TAAERERkdNhACIiIiKnwwDUSEuWLEFERAS0Wi169uyJ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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "alpha_values = [\n", " 0.005,\n", " 0.01,\n", " 0.02,\n", " 0.03,\n", " 0.04,\n", " 0.05,\n", " 0.06,\n", " 0.07,\n", " 0.08,\n", " 0.09,\n", " 0.1,\n", " 0.11,\n", " 0.12,\n", " 0.13,\n", " 0.14,\n", " 0.15,\n", " 0.16,\n", " 0.17,\n", " 0.18,\n", " 0.19,\n", " 0.20,\n", " 0.25,\n", " 0.5,\n", "]\n", "objective = []\n", "\n", "for alpha in alpha_values:\n", " ampl = markowitz_revisited(alpha, mu, Sigma)\n", " objective.append(round(ampl.get_objective(\"Objective\").value(), 3))\n", "\n", "plt.plot(alpha_values, objective)\n", "plt.xlabel(r\"Risk tolerance $\\alpha$\")\n", "plt.ylabel(\"Optimal objective value\")\n", "plt.show()" ] } ], "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.9.6" }, "varInspector": { "cols": { "lenName": 16, "lenType": 16, "lenVar": 40 }, "kernels_config": { "python": { "delete_cmd_postfix": "", "delete_cmd_prefix": "del ", "library": "var_list.py", "varRefreshCmd": "print(var_dic_list())" }, "r": { "delete_cmd_postfix": ") ", "delete_cmd_prefix": "rm(", "library": "var_list.r", "varRefreshCmd": "cat(var_dic_list()) " } }, "types_to_exclude": [ "module", "function", "builtin_function_or_method", "instance", "_Feature" ], "window_display": false } }, "nbformat": 4, "nbformat_minor": 5 }