{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "# Portfolio Optimization\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Introduction\n", "\n", "This tutorial shows how to solve the following mean-variance portfolio optimization problem for $n$ assets:\n", "\n", "$$\\begin{aligned}\n", "\\min_{x \\in \\{0, 1\\}^n} q x^T \\Sigma x - \\mu^T x\\\\\n", "\\text{subject to: } 1^T x = B\n", "\\end{aligned}$$\n", "\n", "where we use the following notation:\n", "\n", "- $x \\in \\{0, 1\\}^n$ denotes the vector of binary decision variables, which indicate which assets to pick ($x[i] = 1$) and which not to pick ($x[i] = 0$),\n", "- $\\mu \\in \\mathbb{R}^n$ defines the expected returns for the assets,\n", "- $\\Sigma \\in \\mathbb{R}^{n \\times n}$ specifies the covariances between the assets,\n", "- $q > 0$ controls the risk appetite of the decision maker,\n", "- and $B$ denotes the budget, i.e. the number of assets to be selected out of $n$.\n", "\n", "We assume the following simplifications:\n", "- all assets have the same price (normalized to 1),\n", "- the full budget $B$ has to be spent, i.e. one has to select exactly $B$ assets.\n", "\n", "The equality constraint $1^T x = B$ is mapped to a penalty term $(1^T x - B)^2$ which is scaled by a parameter and subtracted from the objective function. \n", "The resulting problem can be mapped to a Hamiltonian whose ground state corresponds to the optimal solution.\n", "This notebook shows how to use the Sampling Variational Quantum Eigensolver (`SamplingVQE`) or the Quantum Approximate Optimization Algorithm (`QAOA`) from [Qiskit Algorithms](https://qiskit-community.github.io/qiskit-algorithms/apidocs/qiskit_algorithms.html#minimum-eigensolvers) to find the optimal solution for a given set of parameters.\n", "\n", "Experiments on real quantum hardware for this problem are reported for instance in the following paper:\n", "
\n", "[Improving Variational Quantum Optimization using CVaR. Barkoutsos et al. 2019.](https://arxiv.org/abs/1907.04769)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:05.710593Z", "start_time": "2020-07-13T20:34:57.647535Z" } }, "outputs": [], "source": [ "from qiskit.circuit.library import TwoLocal\n", "from qiskit.result import QuasiDistribution\n", "from qiskit_aer.primitives import Sampler\n", "from qiskit_algorithms import NumPyMinimumEigensolver, QAOA, SamplingVQE\n", "from qiskit_algorithms.optimizers import COBYLA\n", "from qiskit_finance.applications.optimization import PortfolioOptimization\n", "from qiskit_finance.data_providers import RandomDataProvider\n", "from qiskit_optimization.algorithms import MinimumEigenOptimizer\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import datetime" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define problem instance\n", "\n", "Here an Operator instance is created for our Hamiltonian. In this case the paulis are from an Ising Hamiltonian translated from the portfolio problem. We use a random portfolio problem for this notebook. It is straight-forward to extend this to using real financial data as illustrated here:
\n", "[Loading and Processing Stock-Market Time-Series Data](11_time_series.ipynb)" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:15.224327Z", "start_time": "2020-07-13T20:35:15.213892Z" } }, "outputs": [], "source": [ "# set number of assets (= number of qubits)\n", "num_assets = 4\n", "seed = 123\n", "\n", "# Generate expected return and covariance matrix from (random) time-series\n", "stocks = [(\"TICKER%s\" % i) for i in range(num_assets)]\n", "data = RandomDataProvider(\n", " tickers=stocks,\n", " start=datetime.datetime(2016, 1, 1),\n", " end=datetime.datetime(2016, 1, 30),\n", " seed=seed,\n", ")\n", "data.run()\n", "mu = data.get_period_return_mean_vector()\n", "sigma = data.get_period_return_covariance_matrix()" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [ "nbsphinx-thumbnail" ] }, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# plot sigma\n", "plt.imshow(sigma, interpolation=\"nearest\")\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:15.231767Z", "start_time": "2020-07-13T20:35:15.226490Z" } }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "q = 0.5 # set risk factor\n", "budget = num_assets // 2 # set budget\n", "penalty = num_assets # set parameter to scale the budget penalty term\n", "\n", "portfolio = PortfolioOptimization(\n", " expected_returns=mu, covariances=sigma, risk_factor=q, budget=budget\n", ")\n", "qp = portfolio.to_quadratic_program()\n", "qp" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We define some utility methods to print the results in a nice format." ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:15.243604Z", "start_time": "2020-07-13T20:35:15.233567Z" } }, "outputs": [], "source": [ "def print_result(result):\n", " selection = result.x\n", " value = result.fval\n", " print(\"Optimal: selection {}, value {:.4f}\".format(selection, value))\n", "\n", " eigenstate = result.min_eigen_solver_result.eigenstate\n", " probabilities = (\n", " eigenstate.binary_probabilities()\n", " if isinstance(eigenstate, QuasiDistribution)\n", " else {k: np.abs(v) ** 2 for k, v in eigenstate.to_dict().items()}\n", " )\n", " print(\"\\n----------------- Full result ---------------------\")\n", " print(\"selection\\tvalue\\t\\tprobability\")\n", " print(\"---------------------------------------------------\")\n", " probabilities = sorted(probabilities.items(), key=lambda x: x[1], reverse=True)\n", "\n", " for k, v in probabilities:\n", " x = np.array([int(i) for i in list(reversed(k))])\n", " value = portfolio.to_quadratic_program().objective.evaluate(x)\n", " print(\"%10s\\t%.4f\\t\\t%.4f\" % (x, value, v))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## NumPyMinimumEigensolver (as a classical reference)\n", "Lets solve the problem. First classically...\n", "\n", "We can now use the Operator we built above without regard to the specifics of how it was created. We set the algorithm for the NumPyMinimumEigensolver so we can have a classical reference. The problem is set for 'ising'. Backend is not required since this is computed classically not using quantum computation. The result is returned as a dictionary." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:15.264319Z", "start_time": "2020-07-13T20:35:15.245811Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimal: selection [1. 0. 0. 1.], value -0.0149\n", "\n", "----------------- Full result ---------------------\n", "selection\tvalue\t\tprobability\n", "---------------------------------------------------\n", " [1 0 0 1]\t-0.0149\t\t1.0000\n" ] } ], "source": [ "exact_mes = NumPyMinimumEigensolver()\n", "exact_eigensolver = MinimumEigenOptimizer(exact_mes)\n", "\n", "result = exact_eigensolver.solve(qp)\n", "\n", "print_result(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Solution using `SamplingVQE`\n", "We can now use the Sampling Variational Quantum Eigensolver (`SamplingVQE`) to solve the problem. We will specify the optimizer and variational form to be used." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:26.536878Z", "start_time": "2020-07-13T20:35:24.379996Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimal: selection [1. 0. 0. 1.], value -0.0149\n", "\n", "----------------- Full result ---------------------\n", "selection\tvalue\t\tprobability\n", "---------------------------------------------------\n", " [0 1 1 0]\t0.0008\t\t0.8525\n", " [1 0 0 1]\t-0.0149\t\t0.0410\n", " [0 0 1 1]\t-0.0010\t\t0.0312\n", " [0 0 0 1]\t-0.0008\t\t0.0215\n", " [1 0 1 1]\t-0.0150\t\t0.0195\n", " [1 0 0 0]\t-0.0140\t\t0.0088\n", " [0 1 1 1]\t-0.0000\t\t0.0078\n", " [0 1 0 1]\t0.0002\t\t0.0078\n", " [0 1 0 0]\t0.0009\t\t0.0059\n", " [1 0 1 0]\t-0.0140\t\t0.0020\n", " [1 1 0 1]\t-0.0139\t\t0.0010\n", " [0 0 0 0]\t0.0000\t\t0.0010\n" ] } ], "source": [ "from qiskit_algorithms.utils import algorithm_globals\n", "\n", "algorithm_globals.random_seed = 1234\n", "\n", "cobyla = COBYLA()\n", "cobyla.set_options(maxiter=500)\n", "ry = TwoLocal(num_assets, \"ry\", \"cz\", reps=3, entanglement=\"full\")\n", "svqe_mes = SamplingVQE(sampler=Sampler(), ansatz=ry, optimizer=cobyla)\n", "svqe = MinimumEigenOptimizer(svqe_mes)\n", "result = svqe.solve(qp)\n", "\n", "print_result(result)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Solution using `QAOA`\n", "\n", "We also show here a result using the Quantum Approximate Optimization Algorithm (`QAOA`). This is another variational algorithm and it uses an internal variational form that is created based on the problem." ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:28.570970Z", "start_time": "2020-07-13T20:35:26.539093Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Optimal: selection [1. 0. 0. 1.], value -0.0149\n", "\n", "----------------- Full result ---------------------\n", "selection\tvalue\t\tprobability\n", "---------------------------------------------------\n", " [1 0 0 1]\t-0.0149\t\t0.1797\n", " [1 0 1 0]\t-0.0140\t\t0.1729\n", " [1 1 0 0]\t-0.0130\t\t0.1641\n", " [0 0 1 1]\t-0.0010\t\t0.1592\n", " [0 1 1 0]\t0.0008\t\t0.1553\n", " [0 1 0 1]\t0.0002\t\t0.1445\n", " [0 1 0 0]\t0.0009\t\t0.0049\n", " [1 1 0 1]\t-0.0139\t\t0.0039\n", " [1 1 1 1]\t-0.0139\t\t0.0039\n", " [0 0 0 0]\t0.0000\t\t0.0029\n", " [1 0 0 0]\t-0.0140\t\t0.0029\n", " [0 0 1 0]\t-0.0001\t\t0.0020\n", " [0 1 1 1]\t-0.0000\t\t0.0010\n", " [1 1 1 0]\t-0.0130\t\t0.0010\n", " [0 0 0 1]\t-0.0008\t\t0.0010\n", " [1 0 1 1]\t-0.0150\t\t0.0010\n" ] } ], "source": [ "algorithm_globals.random_seed = 1234\n", "\n", "cobyla = COBYLA()\n", "cobyla.set_options(maxiter=250)\n", "qaoa_mes = QAOA(sampler=Sampler(), optimizer=cobyla, reps=3)\n", "qaoa = MinimumEigenOptimizer(qaoa_mes)\n", "result = qaoa.solve(qp)\n", "\n", "print_result(result)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "ExecuteTime": { "end_time": "2020-07-13T20:35:29.079589Z", "start_time": "2020-07-13T20:35:28.573543Z" } }, "outputs": [ { "data": { "text/html": [ "

Version Information

SoftwareVersion
qiskit0.45.0.dev0+ea871e0
qiskit_optimization0.6.0
qiskit_finance0.4.0
qiskit_aer0.12.2
qiskit_ibm_provider0.7.0
qiskit_algorithms0.3.0
System information
Python version3.9.7
Python compilerGCC 7.5.0
Python builddefault, Sep 16 2021 13:09:58
OSLinux
CPUs2
Memory (Gb)5.7784271240234375
Tue Sep 05 15:03:52 2023 EDT
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "

This code is a part of Qiskit

© Copyright IBM 2017, 2023.

This code is licensed under the Apache License, Version 2.0. You may
obtain a copy of this license in the LICENSE.txt file in the root directory
of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.

Any modifications or derivative works of this code must retain this
copyright notice, and modified files need to carry a notice indicating
that they have been altered from the originals.

" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import tutorial_magics\n", "\n", "%qiskit_version_table\n", "%qiskit_copyright" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "celltoolbar": "Tags", "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.9.7" }, "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 }, "vscode": { "interpreter": { "hash": "e3b168dd14084693aa742087410f9921d6040e41eb6bdb17b20e4003862f82dd" } } }, "nbformat": 4, "nbformat_minor": 1 }