{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Portfolio Selection Optimization\n", "This model is an example of the classic [Markowitz portfolio selection optimization model](https://en.wikipedia.org/wiki/Markowitz_model). We want to find the fraction of the portfolio to invest among a set of stocks that balances risk and return. It is a Quadratic Programming (QP) model with vector and matrix data for returns and risk, respectively. This is best suited to a matrix formulation, so we use the Gurobi Python *matrix* interface. The basic model is fairly simple, so we also solve it parametrically to find the efficient frontier.\n", "\n", "**Download the Repository**
\n", "You can download the repository containing this and other examples by clicking [here](https://github.com/Gurobi/modeling-examples/archive/master.zip). \n", "\n", "\n", "## Model Formulation\n", "### Parameters\n", "\n", "We use the [Greek values](https://en.wikipedia.org/wiki/Greeks_\\(finance\\)) that are traditional in finance:\n", "\n", "- $\\delta$: n-element vector measuring the change in price for each stock\n", "- $\\sigma$: n x n matrix measuring the covariance among stocks\n", "\n", "There is one additional parameter when solving the model parametrically:\n", "\n", "- r: target return\n", "\n", "\n", "### Decision Variables\n", "- $x \\ge 0$: n-element vector where each element represents the fraction of the porfolio to invest in each stock\n", "\n", "### Objective Function\n", "Minimize the total risk, a convex quadratic function:\n", "\n", "\\begin{equation}\n", "\\min x^t \\cdot \\sigma \\cdot x\n", "\\end{equation}\n", "\n", "### Constraints\n", "\n", "Allocate the entire portfolio: the total investments should be 1.0 (100%), where $e$ is a unit vector (all 1's):\n", "\n", "\\begin{equation}\n", "e \\cdot x = 1\n", "\\end{equation}\n", "\n", "\n", "Return: When we solve the model parametrically for different return values $r$, we add a constraint on the target return:\n", "\n", "\\begin{equation}\n", "\\delta \\cdot x = r\n", "\\end{equation}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Python Implementation\n", "### Stock data\n", "Use [yfinance](https://pypi.org/project/yfinance/) library to get the latest 2 years of _actual stock data_ from the 20 most profitable US companies, [according to Wikipedia in April 2021](https://en.wikipedia.org/wiki/List_of_largest_companies_in_the_United_States_by_revenue#List_of_companies_by_profit)." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Requirement already satisfied: gurobipy in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (10.0.3)Note: you may need to restart the kernel to use updated packages.\n", "\n", "Collecting yfinance\n", " Obtaining dependency information for yfinance from https://files.pythonhosted.org/packages/e6/b3/388ab967a387cc92926f70e97688dd9a7189b29a0773db815ffc5289e2b5/yfinance-0.2.31-py2.py3-none-any.whl.metadata\n", " Downloading yfinance-0.2.31-py2.py3-none-any.whl.metadata (11 kB)\n", "Requirement already satisfied: pandas>=1.3.0 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (1.5.3)\n", "Requirement already satisfied: numpy>=1.16.5 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (1.24.3)\n", "Requirement already satisfied: requests>=2.31 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (2.31.0)\n", "Collecting multitasking>=0.0.7 (from yfinance)\n", " Downloading multitasking-0.0.11-py3-none-any.whl (8.5 kB)\n", "Requirement already satisfied: lxml>=4.9.1 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (4.9.3)\n", "Requirement already satisfied: appdirs>=1.4.4 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (1.4.4)\n", "Requirement already satisfied: pytz>=2022.5 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (2022.7)\n", "Collecting frozendict>=2.3.4 (from yfinance)\n", " Downloading frozendict-2.3.8-py311-none-any.whl (14 kB)\n", "Collecting peewee>=3.16.2 (from yfinance)\n", " Downloading peewee-3.17.0.tar.gz (2.9 MB)\n", " ---------------------------------------- 0.0/2.9 MB ? eta -:--:--\n", " --------------------------------------- 0.0/2.9 MB 991.0 kB/s eta 0:00:03\n", " -- ------------------------------------- 0.2/2.9 MB 2.4 MB/s eta 0:00:02\n", " ------ --------------------------------- 0.5/2.9 MB 3.5 MB/s eta 0:00:01\n", " --------- ------------------------------ 0.7/2.9 MB 4.2 MB/s eta 0:00:01\n", " ------------- -------------------------- 1.0/2.9 MB 4.2 MB/s eta 0:00:01\n", " ----------------- ---------------------- 1.3/2.9 MB 4.8 MB/s eta 0:00:01\n", " --------------------- ------------------ 1.6/2.9 MB 4.9 MB/s eta 0:00:01\n", " --------------------------- ------------ 2.0/2.9 MB 5.3 MB/s eta 0:00:01\n", " ------------------------------- -------- 2.3/2.9 MB 5.5 MB/s eta 0:00:01\n", " ----------------------------------- ---- 2.6/2.9 MB 5.8 MB/s eta 0:00:01\n", " ------------------------------------- -- 2.8/2.9 MB 5.5 MB/s eta 0:00:01\n", " ---------------------------------------- 2.9/2.9 MB 5.4 MB/s eta 0:00:00\n", " Installing build dependencies: started\n", " Installing build dependencies: finished with status 'done'\n", " Getting requirements to build wheel: started\n", " Getting requirements to build wheel: finished with status 'done'\n", " Preparing metadata (pyproject.toml): started\n", " Preparing metadata (pyproject.toml): finished with status 'done'\n", "Requirement already satisfied: beautifulsoup4>=4.11.1 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from yfinance) (4.12.2)\n", "Collecting html5lib>=1.1 (from yfinance)\n", " Downloading html5lib-1.1-py2.py3-none-any.whl (112 kB)\n", " ---------------------------------------- 0.0/112.2 kB ? eta -:--:--\n", " -------------------------------------- 112.2/112.2 kB 3.3 MB/s eta 0:00:00\n", "Requirement already satisfied: soupsieve>1.2 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from beautifulsoup4>=4.11.1->yfinance) (2.4)\n", "Requirement already satisfied: six>=1.9 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from html5lib>=1.1->yfinance) (1.16.0)\n", "Requirement already satisfied: webencodings in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from html5lib>=1.1->yfinance) (0.5.1)\n", "Requirement already satisfied: python-dateutil>=2.8.1 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from pandas>=1.3.0->yfinance) (2.8.2)\n", "Requirement already satisfied: charset-normalizer<4,>=2 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from requests>=2.31->yfinance) (2.0.4)\n", "Requirement already satisfied: idna<4,>=2.5 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from requests>=2.31->yfinance) (3.4)\n", "Requirement already satisfied: urllib3<3,>=1.21.1 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from requests>=2.31->yfinance) (1.26.16)\n", "Requirement already satisfied: certifi>=2017.4.17 in c:\\users\\pancho\\anaconda3\\envs\\proyectonestle\\lib\\site-packages (from requests>=2.31->yfinance) (2023.7.22)\n", "Downloading yfinance-0.2.31-py2.py3-none-any.whl (65 kB)\n", " ---------------------------------------- 0.0/65.6 kB ? eta -:--:--\n", " ---------------------------------------- 65.6/65.6 kB 3.5 MB/s eta 0:00:00\n", "Building wheels for collected packages: peewee\n", " Building wheel for peewee (pyproject.toml): started\n", " Building wheel for peewee (pyproject.toml): finished with status 'done'\n", " Created wheel for peewee: filename=peewee-3.17.0-py3-none-any.whl size=135766 sha256=5974096996eb451920df562db0e487aaaadf1e6bcbdf3cb7d241d48eb0a55d81\n", " Stored in directory: c:\\users\\pancho\\appdata\\local\\pip\\cache\\wheels\\02\\20\\23\\74a10d0cd31f5d41c19b92ddf4c138ceff01b9f4675f19dbf5\n", "Successfully built peewee\n", "Installing collected packages: peewee, multitasking, html5lib, frozendict, yfinance\n", "Successfully installed frozendict-2.3.8 html5lib-1.1 multitasking-0.0.11 peewee-3.17.0 yfinance-0.2.31\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ " WARNING: The script sample.exe is installed in 'C:\\Users\\Pancho\\anaconda3\\envs\\ProyectoNestle\\Scripts' which is not on PATH.\n", " Consider adding this directory to PATH or, if you prefer to suppress this warning, use --no-warn-script-location.\n" ] } ], "source": [ "%pip install gurobipy yfinance" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[*********************100%%**********************] 20 of 20 completed\n" ] } ], "source": [ "import yfinance as yf\n", "\n", "stocks = ['BRK-A', 'AAPL', 'MSFT', 'JPM', 'GOOG', 'BAC', 'INTC', 'WFC',\n", " 'C', 'VZ', 'META', 'PFE', 'JNJ', 'WMT', 'XOM',\n", " 'FNMA', 'T', 'UNH', 'CMCSA', 'V' ]\n", "\n", "data = yf.download(stocks, period='2y')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Compute Greeks\n", "Using the downloaded stock data, find the delta (return), sigma (covariance) and standard deviation values for stock prices:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "closes = np.transpose(np.array(data.Close)) # matrix of daily closing prices\n", "absdiff = np.diff(closes) # change in closing price each day\n", "reldiff = np.divide(absdiff, closes[:,:-1]) # relative change in daily closing price\n", "delta = np.mean(reldiff, axis=1) # mean price change\n", "sigma = np.cov(reldiff) # covariance (standard deviations)\n", "std = np.std(reldiff, axis=1) # standard deviation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Minimize risk by solving QP model" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Set parameter Username\n", "Academic license - for non-commercial use only - expires 2023-12-07\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 1 rows, 20 columns and 20 nonzeros\n", "Model fingerprint: 0x8083dace\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [1e+00, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [1e+00, 1e+00]\n", "Presolve time: 0.02s\n", "Presolved: 1 rows, 20 columns, 20 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 1.900e+02\n", " Factor NZ : 2.100e+02\n", " Factor Ops : 2.870e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39659952e+05 -2.39659952e+05 1.24e+04 8.21e-07 1.00e+06 0s\n", " 1 1.05586674e+05 -1.05609528e+05 1.15e+03 7.60e-08 1.02e+05 0s\n", " 2 1.75003400e+03 -1.77843491e+03 3.01e+01 2.00e-09 2.93e+03 0s\n", " 3 3.17477419e-02 -3.04635273e+01 6.52e-02 4.33e-12 7.88e+00 0s\n", " 4 1.21242809e-03 -1.99285264e+01 6.52e-08 4.55e-18 9.96e-01 0s\n", " 5 1.21218354e-03 -2.11465359e-02 7.96e-12 3.47e-18 1.12e-03 0s\n", " 6 9.50377488e-04 -1.04906728e-03 2.19e-13 4.34e-19 1.00e-04 0s\n", " 7 1.92539823e-04 -7.14636096e-04 6.94e-18 2.08e-17 4.54e-05 0s\n", " 8 1.03056536e-04 2.93648920e-06 1.04e-17 1.63e-17 5.01e-06 0s\n", " 9 7.56748365e-05 4.67875996e-05 3.30e-17 8.67e-19 1.44e-06 0s\n", " 10 7.11581951e-05 6.86860873e-05 3.47e-18 8.67e-19 1.24e-07 0s\n", " 11 7.04392044e-05 7.01891298e-05 7.89e-17 5.53e-18 1.25e-08 0s\n", " 12 7.03463170e-05 7.03378302e-05 1.73e-17 1.62e-18 4.24e-10 0s\n", "\n", "Barrier solved model in 12 iterations and 0.06 seconds (0.00 work units)\n", "Optimal objective 7.03463170e-05\n", "\n" ] } ], "source": [ "import gurobipy as gp\n", "from gurobipy import GRB\n", "from math import sqrt\n", "\n", "# Create an empty model\n", "m = gp.Model('portfolio')\n", "\n", "# Add matrix variable for the stocks\n", "x = m.addMVar(len(stocks))\n", "\n", "# Objective is to minimize risk (squared). This is modeled using the\n", "# covariance matrix, which measures the historical correlation between stocks\n", "portfolio_risk = x @ sigma @ x\n", "m.setObjective(portfolio_risk, GRB.MINIMIZE)\n", "\n", "# Fix budget with a constraint\n", "m.addConstr(x.sum() == 1, 'budget')\n", "\n", "# Verify model formulation\n", "m.write('portfolio_selection_optimization.lp')\n", "\n", "# Optimize model to find the minimum risk portfolio\n", "m.optimize()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Display minimum risk portfolio using Pandas" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
Minimum Risk Portfolio
BRK-A0.000017
AAPL0.000024
MSFT0.054089
JPM0.000286
GOOG0.024058
BAC0.025590
INTC0.000066
WFC0.000074
C0.345902
VZ0.010441
META0.000019
PFE0.018616
JNJ0.044215
WMT0.022510
XOM0.064354
FNMA0.029768
T0.111170
UNH0.000046
CMCSA0.172376
V0.076379
Volatility0.008387
Expected Return0.000076
\n", "
" ], "text/plain": [ " Minimum Risk Portfolio\n", "BRK-A 0.000017\n", "AAPL 0.000024\n", "MSFT 0.054089\n", "JPM 0.000286\n", "GOOG 0.024058\n", "BAC 0.025590\n", "INTC 0.000066\n", "WFC 0.000074\n", "C 0.345902\n", "VZ 0.010441\n", "META 0.000019\n", "PFE 0.018616\n", "JNJ 0.044215\n", "WMT 0.022510\n", "XOM 0.064354\n", "FNMA 0.029768\n", "T 0.111170\n", "UNH 0.000046\n", "CMCSA 0.172376\n", "V 0.076379\n", "Volatility 0.008387\n", "Expected Return 0.000076" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "minrisk_volatility = sqrt(m.ObjVal)\n", "minrisk_return = delta @ x.X\n", "pd.DataFrame(data=np.append(x.X, [minrisk_volatility, minrisk_return]),\n", " index=stocks + ['Volatility', 'Expected Return'],\n", " columns=['Minimum Risk Portfolio'])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Compute the efficient frontier\n", "Solve the QP parametrically to find the lowest risk portfolio for different expected returns." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x19f72433\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [9e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39744491e+05 -2.39744491e+05 1.24e+04 6.18e-03 1.00e+06 0s\n", " 1 8.93011808e+04 -8.93203537e+04 1.26e+03 6.27e-04 1.10e+05 0s\n", " 2 8.12087614e+02 -8.33382522e+02 3.15e+01 1.57e-05 2.89e+03 0s\n", " 3 2.28111897e-03 -2.09385660e+01 4.79e-02 2.39e-08 5.44e+00 0s\n", " 4 1.71787665e-04 -2.00805784e+00 1.71e-03 8.52e-10 2.62e-01 0s\n", " 5 2.71839514e-04 -8.99732139e-02 3.70e-05 1.85e-11 9.14e-03 0s\n", " 6 2.71973255e-04 9.04766145e-05 3.74e-08 1.87e-14 1.38e-05 0s\n", " 7 2.71973388e-04 2.71791892e-04 3.74e-11 1.91e-17 1.38e-08 0s\n", " 8 2.71973388e-04 2.71973207e-04 3.74e-14 1.36e-12 1.38e-11 0s\n", "\n", "Barrier solved model in 8 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 2.71973388e-04\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x91150d1d\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [8e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39743202e+05 -2.39743202e+05 1.24e+04 6.09e-03 1.00e+06 0s\n", " 1 8.93012149e+04 -8.93207268e+04 1.26e+03 6.18e-04 1.10e+05 0s\n", " 2 8.12084626e+02 -8.34034919e+02 3.15e+01 1.55e-05 2.89e+03 0s\n", " 3 2.23560714e-03 -2.17312632e+01 4.56e-02 2.24e-08 5.27e+00 0s\n", " 4 1.55765607e-04 -4.36863980e+00 7.15e-04 3.51e-10 2.77e-01 0s\n", " 5 1.68723249e-04 -3.60635194e-01 7.15e-10 3.52e-16 1.80e-02 0s\n", " 6 1.68713476e-04 -2.31593299e-04 8.03e-14 2.75e-14 2.00e-05 0s\n", " 7 1.61508300e-04 1.32796168e-04 1.50e-15 4.72e-16 1.44e-06 0s\n", " 8 1.47568788e-04 1.41612398e-04 1.67e-15 1.39e-17 2.98e-07 0s\n", " 9 1.43991933e-04 1.43602616e-04 1.16e-15 1.39e-17 1.95e-08 0s\n", " 10 1.43672156e-04 1.43655923e-04 7.24e-15 6.34e-18 8.12e-10 0s\n", " 11 1.43661659e-04 1.43659871e-04 4.24e-13 1.11e-17 8.94e-11 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 1.43661659e-04\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x02ba5f29\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [7e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39741914e+05 -2.39741914e+05 1.24e+04 5.99e-03 1.00e+06 0s\n", " 1 8.93012452e+04 -8.93210963e+04 1.26e+03 6.08e-04 1.10e+05 0s\n", " 2 8.12081565e+02 -8.34687193e+02 3.15e+01 1.52e-05 2.89e+03 0s\n", " 3 2.19574764e-03 -2.25218309e+01 4.33e-02 2.10e-08 5.10e+00 0s\n", " 4 1.44317496e-04 -6.34898211e+00 2.13e-04 1.03e-10 3.33e-01 0s\n", " 5 1.45374506e-04 -2.02028381e-02 5.36e-08 2.59e-14 1.02e-03 0s\n", " 6 1.45170724e-04 3.22289993e-05 2.37e-10 1.14e-16 5.65e-06 0s\n", " 7 1.26961662e-04 8.80730283e-05 2.32e-16 8.67e-19 1.94e-06 0s\n", " 8 1.23649939e-04 1.18931759e-04 6.77e-17 4.12e-18 2.36e-07 0s\n", " 9 1.20979049e-04 1.20123124e-04 4.51e-17 2.39e-18 4.28e-08 0s\n", " 10 1.20448560e-04 1.20433979e-04 1.86e-16 1.47e-18 7.29e-10 0s\n", " 11 1.20435595e-04 1.20435322e-04 1.62e-15 3.36e-18 1.36e-11 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 1.20435595e-04\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x410706f3\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [6e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39740625e+05 -2.39740625e+05 1.24e+04 5.90e-03 1.00e+06 0s\n", " 1 8.93012657e+04 -8.93214558e+04 1.26e+03 5.99e-04 1.10e+05 0s\n", " 2 8.12078231e+02 -8.35339143e+02 3.15e+01 1.50e-05 2.89e+03 0s\n", " 3 2.15740416e-03 -2.33104903e+01 4.11e-02 1.96e-08 4.94e+00 0s\n", " 4 1.38530806e-04 -8.59023947e+00 4.11e-08 1.96e-14 4.30e-01 0s\n", " 5 1.38530013e-04 -8.58549632e-03 6.40e-13 6.15e-13 4.36e-04 0s\n", " 6 1.37810616e-04 -1.67313784e-06 8.84e-15 8.16e-15 6.97e-06 0s\n", " 7 1.17419694e-04 6.44693929e-05 4.16e-17 1.04e-17 2.65e-06 0s\n", " 8 1.10831687e-04 1.01419866e-04 5.20e-17 4.55e-18 4.71e-07 0s\n", " 9 1.06241369e-04 1.04824521e-04 3.99e-17 1.73e-18 7.08e-08 0s\n", " 10 1.05475288e-04 1.05426533e-04 7.81e-17 2.17e-18 2.44e-09 0s\n", " 11 1.05453692e-04 1.05451844e-04 9.16e-16 1.30e-18 9.24e-11 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 1.05453692e-04\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x2fedd0ee\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [5e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39739337e+05 -2.39739337e+05 1.24e+04 5.80e-03 1.00e+06 0s\n", " 1 8.93012862e+04 -8.93218154e+04 1.26e+03 5.89e-04 1.10e+05 0s\n", " 2 8.12074897e+02 -8.35991046e+02 3.15e+01 1.48e-05 2.89e+03 0s\n", " 3 2.11009779e-03 -2.40976102e+01 3.87e-02 1.82e-08 4.76e+00 0s\n", " 4 1.42332240e-04 -9.91614860e+00 3.87e-08 1.82e-14 4.96e-01 0s\n", " 5 1.42330689e-04 -9.93705179e-03 6.38e-13 2.18e-13 5.04e-04 0s\n", " 6 1.41167618e-04 -2.94551879e-05 8.88e-15 2.56e-15 8.53e-06 0s\n", " 7 1.09693091e-04 4.01989574e-05 4.86e-17 6.94e-18 3.47e-06 0s\n", " 8 1.00280754e-04 8.79196214e-05 1.04e-17 3.25e-18 6.18e-07 0s\n", " 9 9.53796176e-05 9.36488160e-05 2.43e-17 2.60e-18 8.65e-08 0s\n", " 10 9.45289239e-05 9.44888245e-05 1.49e-16 2.60e-18 2.00e-09 0s\n", " 11 9.44983050e-05 9.44982527e-05 1.58e-16 2.49e-18 2.62e-12 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 9.44983050e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xc90fe247\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [4e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39738048e+05 -2.39738048e+05 1.24e+04 5.71e-03 1.00e+06 0s\n", " 1 8.93013050e+04 -8.93221732e+04 1.26e+03 5.79e-04 1.10e+05 0s\n", " 2 8.12071571e+02 -8.36642906e+02 3.15e+01 1.45e-05 2.89e+03 0s\n", " 3 2.12722849e-03 -2.48830819e+01 3.68e-02 1.70e-08 4.62e+00 0s\n", " 4 1.56225621e-04 -1.09498023e+01 3.68e-08 1.70e-14 5.47e-01 0s\n", " 5 1.56222379e-04 -1.09788241e-02 6.23e-13 8.36e-13 5.57e-04 0s\n", " 6 1.53876379e-04 -4.30906851e-05 8.27e-15 1.06e-14 9.85e-06 0s\n", " 7 9.76628583e-05 -3.51403392e-06 6.94e-18 3.47e-18 5.06e-06 0s\n", " 8 9.05972993e-05 8.14331922e-05 2.78e-17 3.04e-18 4.58e-07 0s\n", " 9 8.73147865e-05 8.59427534e-05 6.59e-17 1.73e-18 6.86e-08 0s\n", " 10 8.64291505e-05 8.63584505e-05 7.63e-17 2.28e-18 3.54e-09 0s\n", " 11 8.63824420e-05 8.63823662e-05 4.68e-17 1.73e-18 3.79e-12 0s\n", "\n", "Barrier solved model in 11 iterations and 0.04 seconds (0.00 work units)\n", "Optimal objective 8.63824420e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xe1936c0f\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [4e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39736760e+05 -2.39736760e+05 1.24e+04 5.61e-03 1.00e+06 0s\n", " 1 8.93013322e+04 -8.93225395e+04 1.26e+03 5.70e-04 1.10e+05 0s\n", " 2 8.12068259e+02 -8.37294730e+02 3.15e+01 1.43e-05 2.89e+03 0s\n", " 3 2.27270393e-03 -2.56669232e+01 3.57e-02 1.62e-08 4.56e+00 0s\n", " 4 1.79709246e-04 -1.18815974e+01 3.57e-08 1.62e-14 5.94e-01 0s\n", " 5 1.79702724e-04 -1.19650084e-02 7.91e-13 4.90e-13 6.07e-04 0s\n", " 6 1.74382603e-04 -7.54838775e-05 9.06e-15 5.67e-15 1.25e-05 0s\n", " 7 9.32653343e-05 -2.65734616e-05 8.67e-18 3.69e-18 5.99e-06 0s\n", " 8 8.41222916e-05 7.46927990e-05 2.78e-17 5.64e-18 4.71e-07 0s\n", " 9 8.10845560e-05 7.96675426e-05 4.86e-17 1.63e-18 7.09e-08 0s\n", " 10 8.05033009e-05 8.04338636e-05 5.03e-17 2.49e-18 3.47e-09 0s\n", " 11 8.04508825e-05 8.04505278e-05 3.47e-16 4.55e-18 1.77e-11 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 8.04508825e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x5bb3322f\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [3e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39735471e+05 -2.39735471e+05 1.24e+04 5.52e-03 1.00e+06 0s\n", " 1 8.93013518e+04 -8.93228982e+04 1.26e+03 5.60e-04 1.10e+05 0s\n", " 2 8.12064742e+02 -8.37946301e+02 3.15e+01 1.40e-05 2.89e+03 0s\n", " 3 2.41669450e-03 -2.64491032e+01 3.45e-02 1.54e-08 4.49e+00 0s\n", " 4 2.15168383e-04 -1.25250305e+01 3.45e-08 1.54e-14 6.26e-01 0s\n", " 5 2.15155792e-04 -1.27114304e-02 1.11e-12 1.67e-13 6.46e-04 0s\n", " 6 2.04274613e-04 -1.31370124e-04 1.31e-14 1.98e-15 1.68e-05 0s\n", " 7 9.82964270e-05 -2.92020040e-05 3.47e-18 1.95e-18 6.37e-06 0s\n", " 8 8.08232365e-05 6.42893736e-05 3.99e-17 2.93e-18 8.27e-07 0s\n", " 9 7.72516417e-05 7.56098983e-05 1.82e-16 1.19e-18 8.21e-08 0s\n", " 10 7.66867685e-05 7.65281240e-05 7.63e-17 4.23e-18 7.93e-09 0s\n", " 11 7.66097860e-05 7.66025615e-05 8.15e-17 4.41e-18 3.61e-10 0s\n", "\n", "Barrier solved model in 11 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.66097860e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xe15de684\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [2e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39734183e+05 -2.39734183e+05 1.24e+04 5.43e-03 1.00e+06 0s\n", " 1 8.93014410e+04 -8.93233264e+04 1.26e+03 5.51e-04 1.10e+05 0s\n", " 2 8.12063216e+02 -8.38599806e+02 3.15e+01 1.38e-05 2.89e+03 0s\n", " 3 2.56315224e-03 -2.72294464e+01 3.32e-02 1.46e-08 4.41e+00 0s\n", " 4 2.63643076e-04 -1.29015173e+01 3.32e-08 1.46e-14 6.45e-01 0s\n", " 5 2.63620002e-04 -1.32527227e-02 1.58e-12 2.54e-13 6.76e-04 0s\n", " 6 2.43804954e-04 -2.08811889e-04 2.44e-14 3.68e-15 2.26e-05 0s\n", " 7 1.06120044e-04 -5.95316960e-05 6.94e-18 3.47e-18 8.28e-06 0s\n", " 8 7.97056810e-05 5.35614532e-05 3.82e-17 4.12e-18 1.31e-06 0s\n", " 9 7.48122691e-05 7.16230336e-05 2.81e-16 2.20e-18 1.59e-07 0s\n", " 10 7.40354539e-05 7.36728755e-05 3.47e-17 2.32e-18 1.81e-08 0s\n", " 11 7.39092589e-05 7.38653017e-05 1.65e-17 1.95e-18 2.20e-09 0s\n", " 12 7.38873880e-05 7.38868416e-05 3.82e-17 1.27e-18 2.73e-11 0s\n", "\n", "Barrier solved model in 12 iterations and 0.04 seconds (0.00 work units)\n", "Optimal objective 7.38873880e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xec55df2f\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [1e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39732894e+05 -2.39732894e+05 1.24e+04 5.33e-03 1.00e+06 0s\n", " 1 8.93015411e+04 -8.93237655e+04 1.26e+03 5.41e-04 1.10e+05 0s\n", " 2 8.12062173e+02 -8.39253745e+02 3.15e+01 1.36e-05 2.89e+03 0s\n", " 3 2.71596454e-03 -2.80078561e+01 3.19e-02 1.37e-08 4.33e+00 0s\n", " 4 3.26144776e-04 -1.30301820e+01 3.19e-08 1.37e-14 6.52e-01 0s\n", " 5 3.26104431e-04 -1.36093155e-02 2.22e-12 1.73e-18 6.97e-04 0s\n", " 6 2.90549537e-04 -2.75958243e-04 3.71e-14 1.73e-18 2.83e-05 0s\n", " 7 1.14946361e-04 -8.55982445e-05 8.67e-18 3.47e-18 1.00e-05 0s\n", " 8 7.95871176e-05 4.55630359e-05 4.34e-17 3.90e-18 1.70e-06 0s\n", " 9 7.30395710e-05 6.86595811e-05 2.32e-16 1.29e-18 2.19e-07 0s\n", " 10 7.21486631e-05 7.18337758e-05 1.47e-17 6.51e-19 1.57e-08 0s\n", " 11 7.19891802e-05 7.19687525e-05 3.82e-17 7.91e-18 1.02e-09 0s\n", " 12 7.19803880e-05 7.19797418e-05 7.29e-17 9.64e-19 3.23e-11 0s\n", "\n", "Barrier solved model in 12 iterations and 0.04 seconds (0.00 work units)\n", "Optimal objective 7.19803880e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x301961a4\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [2e-05, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39731606e+05 -2.39731606e+05 1.24e+04 5.24e-03 1.00e+06 0s\n", " 1 8.93016907e+04 -8.93242542e+04 1.26e+03 5.32e-04 1.10e+05 0s\n", " 2 8.12063380e+02 -8.39909889e+02 3.15e+01 1.33e-05 2.89e+03 0s\n", " 3 2.88361342e-03 -2.87843426e+01 3.07e-02 1.30e-08 4.26e+00 0s\n", " 4 4.03803551e-04 -1.29351307e+01 3.07e-08 1.30e-14 6.47e-01 0s\n", " 5 4.03735641e-04 -1.38398851e-02 3.11e-12 2.07e-13 7.12e-04 0s\n", " 6 3.43689415e-04 -3.56310538e-04 5.77e-14 4.17e-15 3.50e-05 0s\n", " 7 1.26800037e-04 -1.17295531e-04 2.08e-17 8.46e-18 1.22e-05 0s\n", " 8 8.10110513e-05 3.73568295e-05 3.64e-17 5.20e-18 2.18e-06 0s\n", " 9 7.21552089e-05 6.57765007e-05 9.37e-17 2.60e-18 3.19e-07 0s\n", " 10 7.10864692e-05 7.03164595e-05 7.81e-18 5.74e-18 3.85e-08 0s\n", " 11 7.08418207e-05 7.08032667e-05 1.04e-17 1.73e-18 1.93e-09 0s\n", " 12 7.08286454e-05 7.08283471e-05 3.47e-17 6.23e-18 1.49e-11 0s\n", "\n", "Barrier solved model in 12 iterations and 0.04 seconds (0.00 work units)\n", "Optimal objective 7.08286454e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xc23e0c3a\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [7e-05, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39730317e+05 -2.39730317e+05 1.24e+04 5.14e-03 1.00e+06 0s\n", " 1 8.93018439e+04 -8.93247464e+04 1.26e+03 5.22e-04 1.10e+05 0s\n", " 2 8.12064747e+02 -8.40566147e+02 3.14e+01 1.31e-05 2.89e+03 0s\n", " 3 3.06629801e-03 -2.95589013e+01 2.96e-02 1.23e-08 4.20e+00 0s\n", " 4 4.97905593e-04 -1.26047160e+01 2.96e-08 1.23e-14 6.30e-01 0s\n", " 5 4.97793994e-04 -1.39994342e-02 4.45e-12 1.73e-18 7.25e-04 0s\n", " 6 4.02585743e-04 -4.93498678e-04 1.12e-13 1.73e-18 4.48e-05 0s\n", " 7 1.47626246e-04 -1.41763578e-04 8.67e-18 7.37e-18 1.45e-05 0s\n", " 8 8.50517027e-05 4.63749514e-06 8.67e-18 3.47e-18 4.02e-06 0s\n", " 9 7.22951896e-05 6.40544894e-05 6.94e-18 2.52e-18 4.12e-07 0s\n", " 10 7.07615968e-05 6.96833750e-05 3.90e-16 2.37e-18 5.39e-08 0s\n", " 11 7.03853569e-05 7.03146952e-05 3.30e-17 1.46e-18 3.53e-09 0s\n", " 12 7.03486574e-05 7.03476589e-05 2.78e-17 8.67e-19 4.99e-11 0s\n", "\n", "Barrier solved model in 12 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.03486574e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x51710fd1\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [1e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39729029e+05 -2.39729029e+05 1.24e+04 5.05e-03 1.00e+06 0s\n", " 1 8.93019970e+04 -8.93252385e+04 1.26e+03 5.13e-04 1.10e+05 0s\n", " 2 8.12066115e+02 -8.41222359e+02 3.14e+01 1.28e-05 2.89e+03 0s\n", " 3 3.25632453e-03 -3.03315252e+01 2.85e-02 1.16e-08 4.13e+00 0s\n", " 4 6.10172767e-04 -1.19776189e+01 2.85e-08 1.16e-14 5.99e-01 0s\n", " 5 6.09989841e-04 -1.41767304e-02 6.69e-12 2.28e-18 7.39e-04 0s\n", " 6 4.60575679e-04 -6.23684656e-04 2.20e-13 1.73e-18 5.42e-05 0s\n", " 7 1.43498047e-04 -2.99347656e-04 1.04e-17 1.04e-17 2.21e-05 0s\n", " 8 8.85926406e-05 2.39550749e-05 8.67e-18 9.54e-18 3.23e-06 0s\n", " 9 7.36603214e-05 5.93880466e-05 5.20e-17 2.44e-18 7.14e-07 0s\n", " 10 7.14256722e-05 6.92233530e-05 8.67e-18 1.84e-18 1.10e-07 0s\n", " 11 7.07591683e-05 7.05234605e-05 3.32e-17 7.59e-19 1.18e-08 0s\n", " 12 7.06434785e-05 7.06367117e-05 1.15e-17 2.49e-18 3.38e-10 0s\n", "\n", "Barrier solved model in 12 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.06434785e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x96276297\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [2e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39727740e+05 -2.39727740e+05 1.24e+04 4.96e-03 1.00e+06 0s\n", " 1 8.93021501e+04 -8.93257307e+04 1.26e+03 5.03e-04 1.10e+05 0s\n", " 2 8.12067484e+02 -8.41878525e+02 3.14e+01 1.26e-05 2.89e+03 0s\n", " 3 3.43397283e-03 -3.11021989e+01 2.71e-02 1.08e-08 4.04e+00 0s\n", " 4 7.44047201e-04 -1.08887700e+01 2.71e-08 1.08e-14 5.44e-01 0s\n", " 5 7.43737664e-04 -1.45502895e-02 1.10e-11 3.66e-18 7.65e-04 0s\n", " 6 5.04455629e-04 -7.99075963e-04 5.05e-13 1.73e-18 6.52e-05 0s\n", " 7 1.24081139e-04 -5.49219172e-04 1.73e-17 1.59e-17 3.37e-05 0s\n", " 8 9.44672705e-05 2.26867127e-05 5.20e-18 1.56e-17 3.59e-06 0s\n", " 9 7.62667155e-05 5.31463756e-05 6.94e-18 6.42e-18 1.16e-06 0s\n", " 10 7.28523789e-05 7.00959547e-05 6.94e-18 2.82e-18 1.38e-07 0s\n", " 11 7.19595243e-05 7.16983530e-05 1.14e-16 4.23e-18 1.31e-08 0s\n", " 12 7.18211959e-05 7.18105900e-05 2.52e-17 2.17e-18 5.30e-10 0s\n", " 13 7.18164794e-05 7.18157243e-05 5.62e-16 2.06e-18 3.78e-11 0s\n", "\n", "Barrier solved model in 13 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.18164794e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x0ed6f4e0\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [3e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39726452e+05 -2.39726452e+05 1.24e+04 4.86e-03 1.00e+06 0s\n", " 1 8.93023017e+04 -8.93262212e+04 1.26e+03 4.93e-04 1.10e+05 0s\n", " 2 8.12068837e+02 -8.42534629e+02 3.14e+01 1.24e-05 2.89e+03 0s\n", " 3 4.13362076e-03 -3.18710464e+01 3.03e-02 1.19e-08 4.38e+00 0s\n", " 4 8.84056125e-04 -1.00416429e+01 3.01e-04 1.18e-10 5.16e-01 0s\n", " 5 8.20704751e-04 -2.35044269e-01 5.06e-07 1.99e-13 1.18e-02 0s\n", " 6 8.07091155e-04 -1.60799735e-03 3.86e-09 1.52e-15 1.21e-04 0s\n", " 7 1.88402945e-04 -5.21994615e-04 3.86e-15 1.32e-17 3.55e-05 0s\n", " 8 1.04836201e-04 2.00463934e-05 9.71e-17 5.75e-18 4.24e-06 0s\n", " 9 7.97604398e-05 5.74347086e-05 2.43e-17 3.25e-18 1.12e-06 0s\n", " 10 7.53170457e-05 7.28803569e-05 1.39e-17 3.47e-18 1.22e-07 0s\n", " 11 7.42536798e-05 7.40547926e-05 6.94e-17 1.41e-18 9.94e-09 0s\n", " 12 7.41161205e-05 7.41097092e-05 5.03e-17 3.05e-18 3.21e-10 0s\n", "\n", "Barrier solved model in 12 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.41161205e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0xf963ade6\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [4e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39725163e+05 -2.39725163e+05 1.24e+04 4.77e-03 1.00e+06 0s\n", " 1 8.93024531e+04 -8.93267116e+04 1.26e+03 4.84e-04 1.10e+05 0s\n", " 2 8.12070190e+02 -8.43190685e+02 3.14e+01 1.21e-05 2.89e+03 0s\n", " 3 5.08012540e-03 -3.26379235e+01 3.50e-02 1.35e-08 4.85e+00 0s\n", " 4 1.10993595e-03 -1.16855188e+01 2.64e-03 1.02e-09 7.38e-01 0s\n", " 5 4.79717182e-04 -4.09537532e+00 2.64e-09 1.02e-15 2.05e-01 0s\n", " 6 4.79213567e-04 -5.05032776e-03 9.27e-13 1.68e-16 2.76e-04 0s\n", " 7 2.84171377e-04 -2.25417126e-04 2.82e-14 7.99e-17 2.55e-05 0s\n", " 8 1.24969602e-04 -3.28113623e-05 6.94e-18 5.20e-18 7.89e-06 0s\n", " 9 8.74723528e-05 5.73452985e-05 1.94e-16 3.47e-18 1.51e-06 0s\n", " 10 8.00426380e-05 7.34083610e-05 5.20e-18 3.88e-18 3.32e-07 0s\n", " 11 7.82911299e-05 7.80023465e-05 1.56e-17 3.04e-18 1.44e-08 0s\n", " 12 7.81137977e-05 7.81064900e-05 7.42e-17 1.73e-18 3.65e-10 0s\n", "\n", "Barrier solved model in 12 iterations and 0.05 seconds (0.00 work units)\n", "Optimal objective 7.81137977e-05\n", "\n", "Gurobi Optimizer version 10.0.3 build v10.0.3rc0 (win64)\n", "\n", "CPU model: AMD Ryzen 9 5900HX with Radeon Graphics, instruction set [SSE2|AVX|AVX2]\n", "Thread count: 8 physical cores, 16 logical processors, using up to 16 threads\n", "\n", "Optimize a model with 2 rows, 20 columns and 40 nonzeros\n", "Model fingerprint: 0x17351106\n", "Model has 210 quadratic objective terms\n", "Coefficient statistics:\n", " Matrix range [6e-05, 1e+00]\n", " Objective range [0e+00, 0e+00]\n", " QObjective range [8e-06, 4e-03]\n", " Bounds range [0e+00, 0e+00]\n", " RHS range [5e-04, 1e+00]\n", "Presolve time: 0.01s\n", "Presolved: 2 rows, 20 columns, 40 nonzeros\n", "Presolved model has 210 quadratic objective terms\n", "Ordering time: 0.00s\n", "\n", "Barrier statistics:\n", " Free vars : 19\n", " AA' NZ : 2.100e+02\n", " Factor NZ : 2.310e+02\n", " Factor Ops : 3.311e+03 (less than 1 second per iteration)\n", " Threads : 1\n", "\n", " Objective Residual\n", "Iter Primal Dual Primal Dual Compl Time\n", " 0 2.39723875e+05 -2.39723875e+05 1.24e+04 4.67e-03 1.00e+06 0s\n", " 1 8.93026044e+04 -8.93272020e+04 1.26e+03 4.74e-04 1.10e+05 0s\n" ] } ], "source": [ "# Create an expression representing the expected return for the portfolio\n", "portfolio_return = delta @ x\n", "target = m.addConstr(portfolio_return == minrisk_return, 'target')\n", "\n", "# Solve for efficient frontier by varying target return\n", "frontier = np.empty((2,0))\n", "for r in np.linspace(delta.min(), delta.max(), 25):\n", " target.rhs = r\n", " m.optimize()\n", " frontier = np.append(frontier, [[sqrt(m.ObjVal)],[r]], axis=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot results\n", "Use the matplot library to plot the optimized solutions, along with the individual stocks:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "#plt.figure(figsize=(10,10))\n", "\n", "fig, ax = plt.subplots(figsize=(10,8))\n", "\n", "# Plot volatility versus expected return for individual stocks\n", "ax.scatter(x=std, y=delta,\n", " color='Blue', label='Individual Stocks')\n", "for i, stock in enumerate(stocks):\n", " ax.annotate(stock, (std[i], delta[i]))\n", "\n", "# Plot volatility versus expected return for minimum risk portfolio\n", "ax.scatter(x=minrisk_volatility, y=minrisk_return, color='DarkGreen')\n", "ax.annotate('Minimum\\nRisk\\nPortfolio', (minrisk_volatility, minrisk_return),\n", " horizontalalignment='right')\n", "\n", "# Plot efficient frontier\n", "ax.plot(frontier[0], frontier[1], label='Efficient Frontier', color='DarkGreen')\n", "\n", "# Format and display the final plot\n", "ax.axis([frontier[0].min()*0.7, frontier[0].max()*1.3, delta.min()*1.2, delta.max()*1.2])\n", "ax.set_xlabel('Volatility (standard deviation)')\n", "ax.set_ylabel('Expected Return')\n", "ax.legend()\n", "ax.grid()\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "ProyectoNestle", "language": "python", "name": "proyectonestle" }, "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.11.4" } }, "nbformat": 4, "nbformat_minor": 4 }