{ "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 Variational Quantum Eigensolver (VQE) or the Quantum Approximate Optimization Algorithm (QAOA) 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 import Aer\n", "from qiskit.algorithms import VQE, QAOA, NumPyMinimumEigensolver\n", "from qiskit.algorithms.optimizers import COBYLA\n", "from qiskit.circuit.library import TwoLocal\n", "from qiskit.utils import QuantumInstance\n", "from qiskit_finance.applications.optimization import PortfolioOptimization\n", "from qiskit_finance.data_providers import RandomDataProvider\n", "from qiskit_optimization.algorithms import MinimumEigenOptimizer\n", "from qiskit_optimization.applications import OptimizationApplication\n", "from qiskit_optimization.converters import QuadraticProgramToQubo\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import datetime" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### [Optional] Setup token to run the experiment on a real device\n", "If you would like to run the experiment on a real device, you need to setup your account first.\n", "\n", "Note: If you do not store your token yet, use IBMQ.save_account('MY_API_TOKEN') to store it first." ] }, { "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(tickers=stocks,\n", " start=datetime.datetime(2016,1,1),\n", " end=datetime.datetime(2016,1,30),\n", " seed=seed)\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": [ { "output_type": "display_data", "data": { "text/plain": "