mirror of
https://github.com/NVIDIA/dgx-spark-playbooks.git
synced 2026-04-23 02:23:53 +00:00
2775 lines
1.6 MiB
Plaintext
2775 lines
1.6 MiB
Plaintext
|
|
{
|
|||
|
|
"cells": [
|
|||
|
|
{
|
|||
|
|
"attachments": {
|
|||
|
|
"7e12dc25-f387-4104-b0fb-25d73de45e5f.png": {
|
|||
|
|
"image/png": "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\n8jTUKnR1aFcYJSw+7GjYu3CP8G3hDyKMIsQRHZEykXGRdZHvozyjSqOGoi2i10TfiFGN4ce0xOJi\nI2MPxU4t9Vq6a+lonF1cUdzdZYbL8pZdW666PH35uXiZeHb8qQRMQlTC0YTP7CB2LXsqkZW4N3GS\nw+Ts5rzgunPLuOM8F14pbyzJJak06VmyS/LO5PEUt5TylAk+k1/Jf5Xqm1qd+j4tKO1w2rf0qPTG\nDHxGQsZZgbwgTdCZqZmZl9knNBUWCYeynLJ2ZU2K/EWHsqHsZdktOVRkWOoWG4m/Ew/nuuZW5X5Y\nEbniVJ5cniCve6XJys0rx/K9839ahV7FWdWxWnv1htXDaxhratZCaxPXdqzTXVe4bnS9z/ojG4gb\n0jb8WmBZUFrwdmPUxtZCjcL1hSPf+XxXXyRdJCoa2OS8qfp79Pf873s222zes/lrMbf4eollSXnJ\n5y2cLdd/sPqh4odvW5O29myz37Z/O3a7YPvdHW47jpTKleaXjuxcsrOpjFZWXPZ2V/yua+W25dW7\nibvFu4cqAipa9ujt2b7nc2VK5Z0qj6rGvep7N+99v4+7r3+/+/6Gao3qkupPP/J/HKzxqWmqNagt\nP4A9kHvg6cHIg10/0X+qO6R6qOTQl8OCw0NHQo901jnU1R1VP7qtHq4X148fizvWe9zzeEuDWUNN\no2JjyQlwQnzi+c8JP9896X+y4xT9VMNp/dN7z1DOFDdBTSubJptTmodaYlr6zvqd7Wh1bj3zi/kv\nh9u026rOKZzbdp54vvD8twv5F6bahe0TF5MvjnTEdzy4FH3pdmdIZ89l/8tXr3hfudTF6Lpw1eVq\n2zWna2ev068337C/0dRt133mV7tfz/TY9zTddLjZ0uvY29q3uO98v1v/xVuet67cZt2+cSfwTt/d\niLuDA3EDQ4PcwWf30u+9up97f/rB+oeYh8WPZB+VP1Z/XPub8W+NQ/ZD54Y9h7ufhD15MMIZefF7\n9u+fRwufkp+Wj2mN1T2zftY27j3e+3zp89EXwhfTE0V/yP2x96XRy9N/uv/ZPRk9OfpK9Orb6y1v\nVN4cfmv7tmMqeOrxu4x30++LP6h8OPKR/rHrU9SnsekVn3GfK74Yf2n96v/14beMb9+EbBF7dhRA\nIQonJQHw+jAA5BgAKL0AEJfOzdizAs19F8wS+E88N4fPij0Ax9YDEOoOQBBiqxGXPqLS7QAEI75w\ndwDb2Eh0fh6end1nRPYYAB6dDOvogCcWdevBP2Rurv9L3f+0QJL1b/Zf56oKL30DaOEAAABWZVhJ\nZk1NACoAAAAIAAGHaQAEAAAAAQAAABoAAAAAAAOShgAHAAAAEgAAAESgAgAEAAAAAQAABlKgAwAE\nAAAAAQAAA3kAAAAAQVNDSUkAAABTY3JlZW5zaG90mueM0wAAAddpVFh0WE1MOmNvbS5hZG9iZS54\nbXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBD\nb3JlIDYuMC4wIj4KICAg
|
|||
|
|
},
|
|||
|
|
"d510574b-6b9e-4ba3-b4a7-7a3f40979945.png": {
|
|||
|
|
"image/png": "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
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "d7e32f85",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"# Quantitative Portfolio Optimization developer example\n",
|
|||
|
|
"\n",
|
|||
|
|
"This notebook introduces NVIDIA's Quantitative Portfolio Optimization developer example. We use the Mean-CVaR model to solve the problem of portfolio asset allocation. We show step-by-step how to pre-process input data, build the optimization model, solve the problem, and backtest the portfolio performance.\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"In particular, we will cover the following in this notebook: \n",
|
|||
|
|
"- **Data-preprocessing** - Calculate daily returns from input price data \n",
|
|||
|
|
"- **Scenario generation** - Use cuML KDE to model returns distribution and generate return scenarios \n",
|
|||
|
|
"- **Model Building** - Build the optimization problem with optional constraints\n",
|
|||
|
|
"- **Solving Optimization on GPU** – Call GPU/CPU solvers with customizable settings to solve the problem\n",
|
|||
|
|
"- **Backtesting** - Visualize and evaluate optimized portfolio\n",
|
|||
|
|
"- **Comparing CPU and GPU Performance** – Evaluate performance solving optimization problem on GPU vs CPU\n",
|
|||
|
|
"\n",
|
|||
|
|
"If you're new to concepts like **[Mean-CVaR (Conditional Value-at-Risk)](https://www.youtube.com/shorts/9u-VrCyneM4)** and would like a deeper dive into the notebook itself as you do it, **[check out the blog: Accelerating Real-Time Financial Decisions with Quantitative Portfolio Optimization](https://developer.nvidia.com/blog/accelerating-real-time-financial-decisions-with-quantitative-portfolio-optimization/)**\n",
|
|||
|
|
"\n",
|
|||
|
|
"Before diving into portfolio optimization...\n",
|
|||
|
|
"## ***PLEASE ENSURE YOU RUN THIS NOTEBOOK WITH THE \"Portfolio Optimization\" KERNEL***\n",
|
|||
|
|
""
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "061ff854",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"## Table of Contents\n",
|
|||
|
|
"\n",
|
|||
|
|
"0. [Portfolio Optimization Setup](#portfolio-optimization-setup)\n",
|
|||
|
|
" - GPU Check\n",
|
|||
|
|
" - Import Libraries\n",
|
|||
|
|
"\n",
|
|||
|
|
"2. [Introduction to Mean-CVaR Optimization](#build-a-mean-cvar-problem)\n",
|
|||
|
|
" - Mathematical Formulation\n",
|
|||
|
|
"\n",
|
|||
|
|
"3. [Data Preprocessing and Model Setup](#data-preprocessing-and-model-setup)\n",
|
|||
|
|
" - Data Preparation\n",
|
|||
|
|
" - Define Problem Parameters\n",
|
|||
|
|
" - Build Mean-CVaR Problem\n",
|
|||
|
|
"\n",
|
|||
|
|
"4. [Solve CVaR Optimization](#solve-cvar-optimization)\n",
|
|||
|
|
" - cuOpt GPU LP Solver\n",
|
|||
|
|
" - CPU Solver Comparison\n",
|
|||
|
|
" - Portfolio Visualization\n",
|
|||
|
|
" - cuOpt GPU MILP Solver\n",
|
|||
|
|
"\n",
|
|||
|
|
"5. [Backtest Portfolio](#backtest-portfolio)\n",
|
|||
|
|
" - Testing Methods\n",
|
|||
|
|
" - Performance Metrics\n",
|
|||
|
|
" - Benchmark Comparison\n",
|
|||
|
|
"\n",
|
|||
|
|
"6. [GPU vs. CPU: Comparison over Different Regimes](#gpu-vs-cpu-comparison-over-different-regimes)\n",
|
|||
|
|
" - Regime Analysis\n",
|
|||
|
|
" - Performance Comparison\n",
|
|||
|
|
"\n",
|
|||
|
|
"7. [Appendix](#appendix)\n",
|
|||
|
|
" - Optional Parameter Constraints\n",
|
|||
|
|
" - cuOpt Python API\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "69085f1c",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"## 0. Portfolio Optimization Setup\n",
|
|||
|
|
"<a id='portfolio-optimization-setup'></a>\n",
|
|||
|
|
"\n",
|
|||
|
|
"Before diving into portfolio optimization, we need to import the necessary libraries and perform initial setup if required.\n",
|
|||
|
|
"\n",
|
|||
|
|
"### 0.1 GPU Check"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 1,
|
|||
|
|
"id": "c9abe356-0892-4c66-9c37-df4375bbc436",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"Sat Dec 6 13:53:03 2025 \n",
|
|||
|
|
"+-----------------------------------------------------------------------------------------+\n",
|
|||
|
|
"| NVIDIA-SMI 580.95.05 Driver Version: 580.95.05 CUDA Version: 13.0 |\n",
|
|||
|
|
"+-----------------------------------------+------------------------+----------------------+\n",
|
|||
|
|
"| GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |\n",
|
|||
|
|
"| Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |\n",
|
|||
|
|
"| | | MIG M. |\n",
|
|||
|
|
"|=========================================+========================+======================|\n",
|
|||
|
|
"| 0 NVIDIA GB10 On | 0000000F:01:00.0 Off | N/A |\n",
|
|||
|
|
"| N/A 40C P0 11W / N/A | Not Supported | 0% Default |\n",
|
|||
|
|
"| | | N/A |\n",
|
|||
|
|
"+-----------------------------------------+------------------------+----------------------+\n",
|
|||
|
|
"\n",
|
|||
|
|
"+-----------------------------------------------------------------------------------------+\n",
|
|||
|
|
"| Processes: |\n",
|
|||
|
|
"| GPU GI CI PID Type Process name GPU Memory |\n",
|
|||
|
|
"| ID ID Usage |\n",
|
|||
|
|
"|=========================================================================================|\n",
|
|||
|
|
"| No running processes found |\n",
|
|||
|
|
"+-----------------------------------------------------------------------------------------+\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"!nvidia-smi"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "7e989cda",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 0.2 Import Libraries\n",
|
|||
|
|
"\n",
|
|||
|
|
"Import the portfolio optimization modules and other required packages.\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 2,
|
|||
|
|
"id": "24968ee6",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"import os\n",
|
|||
|
|
"import cvxpy as cp\n",
|
|||
|
|
"\n",
|
|||
|
|
"from cufolio import cvar_optimizer, cvar_utils, utils\n",
|
|||
|
|
"from cufolio.cvar_parameters import CvarParameters"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "cb3c96f3",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"\n",
|
|||
|
|
"<a id='build-a-mean-cvar-problem'></a>\n",
|
|||
|
|
"## 1. Introduction to Mean-CVaR Optimization\n",
|
|||
|
|
"\n",
|
|||
|
|
"The Mean-CVaR model captures the risk-return trade-off, aiming to maximize expected return while minimizing Conditional Value-at-Risk. \n",
|
|||
|
|
"\n",
|
|||
|
|
"Traditionally, variance of portfolio returns is used as the measure of risk. Here, we use Conditional Value-at-Risk (CVaR) as an alternative risk measure because it provides a more robust assessment of potential tail losses, and allows a data-driven approach to portfolio optimization without making assumptions on the underlying returns distribution. CVaR measures the average worst-case loss of a return distribution. Formally, for a loss random variable L,\n",
|
|||
|
|
"$$\\text{CVaR} = {E}[L| L \\leq \\text{VaR}_\\alpha (L)]$$\n",
|
|||
|
|
"where $\\text{VaR}(L) = \\inf\\{l: P(L \\leq l) \\geq \\alpha \\}$ is the $\\alpha$-quantile of the loss distribution. CVaR is a more appropriate risk measure for portfolios that may contain assets with asymmetric return distribution - it has replaced Value-at-Risk(VaR) in Basel III market-risk rules; Mathematically, CVaR is a coherent risk measure—satisfying subadditivity, translation invariance, positive homogeneity, and monotonicity—which aligns with the diversification principles. Moreover, it has a computationally tractable transformation as a scenario-based optimization: for confidence level $\\alpha$, the CVaR of portfolio ${w}$ can be written in abstract form as \n",
|
|||
|
|
"$$\\text{CVaR}({w}) = \\min_t\\left\\{t + \\frac{1}{1-\\alpha}\\sum_{\\omega \\in \\Omega}p(\\omega)\\max \\{\\text{loss}({w},\\omega) - t, 0\\}\\right\\}, $$\n",
|
|||
|
|
"where $\\Omega$ is the probability space of returns scenarios and $p(\\omega)$ is the probability of a particular scenario $\\omega \\in \\Omega$. Intuitively, this expression represents the portfolio’s average loss below the $\\alpha$-quantile of all return scenarios. This scenario-based formulation makes CVaR more robust regardless whether the asset returns distribution is Gaussian or not. When we use linear loss, i.e. $\\text{loss}(w,\\omega) = -R(\\omega){w}$, with $R$ as the return scenarios matrix of size (num_scenarios, num_assets), the minimization of the CVaR can be transformed into a linear program by replacing the $\\max\\{\\cdot,0\\}$ non-negative operator with an auxiliary variable ${u}$: \n",
|
|||
|
|
"\n",
|
|||
|
|
"\\begin{align*}\n",
|
|||
|
|
"\\text{minimize} \\; \\quad & t + \\frac{1}{1-\\alpha}{p}^\\top {u},\\\\\n",
|
|||
|
|
"\\text{subject to} \\quad &{u} +t \\geq -R^\\top {w},\\\\\n",
|
|||
|
|
"&u\\geq 0\n",
|
|||
|
|
"\\end{align*}\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"Then, we add constraints to model real-world trading limitations:\n",
|
|||
|
|
"- Concentration limits on single assets\n",
|
|||
|
|
"- Amount invested in risk-free assets (cash)\n",
|
|||
|
|
"- Investment budgets\n",
|
|||
|
|
"- Leverage constraints\n",
|
|||
|
|
"- Turnover from an existing portfolio\n",
|
|||
|
|
"- Cardinality constraints (maximum number of assets allowed in the portfolio)\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"The mathematical formulation of the problem is given as follows: \n",
|
|||
|
|
"\\begin{align*}\n",
|
|||
|
|
"\\text{maximize } \\quad &\\mu^\\top {w} - \\lambda_{\\text{ risk}}\\left(t + \\frac{1}{1-\\alpha}p^\\top {u}\\right)\\\\\n",
|
|||
|
|
"\\text{subject to} \\quad &{u} +t \\geq -R^\\top {w}, \\, u \\geq 0 \\quad \\text{ (CVaR)}\\\\\n",
|
|||
|
|
"& \\sum_i w_i + c = 1\\quad \\text{(self-financing)}\\\\\n",
|
|||
|
|
"& w_i^{\\text{ min}} \\leq w_i \\leq w_i^{\\text{ max}}, \\forall i \\quad \\text{ (concentration)}\\\\\n",
|
|||
|
|
"& c^{\\text{ min}} \\leq c \\leq c^{\\text{ max}} \\quad \\text{ (cash)}\\\\\n",
|
|||
|
|
"& L= \\Vert {w} \\Vert_1 \\leq L^{\\text{ limit}} \\quad\\text{ (leverage)}\\\\\n",
|
|||
|
|
"& T = \\Vert {w} - {w}_{\\text{ pre}}\\Vert_1 \\leq T^{\\text{ limit}}\\quad \\text{ (turnover)}\n",
|
|||
|
|
"\\end{align*}"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "948b8261",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"## 2. Data Preprocessing and Model Setup\n",
|
|||
|
|
"<a id='data-preprocessing-and-model-setup'></a>\n",
|
|||
|
|
"\n",
|
|||
|
|
"We start with an example using a 397-stock subset of the S&P 500 stocks. We aim to build a long-short portfolio that maximizes risk-adjusted returns while meeting custom trading constraints. "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "67635399",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 2.1 Data Preparation\n",
|
|||
|
|
"\n",
|
|||
|
|
"We load closing prices from `2021-01-01` to `2024-01-01` and compute daily log‐returns.\n",
|
|||
|
|
"\n",
|
|||
|
|
"Key Components:\n",
|
|||
|
|
"\n",
|
|||
|
|
"- Historical Dataset (`data_path`): CSV file with adjusted closing prices.\n",
|
|||
|
|
"- Regime Information (`regime_dict`): select the market regime \n",
|
|||
|
|
"- Computation Setting (`returns_compute_settings`): \n",
|
|||
|
|
" - type of returns to compute \"LOG\", \"NORMAL\"\n",
|
|||
|
|
" - frequency: dault to 1 - daily returns\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "65ba44d4",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"#### Disclaimer\n",
|
|||
|
|
"*Each user is responsible for checking the content of datasets and the applicable licenses and determining if suitable for the intended use.*"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 3,
|
|||
|
|
"id": "31173d1a",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stderr",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"/home/rapids/notebooks/setup/src/utils.py:530: FutureWarning: YF.download() has changed argument auto_adjust default to True\n",
|
|||
|
|
" data = yf.download(tickers, start=start_date, end=end_date, timeout = 30)\n",
|
|||
|
|
"[*********************100%***********************] 392 of 392 completed\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# User inputs for S&P 500 example\n",
|
|||
|
|
"dataset_name = \"sp500\"\n",
|
|||
|
|
"dataset_format = \"csv\"\n",
|
|||
|
|
"data_dir = \"./data/stock_data\"\n",
|
|||
|
|
"data_path = f\"{data_dir}/{dataset_name}.{dataset_format}\"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Create data folder structure if it doesn't exst \n",
|
|||
|
|
"if not os.path.exists(data_dir):\n",
|
|||
|
|
" print('creating data directory')\n",
|
|||
|
|
" os.system(f'mkdir -p {data_dir}')\n",
|
|||
|
|
" \n",
|
|||
|
|
"# Download data if not exists\n",
|
|||
|
|
"if not os.path.exists(data_path):\n",
|
|||
|
|
" utils.download_data(data_path)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 4,
|
|||
|
|
"id": "dbbf9697",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"# Set date range\n",
|
|||
|
|
"regime_name = \"recent\" \n",
|
|||
|
|
"time_range = (\"2021-01-01\", \"2024-01-01\")\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Define the regime for this example\n",
|
|||
|
|
"regime_dict = {\"name\": regime_name, \"range\": time_range}\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Define the settings for returns computation\n",
|
|||
|
|
"returns_compute_settings = {'return_type': 'LOG', 'freq': 1}\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Compute returns from price data\n",
|
|||
|
|
"returns_dict = utils.calculate_returns(\n",
|
|||
|
|
" data_path,\n",
|
|||
|
|
" regime_dict,\n",
|
|||
|
|
" returns_compute_settings\n",
|
|||
|
|
")"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "6057226b",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 2.2 Scenario Generation\n",
|
|||
|
|
"Assume the return distribution is stationary over the optimization period and use historical returns to approximate future ones.\n",
|
|||
|
|
"In particular, we use `cuml.KDE` on GPU or `sklearn.KDE` on CPU to fit return distribution and sample scenarios. Also support fitting a Multivariate Gaussian distribution and sampling from it. One can configure the scenario generation step by setting `scenario_generation_settings`.\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 5,
|
|||
|
|
"id": "954e3c7e",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"# Define the settings for scenario generation\n",
|
|||
|
|
"scenario_generation_settings = {'num_scen': 10000, # Number of return scenarios to simulate \n",
|
|||
|
|
" 'fit_type': 'kde', \n",
|
|||
|
|
" 'kde_settings': {'bandwidth': 0.01, \n",
|
|||
|
|
" 'kernel': 'gaussian', \n",
|
|||
|
|
" 'device': 'GPU'\n",
|
|||
|
|
" },\n",
|
|||
|
|
" 'verbose': False\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Generate return scenarios from KDE\n",
|
|||
|
|
"returns_dict = cvar_utils.generate_cvar_data(\n",
|
|||
|
|
" returns_dict,\n",
|
|||
|
|
" scenario_generation_settings\n",
|
|||
|
|
")"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "52b0afab",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 2.3 Define Optimization Parameters\n",
|
|||
|
|
"We define a `CvarParameters` object to encapsulate key constraints and settings for our portfolio optimization pipeline. This object configures the Mean-CVaR model with both required and optional parameters:\n",
|
|||
|
|
"\n",
|
|||
|
|
"Required parameters: Settings like `w_min`, `w_max`, `risk_aversion`, `confidence`, `num_scen`, and `fit_type` must be specified to establish the basic optimization framework.\n",
|
|||
|
|
"\n",
|
|||
|
|
"Optional constraints: Parameters such as `T_tar` (turnover constraint), `cvar_limit` (maximum CVaR threshold), and `cardinality` (portfolio size limit) are optional. Setting any of these to a non-`None` value will add the corresponding constraint to the Mean-CVaR model."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 6,
|
|||
|
|
"id": "69d91a63",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"# Define CVaR optimization parameters for the S&P 500 example\n",
|
|||
|
|
"cvar_params = CvarParameters(\n",
|
|||
|
|
" w_min={\"NVDA\":0.1, \"others\": -0.3}, w_max={\"NVDA\": 0.6, \"others\": 0.4}, # Asset weight allocation bounds\n",
|
|||
|
|
" c_min=0.0, c_max=0.2, # Cash holdings bounds\n",
|
|||
|
|
" L_tar=1.6, T_tar=None, # Leverage and turnover (None for this example)\n",
|
|||
|
|
" cvar_limit=None, # Max CVaR (None = unconstrained for this example)\n",
|
|||
|
|
" cardinality=None, # Cardinality constraints\n",
|
|||
|
|
" risk_aversion=1, # Risk aversion level\n",
|
|||
|
|
" confidence=0.95 # CVaR confidence level (alpha)\n",
|
|||
|
|
")"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "85f3cdbe",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 2.4 Build Mean-CVaR Problem\n",
|
|||
|
|
"We take the processed data `returns_dict` and the problem parameters `cvar_params` and formulates the problem `cvar_problem`. \n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 7,
|
|||
|
|
"id": "53e27d97",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"# Instantiate CVaR optimization problem for the S&P 500 example\n",
|
|||
|
|
"cvar_problem = cvar_optimizer.CVaR(\n",
|
|||
|
|
" returns_dict=returns_dict,\n",
|
|||
|
|
" cvar_params=cvar_params\n",
|
|||
|
|
")"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "ba37c6be",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"\n",
|
|||
|
|
"<a id='solve-cvar-optimization'></a>\n",
|
|||
|
|
"## 3. Solve CVaR Optimization\n",
|
|||
|
|
"\n",
|
|||
|
|
"### 3.1 cuOpt GPU LP Solver\n",
|
|||
|
|
"We then call the cuOpt LP solver and returns the optimized portfolio. One may also provide customized configurations to the cuOpt LP solver including solver mode, accuracy, etc. \n",
|
|||
|
|
"\n",
|
|||
|
|
"cuOpt LP solver supports four solve methods: choose one of the following by setting `solver_method`: \n",
|
|||
|
|
"1. PDLP algorithm has three solver modes: choose one of the following by setting `solver_mode`:\n",
|
|||
|
|
" - \"Stable2\": balance speed and accuracy\n",
|
|||
|
|
" - \"Methodical1\": prioritize accuracy\n",
|
|||
|
|
" - \"Fast1\": prioritize speed\n",
|
|||
|
|
"\n",
|
|||
|
|
"2. Dual Simplex\n",
|
|||
|
|
"3. Barrier Method\n",
|
|||
|
|
"4. Concurrent: runs all three algorithms and return the fastest.\n",
|
|||
|
|
"\n",
|
|||
|
|
"For details, see cuOpt documentation: https://docs.nvidia.com/cuopt/user-guide/latest/introduction.html.\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 8,
|
|||
|
|
"id": "898d3f8c-2649-4c4b-90ba-30e38ed4b7ed",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter time_limit to 1.500000e+01\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"Scenarios: 10,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002553 (0.2553%)\n",
|
|||
|
|
"CVaR (95%): 0.025875 (2.5875%)\n",
|
|||
|
|
"Objective Value: -0.001445\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.1277 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0652 seconds\n",
|
|||
|
|
"Solve Time: 2.0053 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.289 ( 28.94%)\n",
|
|||
|
|
"NVDA 0.172 ( 17.18%)\n",
|
|||
|
|
"MCK 0.167 ( 16.72%)\n",
|
|||
|
|
"JBL 0.101 ( 10.14%)\n",
|
|||
|
|
"COP 0.097 ( 9.68%)\n",
|
|||
|
|
"IRM 0.091 ( 9.11%)\n",
|
|||
|
|
"PWR 0.088 ( 8.84%)\n",
|
|||
|
|
"IT 0.063 ( 6.32%)\n",
|
|||
|
|
"NUE 0.052 ( 5.17%)\n",
|
|||
|
|
"FICO 0.042 ( 4.22%)\n",
|
|||
|
|
"STLD 0.037 ( 3.70%)\n",
|
|||
|
|
"Total Long 1.200 (120.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (2 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.279 (-27.90%)\n",
|
|||
|
|
"ILMN -0.121 (-12.09%)\n",
|
|||
|
|
"Total Short -0.400 (-39.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.000 ( -0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 80.02%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.02%)\n",
|
|||
|
|
"Gross Exposure 1.600 (160.00%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# GPU solver settings\n",
|
|||
|
|
"gpu_solver_settings = {\"solver\": cp.CUOPT, \n",
|
|||
|
|
" \"verbose\": False, \n",
|
|||
|
|
" \"solver_method\": \"PDLP\", \n",
|
|||
|
|
" \"time_limit\":15, \n",
|
|||
|
|
" \"optimality\": 1e-4\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solve on GPU\n",
|
|||
|
|
"gpu_results, gpu_portfolio = cvar_problem.solve_optimization_problem(solver_settings=gpu_solver_settings)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 9,
|
|||
|
|
"id": "2c151cb0-58f6-4cb7-8537-ab978cbf2cb1",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"regime recent\n",
|
|||
|
|
"solver CUOPT\n",
|
|||
|
|
"solve time 2.005276\n",
|
|||
|
|
"return 0.002553\n",
|
|||
|
|
"CVaR 0.025875\n",
|
|||
|
|
"obj -0.001445\n",
|
|||
|
|
"dtype: object"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"execution_count": 9,
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "execute_result"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"gpu_results"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "ce1483b8",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 3.2 Solve on CPU solver\n",
|
|||
|
|
"Using CVXPY as the modeling API, we can easily change to any CPU solver supported on CVXPY to solve the same problem. We can compare the performance and verify that CPU and GPU solver results are the same up to the tolerance level. Just change the solver in the solver settings dictionary."
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 10,
|
|||
|
|
"id": "c4c1fa1e-3e89-42ec-8abb-168f3d3059b5",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"Scenarios: 10,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002553 (0.2553%)\n",
|
|||
|
|
"CVaR (95%): 0.025924 (2.5924%)\n",
|
|||
|
|
"Objective Value: -0.001443\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.3141 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.1857 seconds\n",
|
|||
|
|
"Solve Time: 16.4686 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.289 ( 28.94%)\n",
|
|||
|
|
"NVDA 0.172 ( 17.17%)\n",
|
|||
|
|
"MCK 0.166 ( 16.58%)\n",
|
|||
|
|
"JBL 0.102 ( 10.20%)\n",
|
|||
|
|
"COP 0.097 ( 9.67%)\n",
|
|||
|
|
"IRM 0.091 ( 9.07%)\n",
|
|||
|
|
"PWR 0.088 ( 8.82%)\n",
|
|||
|
|
"IT 0.066 ( 6.58%)\n",
|
|||
|
|
"NUE 0.051 ( 5.06%)\n",
|
|||
|
|
"FICO 0.041 ( 4.14%)\n",
|
|||
|
|
"STLD 0.038 ( 3.77%)\n",
|
|||
|
|
"Total Long 1.200 (119.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (2 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.279 (-27.94%)\n",
|
|||
|
|
"ILMN -0.121 (-12.06%)\n",
|
|||
|
|
"Total Short -0.400 (-39.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 79.99%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.00%)\n",
|
|||
|
|
"Gross Exposure 1.600 (159.98%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"cvar_problem = cvar_optimizer.CVaR(\n",
|
|||
|
|
" returns_dict=returns_dict,\n",
|
|||
|
|
" cvar_params=cvar_params,\n",
|
|||
|
|
" api_settings={\"api\": \"cvxpy\"}\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# CPU solver settings\n",
|
|||
|
|
"cpu_solver_settings = {\"solver\":cp.CLARABEL, \"verbose\": False, \"tol_gap_abs\": 1e-4, \"tol_gap_rel\": 1e-4, \"tol_feas\": 1e-4}\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solve on CPU\n",
|
|||
|
|
"cpu_results, cpu_portfolio = cvar_problem.solve_optimization_problem(solver_settings=cpu_solver_settings)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 11,
|
|||
|
|
"id": "b8f73f3b-e7fa-4cfd-8b54-0cbbfaed8c9a",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"regime recent\n",
|
|||
|
|
"solver CLARABEL\n",
|
|||
|
|
"solve time 16.468553\n",
|
|||
|
|
"return 0.002553\n",
|
|||
|
|
"CVaR 0.025924\n",
|
|||
|
|
"obj -0.001443\n",
|
|||
|
|
"dtype: object"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"execution_count": 11,
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "execute_result"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"cpu_results"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 12,
|
|||
|
|
"id": "2e993daf-d209-44c3-ae15-e6ec3991a69b",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"SOLVER COMPARISON\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"Solver Solve Time (s) Objective Return CVaR \n",
|
|||
|
|
"-----------------------------------------------------------------\n",
|
|||
|
|
"cuOpt (GPU) 2.0053 -0.001445 0.002553 0.025875 \n",
|
|||
|
|
"CLARABEL (CPU) 16.4686 -0.001443 0.002553 0.025924 \n",
|
|||
|
|
"\n",
|
|||
|
|
"Objective Differences:\n",
|
|||
|
|
"cuOpt (GPU) vs CLARABEL (CPU): 0.00000194\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Compare results between GPU and CPU solvers\n",
|
|||
|
|
"utils.compare_results(gpu_results, cpu_results)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "bb878a29",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 3.3 Optional: Visualize Optimized Portfolio"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 13,
|
|||
|
|
"id": "c1cd3113-f64c-4955-9d39-9cd52ad0d84c",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"image/png": "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
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 3600x2400 with 1 Axes>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "display_data"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Plot portfolio\n",
|
|||
|
|
"ax = gpu_portfolio.plot_portfolio(show_plot = True, min_percentage = 1)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "9ded9844",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 3.4 Adding Cardinality Constraint: Mixed-Integer Linear Program \n",
|
|||
|
|
"\n",
|
|||
|
|
"A **cardinality constraint** limits the maximum number of assets held in the portfolio, promoting sparsity and reducing transaction costs. This constraint transforms the problem into a **Mixed-Integer Linear Program (MILP)** because it requires binary decision variables to track whether each asset is included.\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Mathematical Formulation:**\n",
|
|||
|
|
"\n",
|
|||
|
|
"We introduce binary variables $y_i \\in \\{0,1\\}$ for each asset $i$, where:\n",
|
|||
|
|
"- $y_i = 1$ if asset $i$ is held in the portfolio (i.e., $w_i \\neq 0$)\n",
|
|||
|
|
"- $y_i = 0$ otherwise\n",
|
|||
|
|
"\n",
|
|||
|
|
"The cardinality constraint is then:\n",
|
|||
|
|
"$$\\sum_{i=1}^{N} y_i \\leq K$$\n",
|
|||
|
|
"where $K$ is the maximum number of assets allowed. To link the binary variables with the continuous weights, we add:\n",
|
|||
|
|
"$$w_i^{\\min} \\cdot y_i \\leq w_i \\leq w_i^{\\max} \\cdot y_i, \\quad \\forall i$$\n",
|
|||
|
|
"\n",
|
|||
|
|
"This ensures that $w_i = 0$ when $y_i = 0$, and $w_i$ can take non-zero values only when $y_i = 1$. The presence of integer decision variables $y_i$ makes this a MILP.\n",
|
|||
|
|
"\n",
|
|||
|
|
"The complete problem can be written as follows:\n",
|
|||
|
|
"\n",
|
|||
|
|
"\\begin{align*}\n",
|
|||
|
|
"\\text{maximize } \\quad & \\mu^\\top {w} - \\lambda_{risk}\\left(t + \\frac{1}{1-\\alpha}p^\\top {u}\\right),\\\\\n",
|
|||
|
|
"\\text{subject to } \\quad & {1}^\\top {w} = 1,\\\\\n",
|
|||
|
|
"&{u} \\geq -R^\\top {w} - t,\\\\\n",
|
|||
|
|
"& {w}^{\\min} \\circ {y} \\leq {w} \\leq {w}^{\\max} \\circ {y}, c^{\\min} \\leq c \\leq c^{\\max},\\\\\n",
|
|||
|
|
"& L= \\Vert {w} \\Vert_1 \\leq L^{tar},\\\\\n",
|
|||
|
|
"& T = \\Vert {w} - {w}_{b}\\Vert_1 \\leq T^{tar},\\\\\n",
|
|||
|
|
"& \\sum{{y}_i} \\leq K,\\\\\n",
|
|||
|
|
"&{y}_i \\in \\{0,1\\}^N.\n",
|
|||
|
|
"\\end{align*}\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Model Set-Up:** \n",
|
|||
|
|
"\n",
|
|||
|
|
"To set up a MILP problem, we just need to set the `cardinality` to an integer number (max number of assets allowed in the portfolio) when instantiating the `CvarParameters` dataclass. cuOpt offers MILP solvers with a GPU-accelerated heuristics algorithm and a CPU branch-and-cut algorithm. Since MILPs are much challenging to solve in general, we should expect a longer solve time. After solving, one can verify that the number of assets in the portfolio is indeed less than or equal to the cardinality constraint. \n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 14,
|
|||
|
|
"id": "f6fc040a",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"==================================================\n",
|
|||
|
|
"MIXED-INTEGER LINEAR PROGRAMMING (MILP) SETUP\n",
|
|||
|
|
"==================================================\n",
|
|||
|
|
"Cardinality Constraint: K ≤ 10 assets\n",
|
|||
|
|
"==================================================\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter mip_absolute_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter time_limit to 2.000000e+02\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"Scenarios: 10,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"Cardinality Limit: 10 assets\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002576 (0.2576%)\n",
|
|||
|
|
"CVaR (95%): 0.026755 (2.6755%)\n",
|
|||
|
|
"Objective Value: -0.001431\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.1288 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.1748 seconds\n",
|
|||
|
|
"Solve Time: 45.3261 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (8 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.295 ( 29.54%)\n",
|
|||
|
|
"MCK 0.195 ( 19.54%)\n",
|
|||
|
|
"NVDA 0.190 ( 18.99%)\n",
|
|||
|
|
"PWR 0.121 ( 12.11%)\n",
|
|||
|
|
"COP 0.115 ( 11.53%)\n",
|
|||
|
|
"JBL 0.114 ( 11.38%)\n",
|
|||
|
|
"IRM 0.091 ( 9.06%)\n",
|
|||
|
|
"NUE 0.078 ( 7.85%)\n",
|
|||
|
|
"Total Long 1.200 (120.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (2 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.273 (-27.28%)\n",
|
|||
|
|
"ILMN -0.127 (-12.72%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 80.00%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.00%)\n",
|
|||
|
|
"Gross Exposure 1.600 (160.00%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"name": "stderr",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"/home/rapids/notebooks/setup/.venv/lib/python3.13/site-packages/cvxpy/problems/problem.py:1539: UserWarning: Solution may be inaccurate. Try another solver, adjusting the solver settings, or solve with verbose=True for more information.\n",
|
|||
|
|
" warnings.warn(\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Define CVaR optimization parameters for the S&P 500 example\n",
|
|||
|
|
"milp_cvar_params = CvarParameters(\n",
|
|||
|
|
" w_min={\"NVDA\":0.1, \"others\": -0.3}, w_max={\"NVDA\": 0.6, \"others\": 0.4}, # Asset weight allocation bounds\n",
|
|||
|
|
" c_min=0.0, c_max=0.2, # Cash holdings bounds\n",
|
|||
|
|
" L_tar=1.6, T_tar=None, # Leverage and turnover (None for this example)\n",
|
|||
|
|
" cvar_limit=None, # Max CVaR (None = unconstrained for this example)\n",
|
|||
|
|
" cardinality=10, # Cardinality constraints\n",
|
|||
|
|
" risk_aversion=1, # Risk aversion level\n",
|
|||
|
|
" confidence=0.95, # CVaR confidence level (alpha)\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Instantiate the MILP problem\n",
|
|||
|
|
"milp_cvar_problem = cvar_optimizer.CVaR(\n",
|
|||
|
|
" returns_dict=returns_dict,\n",
|
|||
|
|
" cvar_params=milp_cvar_params\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# cuOpt MILP solver settings\n",
|
|||
|
|
"gpu_solver_settings = {\"solver\": cp.CUOPT, \n",
|
|||
|
|
" \"verbose\": False, \n",
|
|||
|
|
" \"time_limit\":200, \n",
|
|||
|
|
" \"mip_absolute_tolerance\": 1e-4\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solve the MILP problem\n",
|
|||
|
|
"milp_results, milp_portfolio = milp_cvar_problem.solve_optimization_problem(solver_settings=gpu_solver_settings)"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "0dc4cf60",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"## 4. Backtest Portfolio\n",
|
|||
|
|
"<a id='backtest-portfolio'></a>\n",
|
|||
|
|
"\n",
|
|||
|
|
"The `portfolio_backtester` evaluates portfolio performance against historical data and benchmarks. It supports multiple testing methods and calculates comprehensive performance metrics:\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Testing Methods:**\n",
|
|||
|
|
"- **Historical**: Uses actual historical return data\n",
|
|||
|
|
"- **KDE Simulation**: Generates scenarios using Kernel Density Estimation\n",
|
|||
|
|
"- **Gaussian Simulation**: Generates scenarios from multivariate normal distribution\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Performance Metrics:**\n",
|
|||
|
|
"- **Sharpe Ratio**: Risk-adjusted return relative to volatility (annualized)\n",
|
|||
|
|
"- **Sortino Ratio**: Return relative to downside deviation (annualized)\n",
|
|||
|
|
"- **Maximum Drawdown**: Largest peak-to-trough decline\n",
|
|||
|
|
"\n",
|
|||
|
|
"**Benchmarking:** By default, compares against an equal-weight portfolio. Custom benchmarks can also be provided.\n",
|
|||
|
|
"\n",
|
|||
|
|
"The backtester visualizes cumulative returns over time and allows comparison between the optimized portfolio and benchmark strategies.\n",
|
|||
|
|
"\n",
|
|||
|
|
"The `cut_off_date` marks the boundary between training data used for optimization and test data used for out-of-sample evaluation. One can test whether the optimized portfolio is robust to potential regime shifts. "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 15,
|
|||
|
|
"id": "280ab80d-d3d2-4ab2-9564-29034333564c",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [],
|
|||
|
|
"source": [
|
|||
|
|
"# Define test regime and calculate test returns\n",
|
|||
|
|
"test_regime_dict = {\"name\": \"test_recent\", \"range\": (\"2023-09-01\", \"2024-07-01\")}\n",
|
|||
|
|
"test_returns_dict = utils.calculate_returns(data_path, test_regime_dict, returns_compute_settings)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Backtest settings\n",
|
|||
|
|
"test_method = \"historical\"\n",
|
|||
|
|
"risk_free = 0.0"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 16,
|
|||
|
|
"id": "24e079b7-f0f2-4040-8a13-5b310b9277a5",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"text/html": [
|
|||
|
|
"<div>\n",
|
|||
|
|
"<style scoped>\n",
|
|||
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|||
|
|
" vertical-align: middle;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .dataframe tbody tr th {\n",
|
|||
|
|
" vertical-align: top;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .dataframe thead th {\n",
|
|||
|
|
" text-align: right;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"</style>\n",
|
|||
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|||
|
|
" <thead>\n",
|
|||
|
|
" <tr style=\"text-align: right;\">\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th>returns</th>\n",
|
|||
|
|
" <th>cumulative returns</th>\n",
|
|||
|
|
" <th>mean portfolio return</th>\n",
|
|||
|
|
" <th>sharpe</th>\n",
|
|||
|
|
" <th>sortino</th>\n",
|
|||
|
|
" <th>max drawdown</th>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>portfolio name</th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </thead>\n",
|
|||
|
|
" <tbody>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>CUOPT_optimal</th>\n",
|
|||
|
|
" <td>[0.002920315102210369, 0.0013245199061181615, ...</td>\n",
|
|||
|
|
" <td>[1.0029245833762488, 1.004253857081673, 1.0131...</td>\n",
|
|||
|
|
" <td>0.00302</td>\n",
|
|||
|
|
" <td>3.514806</td>\n",
|
|||
|
|
" <td>6.410716</td>\n",
|
|||
|
|
" <td>0.072152</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>AMZN-JPM</th>\n",
|
|||
|
|
" <td>[-0.006441757889020252, -0.010386305987946275,...</td>\n",
|
|||
|
|
" <td>[0.9935789457535249, 0.9833127370811252, 0.994...</td>\n",
|
|||
|
|
" <td>0.001548</td>\n",
|
|||
|
|
" <td>1.966758</td>\n",
|
|||
|
|
" <td>3.128698</td>\n",
|
|||
|
|
" <td>0.136417</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>AAPL-MSFT</th>\n",
|
|||
|
|
" <td>[0.009376198001004993, -0.011796913326585681, ...</td>\n",
|
|||
|
|
" <td>[1.0094202922498714, 0.9975822122430166, 0.983...</td>\n",
|
|||
|
|
" <td>0.001181</td>\n",
|
|||
|
|
" <td>1.867662</td>\n",
|
|||
|
|
" <td>2.827687</td>\n",
|
|||
|
|
" <td>0.073053</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>NKE-MCD</th>\n",
|
|||
|
|
" <td>[-0.009164162734788928, -0.00906895491356785, ...</td>\n",
|
|||
|
|
" <td>[0.9908777002272608, 0.981932099973256, 0.9830...</td>\n",
|
|||
|
|
" <td>-0.000643</td>\n",
|
|||
|
|
" <td>-1.054596</td>\n",
|
|||
|
|
" <td>-1.269279</td>\n",
|
|||
|
|
" <td>0.192486</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </tbody>\n",
|
|||
|
|
"</table>\n",
|
|||
|
|
"</div>"
|
|||
|
|
],
|
|||
|
|
"text/plain": [
|
|||
|
|
" returns \\\n",
|
|||
|
|
"portfolio name \n",
|
|||
|
|
"CUOPT_optimal [0.002920315102210369, 0.0013245199061181615, ... \n",
|
|||
|
|
"AMZN-JPM [-0.006441757889020252, -0.010386305987946275,... \n",
|
|||
|
|
"AAPL-MSFT [0.009376198001004993, -0.011796913326585681, ... \n",
|
|||
|
|
"NKE-MCD [-0.009164162734788928, -0.00906895491356785, ... \n",
|
|||
|
|
"\n",
|
|||
|
|
" cumulative returns \\\n",
|
|||
|
|
"portfolio name \n",
|
|||
|
|
"CUOPT_optimal [1.0029245833762488, 1.004253857081673, 1.0131... \n",
|
|||
|
|
"AMZN-JPM [0.9935789457535249, 0.9833127370811252, 0.994... \n",
|
|||
|
|
"AAPL-MSFT [1.0094202922498714, 0.9975822122430166, 0.983... \n",
|
|||
|
|
"NKE-MCD [0.9908777002272608, 0.981932099973256, 0.9830... \n",
|
|||
|
|
"\n",
|
|||
|
|
" mean portfolio return sharpe sortino max drawdown \n",
|
|||
|
|
"portfolio name \n",
|
|||
|
|
"CUOPT_optimal 0.00302 3.514806 6.410716 0.072152 \n",
|
|||
|
|
"AMZN-JPM 0.001548 1.966758 3.128698 0.136417 \n",
|
|||
|
|
"AAPL-MSFT 0.001181 1.867662 2.827687 0.073053 \n",
|
|||
|
|
"NKE-MCD -0.000643 -1.054596 -1.269279 0.192486 "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"execution_count": 16,
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "execute_result"
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAADf4AAAlOCAYAAABeUKPwAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjcsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvTLEjVAAAAAlwSFlzAAAuIwAALiMBeKU/dgABAABJREFUeJzs3XlgFPX9//HX7JX75CZcIpdQQBRBLYgCKqgQSmtt609r26/WHnjUWrUHba21WqvVqlVba0VqbdXKpQgKeAAqCCKgCChyhHAl5D42e83vj5jJbo7NJtlkl/B8lKTzmfnMZ96zG9Zo8tq34fF4TAEAAAAAAAAAAAAAAAAAAAAAAAAAgLhgi3UBAAAAAAAAAAAAAAAAAAAAAAAAAACgHsE/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiCME/AAAAAAAAAAAAAAAAAAAAAAAAAADiiCPWBQDRFAgE5PF4QvbZ7XYZhhGjigAAAAAAAAAAAAAAAAAAAAAAAACcSEzTlN/vD9nncrlks3VeHz6Cf+hSPB6Pdu/eHesyAAAAAAAAAAAAAAAAAAAAAAAAAHQhw4YNU2JiYqddr/MihgAAAAAAAAAAAAAAAAAAAAAAAAAAoEUE/wAAAAAAAAAAAAAAAAAAAAAAAAAAiCME/wAAAAAAAAAAAAAAAAAAAAAAAAAAiCOOWBcARJPdbm+0b9iwYXI4+FI/UQQCAXk8Hmvscrlks5FRBnDi4HUMwMmE1zwAJzpexwCcDPx+v44fPy7TNBUIBKz9NptN3bt3b/K/qQLAiYzv8QDEK16fAJxMeM0DcKLjdQzAyYTXPAAnOl7H0JF8Pp92794dsq+zf8ZOGgpdimEYjfY5HA6CfyeQQCAQ8gtIDoeDf/ACOKHwOgbgZMJrHoATHa9jAE4GhmHIZrPJNM2Q/TabTQ6Hg+AfgC6H7/EAxCtenwCcTHjNA3Ci43UMwMmE1zwAJzpex9DZmsotdSS+mgEAAAAAAAAAAAAAAAAAAAAAAAAAiCO0QQMAAAAAAAAAoIuy2Wzq0aOHAoGAPB6Ptd/lcvFOlwAAAAAAAAAAAAAAxDGCfwAAAAAAAAAAdFGGYchut1v/X6duHwAAAAAAAAAAAAAAiE+8nS8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHGE4B8AAAAAAAAAAAAAAAAAAAAAAAAAAHHEEesCgBOJaZry+Xzy+/2xLqXLCgQC8nq9IWObjYwygLaz2WxyOBy8lgAAAAAAAAAAAAAAAAAAAAAAThgE/4AIVFdXq7i4WMXFxYT+AOAEZBiGUlNTlZmZqfT0dNnt9liXBAAAAABAp/D7/SoqKpJpmiH/bdNut6tbt278OzIAAAAAAAAAAAAAAHGK4B/QgiNHjujYsWOxLgMA0A6maaq8vFzl5eWy2+065ZRTlJycHOuyAAAAAADoFH6/X6ZpKhAIxLoUAAAAAAAAAAAAAAAQIVusCwDiWVFREaE/AOhi/H6/Pv/8c1VVVcW6FAAAAAAAAAAAAAAAAAAAAAAAmkTHP6AZbrdb+fn51tgwDGVlZSk7O1tOp1OGYcSwOgBAJEzTlN/vV0VFhYqKiuR2uyVJgUBAe/fu1YgRI2S322NcJQAAAAAAAAAAAAAAAAAAAAAAoQj+Ac0oKyuTaZrW+JRTTlFWVlYMKwIAtFVaWpp69+6tvLw8FRQUSKrt/FdWVsZrOwAAAAAAAAAAAAAAAAAAAAAg7thiXQAQr8rLy63t9PR0giEAcIIzDEP9+/dXYmKita+kpCR2BQEAAAAAAAAAAAAAAAAAAAAA0AyCf0ATAoGAKisrrXFGRkYMqwEARIthGMrOzrbGFRUVCgQCMawIAAAAAAAAAAAAAAAAAAAAAIDGCP4BTfD5fCHj5OTkGFUCAIi21NRUa9s0Tfn9/hhWAwAAAAAAAAAAAAAAAAAAAABAY45YFwDEo4bdn+x2e4wqAQBEW8PX9NWrV8vhcKhPnz7q37+/0tPTY1QZAAAAAAAAAAAAAAAAAAAAAAC1CP4BAICTimEYIeOSkhL5/X4dP35cH330kbp166Yvf/nLSkpKilGFAAAAAAAAAAAAAAAAAAAAAICTHcE/AABwUsvLy1N5eblSUlKUkZEhSXrjjTd0wQUXEP4DAAAAAAAAAAAAAAAAAAAAAMSELdYFAAAAxFK3bt2UlpamyspK5efn6/DhwyovL9dbb70l0zRjXR4AAAAAAAAAAAAAAAAAAAAA4CRExz8AAHBSy8rKUkpKinw+n/Ly8nT8+HG5XC5JUkFBgXr27BnjCgEAAAAAAAAAAAAAAAAAAAAAJxs6/gEAAEhyOBwaMGCA7Ha7iouLJUkHDx6McVUAAAAAAAAAAAAAAAAAAAAAgJMRwT8AAIAv2O12paeny+12q6amRvn5+bEuCQAAAAAAAAAAAAAAAAAAAABwEiL4BwDACWbq1KkaPny4hg8fflJ1pLv99tut+37ppZc67DopKSmSpJqaGlVXV8s0zQ67FgAAAAAAAAAAAAAAAAAAAAAATXHEugAA6AwVFRV6++23tX79en300UcqKipScXGxnE6nMjIyNGjQII0ePVpTp07VuHHjmlxj6tSpVvevP/zhD5o7d27E13/44Yf1yCOPSJImTJighQsXRnzuxo0b9eabb+r999/XsWPHVFRUpMTERHXr1k2DBw/WlClTNG3aNHXv3j3iNYPvpSHDMJSSkqLs7GyNHDlS5513ni699FIlJiZacw4ePKhp06ZFfL1I/PjHP9a8efOiuibQFjZb7fsiBAIBmaYpv98vh4NvmQAAAAAAAAAAAAAAAAAAAAAAnYffYgfQpVVXV2vBggV66qmnVFpa2ui41+tVVVWVDh8+rHfffVd/+9vfNGjQIM2bN0+XXnqpDMOIQdW1Nm/erHvvvVdbt25tdMzj8aisrEx79+7V6tWrdffdd+s73/mOrr32WqtbWVuZpqmKigpVVFTowIEDWrFihf785z/r7rvv1nnnndeutdFYcAhz9erV6tevX4wrQt3f+7pOf3T8AwAAAAAAAAAAAAAAAAAAAAB0NoJ/ALqsQ4cO6frrr9euXbtC9vft21fDhw9XVlaWAoGACgsLtXPnThUWFkqS9u3bp1tuuUWHDx/WtddeG4vS9cwzz+gPf/iDAoGAtS8rK0tjx45V9+7dVV1drby
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 3600x2400 with 1 Axes>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "display_data"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"from cufolio import backtest\n",
|
|||
|
|
"\n",
|
|||
|
|
"# (Optional) Compare results between optimized portfolio and user-defined portfolios\n",
|
|||
|
|
"portfolios_dict = {'AMZN-JPM':({'AMZN': 0.72, 'JPM': 0.18}, 0.1),\\\n",
|
|||
|
|
" 'AAPL-MSFT': ({'AAPL': 0.29, 'MSFT': 0.61}, 0.1),\\\n",
|
|||
|
|
" 'NKE-MCD': ({'MCD': 0.65, 'NKE': 0.25}, 0.1)}\n",
|
|||
|
|
"\n",
|
|||
|
|
"benchmark_portfolios = cvar_utils.generate_user_input_portfolios(portfolios_dict, test_returns_dict)\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Uncomment the following lineto use equal-weight benchmark portfolio\n",
|
|||
|
|
"# benchmark_portfolios = None \n",
|
|||
|
|
"\n",
|
|||
|
|
"# Set cut-off date for backtest visualization\n",
|
|||
|
|
"cut_off_date = regime_dict[\"range\"][1]\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Create backtester and run backtest\n",
|
|||
|
|
"backtester = backtest.portfolio_backtester(gpu_portfolio, test_returns_dict, risk_free, test_method, benchmark_portfolios = benchmark_portfolios)\n",
|
|||
|
|
"\n",
|
|||
|
|
"backtest_result,_ = backtester.backtest_against_benchmarks(plot_returns=True, cut_off_date=cut_off_date)\n",
|
|||
|
|
"\n",
|
|||
|
|
"backtest_result"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 17,
|
|||
|
|
"id": "d71d7cff-7f48-4d7b-a898-4f298445f4de",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"Combined plot saved: ../results/backtest/combined_cuopt_optimal_historical_analysis.png\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"image/png": "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
|
|||
|
|
"text/plain": [
|
|||
|
|
"<Figure size 4800x2400 with 2 Axes>"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "display_data"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Plot portfolio and backtest results side by side\n",
|
|||
|
|
"utils.portfolio_plot_with_backtest(portfolio=gpu_portfolio, \\\n",
|
|||
|
|
" backtester=backtester, \\\n",
|
|||
|
|
" cut_off_date=cut_off_date, \\\n",
|
|||
|
|
" backtest_plot_title=\"Backtest Results\", \\\n",
|
|||
|
|
" save_plot = True, \\\n",
|
|||
|
|
" results_dir = \"../results/backtest\")"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "04b193df",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"## 5. GPU vs. CPU: Comparison over Different Regimes\n",
|
|||
|
|
"<a id='gpu-vs-cpu-comparison-over-different-regimes'></a>\n",
|
|||
|
|
"\n",
|
|||
|
|
"To further compare the performance of cuOpt GPU solver vs. CPU solvers, we can compare CPU vs. GPU performance over solving the same problems over different market regimes. The function `cvar_utils.optimize_market_regimes` generates Mean-CVaR optimization problems iteratively over different regimes from `regime_comparison_selected_dict`, solve each problem using all the solvers specified in `solver_settings_list`, and returns a dataframe of results. "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 18,
|
|||
|
|
"id": "bbd039c9-347e-4576-b1c4-568a66c8be57",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: pre_crisis\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: pre_crisis\n",
|
|||
|
|
"Time Period: 2005-01-01 to 2007-10-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003253 (0.3253%)\n",
|
|||
|
|
"CVaR (95%): 0.027550 (2.7550%)\n",
|
|||
|
|
"Objective Value: -0.001916\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2676 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3611 seconds\n",
|
|||
|
|
"Solve Time: 40.9632 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2005-01-01 to 2007-10-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (14 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"DLR 0.227 ( 22.74%)\n",
|
|||
|
|
"AAPL 0.169 ( 16.85%)\n",
|
|||
|
|
"MNST 0.165 ( 16.55%)\n",
|
|||
|
|
"ILMN 0.110 ( 10.99%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"ISRG 0.094 ( 9.36%)\n",
|
|||
|
|
"HOLX 0.074 ( 7.44%)\n",
|
|||
|
|
"LKQ 0.063 ( 6.34%)\n",
|
|||
|
|
"SBAC 0.060 ( 5.95%)\n",
|
|||
|
|
"NDAQ 0.048 ( 4.78%)\n",
|
|||
|
|
"VRTX 0.034 ( 3.43%)\n",
|
|||
|
|
"SLB 0.025 ( 2.46%)\n",
|
|||
|
|
"MOS 0.015 ( 1.55%)\n",
|
|||
|
|
"BKNG 0.013 ( 1.28%)\n",
|
|||
|
|
"Total Long 1.197 (119.72%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (7 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"JCI -0.106 (-10.59%)\n",
|
|||
|
|
"LEN -0.079 ( -7.93%)\n",
|
|||
|
|
"DHI -0.071 ( -7.10%)\n",
|
|||
|
|
"AXON -0.063 ( -6.29%)\n",
|
|||
|
|
"AMD -0.033 ( -3.31%)\n",
|
|||
|
|
"PHM -0.027 ( -2.67%)\n",
|
|||
|
|
"BSX -0.021 ( -2.11%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.797 ( 79.72%)\n",
|
|||
|
|
"Total Portfolio 0.997 ( 99.73%)\n",
|
|||
|
|
"Gross Exposure 1.597 (159.72%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.001916, Time: 40.9632s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: pre_crisis\n",
|
|||
|
|
"Time Period: 2005-01-01 to 2007-10-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003253 (0.3253%)\n",
|
|||
|
|
"CVaR (95%): 0.027507 (2.7507%)\n",
|
|||
|
|
"Objective Value: -0.001917\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2856 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0936 seconds\n",
|
|||
|
|
"Solve Time: 3.2496 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2005-01-01 to 2007-10-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (14 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"DLR 0.228 ( 22.82%)\n",
|
|||
|
|
"AAPL 0.169 ( 16.86%)\n",
|
|||
|
|
"MNST 0.166 ( 16.60%)\n",
|
|||
|
|
"ILMN 0.109 ( 10.88%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"ISRG 0.093 ( 9.28%)\n",
|
|||
|
|
"HOLX 0.075 ( 7.49%)\n",
|
|||
|
|
"LKQ 0.063 ( 6.33%)\n",
|
|||
|
|
"SBAC 0.060 ( 5.98%)\n",
|
|||
|
|
"NDAQ 0.047 ( 4.72%)\n",
|
|||
|
|
"VRTX 0.035 ( 3.46%)\n",
|
|||
|
|
"SLB 0.026 ( 2.62%)\n",
|
|||
|
|
"MOS 0.016 ( 1.57%)\n",
|
|||
|
|
"BKNG 0.011 ( 1.15%)\n",
|
|||
|
|
"Total Long 1.197 (119.74%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (7 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"JCI -0.105 (-10.53%)\n",
|
|||
|
|
"LEN -0.079 ( -7.86%)\n",
|
|||
|
|
"DHI -0.072 ( -7.18%)\n",
|
|||
|
|
"AXON -0.063 ( -6.32%)\n",
|
|||
|
|
"AMD -0.033 ( -3.33%)\n",
|
|||
|
|
"PHM -0.026 ( -2.63%)\n",
|
|||
|
|
"BSX -0.022 ( -2.15%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.000 ( -0.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.797 ( 79.75%)\n",
|
|||
|
|
"Total Portfolio 0.997 ( 99.74%)\n",
|
|||
|
|
"Gross Exposure 1.597 (159.74%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.001917, Time: 3.2496s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: crisis\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: crisis\n",
|
|||
|
|
"Time Period: 2007-10-01 to 2009-04-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.005043 (0.5043%)\n",
|
|||
|
|
"CVaR (95%): 0.061742 (6.1742%)\n",
|
|||
|
|
"Objective Value: -0.003765\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4999 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3712 seconds\n",
|
|||
|
|
"Solve Time: 48.6149 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2007-10-01 to 2009-04-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (6 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"NFLX 0.400 ( 40.00%)\n",
|
|||
|
|
"AZO 0.400 ( 40.00%)\n",
|
|||
|
|
"ILMN 0.164 ( 16.42%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"ROST 0.079 ( 7.85%)\n",
|
|||
|
|
"EW 0.057 ( 5.73%)\n",
|
|||
|
|
"Total Long 1.200 (119.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MGM -0.219 (-21.88%)\n",
|
|||
|
|
"AIG -0.168 (-16.81%)\n",
|
|||
|
|
"LVS -0.013 ( -1.30%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 79.99%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.00%)\n",
|
|||
|
|
"Gross Exposure 1.600 (159.99%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.003765, Time: 48.6149s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: crisis\n",
|
|||
|
|
"Time Period: 2007-10-01 to 2009-04-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.005039 (0.5039%)\n",
|
|||
|
|
"CVaR (95%): 0.061607 (6.1607%)\n",
|
|||
|
|
"Objective Value: -0.003764\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4636 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0920 seconds\n",
|
|||
|
|
"Solve Time: 8.7385 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2007-10-01 to 2009-04-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (6 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"AZO 0.400 ( 40.00%)\n",
|
|||
|
|
"NFLX 0.400 ( 40.00%)\n",
|
|||
|
|
"ILMN 0.164 ( 16.41%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"ROST 0.078 ( 7.76%)\n",
|
|||
|
|
"EW 0.058 ( 5.83%)\n",
|
|||
|
|
"Total Long 1.200 (120.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MGM -0.218 (-21.84%)\n",
|
|||
|
|
"AIG -0.168 (-16.82%)\n",
|
|||
|
|
"LVS -0.013 ( -1.30%)\n",
|
|||
|
|
"Total Short -0.400 (-39.96%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.000 ( -0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 80.04%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.03%)\n",
|
|||
|
|
"Gross Exposure 1.600 (159.96%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.003764, Time: 8.7385s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: post_crisis\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: post_crisis\n",
|
|||
|
|
"Time Period: 2009-06-30 to 2014-06-30\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.001885 (0.1885%)\n",
|
|||
|
|
"CVaR (95%): 0.024646 (2.4646%)\n",
|
|||
|
|
"Objective Value: -0.000929\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4658 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3662 seconds\n",
|
|||
|
|
"Solve Time: 38.8701 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2009-06-30 to 2014-06-30\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (16 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"STZ 0.139 ( 13.89%)\n",
|
|||
|
|
"BKNG 0.138 ( 13.82%)\n",
|
|||
|
|
"INCY 0.106 ( 10.63%)\n",
|
|||
|
|
"REGN 0.106 ( 10.55%)\n",
|
|||
|
|
"BBWI 0.101 ( 10.06%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"DPZ 0.096 ( 9.61%)\n",
|
|||
|
|
"OKE 0.084 ( 8.38%)\n",
|
|||
|
|
"EXR 0.070 ( 7.01%)\n",
|
|||
|
|
"COO 0.064 ( 6.44%)\n",
|
|||
|
|
"BIIB 0.051 ( 5.06%)\n",
|
|||
|
|
"TYL 0.043 ( 4.32%)\n",
|
|||
|
|
"MKTX 0.033 ( 3.29%)\n",
|
|||
|
|
"MCK 0.024 ( 2.38%)\n",
|
|||
|
|
"AAPL 0.024 ( 2.36%)\n",
|
|||
|
|
"NFLX 0.022 ( 2.18%)\n",
|
|||
|
|
"Total Long 1.200 (119.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (6 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"BAC -0.121 (-12.05%)\n",
|
|||
|
|
"AMD -0.080 ( -7.98%)\n",
|
|||
|
|
"MS -0.079 ( -7.93%)\n",
|
|||
|
|
"J -0.073 ( -7.26%)\n",
|
|||
|
|
"HPQ -0.022 ( -2.15%)\n",
|
|||
|
|
"TPR -0.019 ( -1.91%)\n",
|
|||
|
|
"Total Short -0.393 (-39.27%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.001 ( -0.09%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.807 ( 80.71%)\n",
|
|||
|
|
"Total Portfolio 1.006 (100.63%)\n",
|
|||
|
|
"Gross Exposure 1.593 (159.26%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.000929, Time: 38.8701s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: post_crisis\n",
|
|||
|
|
"Time Period: 2009-06-30 to 2014-06-30\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.001886 (0.1886%)\n",
|
|||
|
|
"CVaR (95%): 0.024644 (2.4644%)\n",
|
|||
|
|
"Objective Value: -0.000930\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2807 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0928 seconds\n",
|
|||
|
|
"Solve Time: 3.4689 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2009-06-30 to 2014-06-30\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (16 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"STZ 0.140 ( 14.04%)\n",
|
|||
|
|
"BKNG 0.138 ( 13.78%)\n",
|
|||
|
|
"INCY 0.106 ( 10.65%)\n",
|
|||
|
|
"REGN 0.106 ( 10.58%)\n",
|
|||
|
|
"BBWI 0.102 ( 10.16%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"DPZ 0.097 ( 9.70%)\n",
|
|||
|
|
"OKE 0.084 ( 8.38%)\n",
|
|||
|
|
"EXR 0.068 ( 6.84%)\n",
|
|||
|
|
"COO 0.064 ( 6.35%)\n",
|
|||
|
|
"BIIB 0.051 ( 5.11%)\n",
|
|||
|
|
"TYL 0.042 ( 4.23%)\n",
|
|||
|
|
"MKTX 0.033 ( 3.28%)\n",
|
|||
|
|
"MCK 0.025 ( 2.47%)\n",
|
|||
|
|
"AAPL 0.022 ( 2.23%)\n",
|
|||
|
|
"NFLX 0.022 ( 2.20%)\n",
|
|||
|
|
"Total Long 1.200 (120.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (6 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"BAC -0.122 (-12.18%)\n",
|
|||
|
|
"AMD -0.079 ( -7.93%)\n",
|
|||
|
|
"MS -0.079 ( -7.90%)\n",
|
|||
|
|
"J -0.073 ( -7.32%)\n",
|
|||
|
|
"HPQ -0.021 ( -2.12%)\n",
|
|||
|
|
"TPR -0.019 ( -1.87%)\n",
|
|||
|
|
"Total Short -0.393 (-39.31%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.001 ( -0.06%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.807 ( 80.69%)\n",
|
|||
|
|
"Total Portfolio 1.006 (100.63%)\n",
|
|||
|
|
"Gross Exposure 1.593 (159.31%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.000930, Time: 3.4689s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: oil_price_crash\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: oil_price_crash\n",
|
|||
|
|
"Time Period: 2014-06-01 to 2016-03-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003050 (0.3050%)\n",
|
|||
|
|
"CVaR (95%): 0.026816 (2.6816%)\n",
|
|||
|
|
"Objective Value: -0.001877\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4931 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3742 seconds\n",
|
|||
|
|
"Solve Time: 40.8305 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2014-06-01 to 2016-03-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (12 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"EW 0.282 ( 28.19%)\n",
|
|||
|
|
"MKTX 0.243 ( 24.30%)\n",
|
|||
|
|
"HRL 0.135 ( 13.45%)\n",
|
|||
|
|
"TTWO 0.126 ( 12.64%)\n",
|
|||
|
|
"DPZ 0.121 ( 12.11%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"GPN 0.076 ( 7.59%)\n",
|
|||
|
|
"AMZN 0.052 ( 5.20%)\n",
|
|||
|
|
"EA 0.021 ( 2.08%)\n",
|
|||
|
|
"NDAQ 0.018 ( 1.76%)\n",
|
|||
|
|
"MNST 0.011 ( 1.13%)\n",
|
|||
|
|
"VMC 0.011 ( 1.07%)\n",
|
|||
|
|
"Total Long 1.195 (119.51%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (4 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"DVN -0.228 (-22.82%)\n",
|
|||
|
|
"FCX -0.101 (-10.06%)\n",
|
|||
|
|
"MU -0.053 ( -5.31%)\n",
|
|||
|
|
"WMB -0.018 ( -1.81%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.795 ( 79.51%)\n",
|
|||
|
|
"Total Portfolio 0.995 ( 99.52%)\n",
|
|||
|
|
"Gross Exposure 1.595 (159.51%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.001877, Time: 40.8305s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: oil_price_crash\n",
|
|||
|
|
"Time Period: 2014-06-01 to 2016-03-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003051 (0.3051%)\n",
|
|||
|
|
"CVaR (95%): 0.026809 (2.6809%)\n",
|
|||
|
|
"Objective Value: -0.001878\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4925 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0876 seconds\n",
|
|||
|
|
"Solve Time: 5.6258 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2014-06-01 to 2016-03-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (12 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"EW 0.283 ( 28.26%)\n",
|
|||
|
|
"MKTX 0.243 ( 24.27%)\n",
|
|||
|
|
"HRL 0.135 ( 13.54%)\n",
|
|||
|
|
"TTWO 0.125 ( 12.52%)\n",
|
|||
|
|
"DPZ 0.122 ( 12.15%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"GPN 0.076 ( 7.59%)\n",
|
|||
|
|
"AMZN 0.052 ( 5.24%)\n",
|
|||
|
|
"EA 0.021 ( 2.14%)\n",
|
|||
|
|
"NDAQ 0.017 ( 1.65%)\n",
|
|||
|
|
"MNST 0.011 ( 1.10%)\n",
|
|||
|
|
"VMC 0.011 ( 1.07%)\n",
|
|||
|
|
"Total Long 1.195 (119.53%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (4 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"DVN -0.229 (-22.90%)\n",
|
|||
|
|
"FCX -0.101 (-10.06%)\n",
|
|||
|
|
"MU -0.053 ( -5.27%)\n",
|
|||
|
|
"WMB -0.018 ( -1.79%)\n",
|
|||
|
|
"Total Short -0.400 (-40.02%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.795 ( 79.51%)\n",
|
|||
|
|
"Total Portfolio 0.995 ( 99.51%)\n",
|
|||
|
|
"Gross Exposure 1.595 (159.55%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.001878, Time: 5.6258s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: FAANG_surge\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: FAANG_surge\n",
|
|||
|
|
"Time Period: 2015-01-01 to 2021-01-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002204 (0.2204%)\n",
|
|||
|
|
"CVaR (95%): 0.035408 (3.5408%)\n",
|
|||
|
|
"Objective Value: -0.001038\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4637 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3668 seconds\n",
|
|||
|
|
"Solve Time: 44.2222 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2015-01-01 to 2021-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"MKTX 0.253 ( 25.35%)\n",
|
|||
|
|
"NVDA 0.231 ( 23.10%)\n",
|
|||
|
|
"AMZN 0.186 ( 18.63%)\n",
|
|||
|
|
"CPRT 0.150 ( 14.98%)\n",
|
|||
|
|
"DHR 0.101 ( 10.06%)\n",
|
|||
|
|
"AMD 0.099 ( 9.87%)\n",
|
|||
|
|
"ALGN 0.070 ( 6.97%)\n",
|
|||
|
|
"NEM 0.036 ( 3.64%)\n",
|
|||
|
|
"NFLX 0.034 ( 3.36%)\n",
|
|||
|
|
"WST 0.021 ( 2.07%)\n",
|
|||
|
|
"PGR 0.012 ( 1.19%)\n",
|
|||
|
|
"Total Long 1.192 (119.22%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (6 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"WDC -0.090 ( -8.97%)\n",
|
|||
|
|
"DVN -0.078 ( -7.76%)\n",
|
|||
|
|
"PCG -0.075 ( -7.47%)\n",
|
|||
|
|
"APA -0.071 ( -7.09%)\n",
|
|||
|
|
"VTRS -0.067 ( -6.73%)\n",
|
|||
|
|
"BIIB -0.018 ( -1.80%)\n",
|
|||
|
|
"Total Short -0.398 (-39.82%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.794 ( 79.41%)\n",
|
|||
|
|
"Total Portfolio 0.994 ( 99.41%)\n",
|
|||
|
|
"Gross Exposure 1.590 (159.04%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.001038, Time: 44.2222s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: FAANG_surge\n",
|
|||
|
|
"Time Period: 2015-01-01 to 2021-01-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002205 (0.2205%)\n",
|
|||
|
|
"CVaR (95%): 0.035420 (3.5420%)\n",
|
|||
|
|
"Objective Value: -0.001039\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2639 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.1018 seconds\n",
|
|||
|
|
"Solve Time: 4.4764 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2015-01-01 to 2021-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"MKTX 0.254 ( 25.37%)\n",
|
|||
|
|
"NVDA 0.232 ( 23.21%)\n",
|
|||
|
|
"AMZN 0.187 ( 18.69%)\n",
|
|||
|
|
"CPRT 0.151 ( 15.05%)\n",
|
|||
|
|
"DHR 0.101 ( 10.15%)\n",
|
|||
|
|
"AMD 0.099 ( 9.91%)\n",
|
|||
|
|
"ALGN 0.069 ( 6.87%)\n",
|
|||
|
|
"NEM 0.036 ( 3.61%)\n",
|
|||
|
|
"NFLX 0.033 ( 3.29%)\n",
|
|||
|
|
"WST 0.019 ( 1.92%)\n",
|
|||
|
|
"PGR 0.011 ( 1.14%)\n",
|
|||
|
|
"Total Long 1.192 (119.21%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (6 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"WDC -0.090 ( -9.01%)\n",
|
|||
|
|
"DVN -0.078 ( -7.81%)\n",
|
|||
|
|
"PCG -0.075 ( -7.47%)\n",
|
|||
|
|
"APA -0.071 ( -7.06%)\n",
|
|||
|
|
"VTRS -0.067 ( -6.69%)\n",
|
|||
|
|
"BIIB -0.018 ( -1.77%)\n",
|
|||
|
|
"Total Short -0.398 (-39.82%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.000 ( -0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.794 ( 79.40%)\n",
|
|||
|
|
"Total Portfolio 0.994 ( 99.39%)\n",
|
|||
|
|
"Gross Exposure 1.590 (159.03%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.001039, Time: 4.4764s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: covid\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: covid\n",
|
|||
|
|
"Time Period: 2020-01-01 to 2023-01-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002585 (0.2585%)\n",
|
|||
|
|
"CVaR (95%): 0.038982 (3.8982%)\n",
|
|||
|
|
"Objective Value: -0.001398\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.5059 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3704 seconds\n",
|
|||
|
|
"Solve Time: 48.0219 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2020-01-01 to 2023-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (9 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"PWR 0.269 ( 26.94%)\n",
|
|||
|
|
"STLD 0.223 ( 22.30%)\n",
|
|||
|
|
"LLY 0.210 ( 20.99%)\n",
|
|||
|
|
"MCK 0.175 ( 17.52%)\n",
|
|||
|
|
"EQT 0.101 ( 10.14%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"BBWI 0.053 ( 5.34%)\n",
|
|||
|
|
"ON 0.047 ( 4.68%)\n",
|
|||
|
|
"DECK 0.019 ( 1.86%)\n",
|
|||
|
|
"Total Long 1.198 (119.76%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"CCL -0.300 (-30.00%)\n",
|
|||
|
|
"SWK -0.078 ( -7.82%)\n",
|
|||
|
|
"INTC -0.012 ( -1.22%)\n",
|
|||
|
|
"Total Short -0.390 (-39.03%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.807 ( 80.73%)\n",
|
|||
|
|
"Total Portfolio 1.007 (100.73%)\n",
|
|||
|
|
"Gross Exposure 1.588 (158.79%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.001398, Time: 48.0219s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: covid\n",
|
|||
|
|
"Time Period: 2020-01-01 to 2023-01-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002586 (0.2586%)\n",
|
|||
|
|
"CVaR (95%): 0.038959 (3.8959%)\n",
|
|||
|
|
"Objective Value: -0.001400\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2707 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0916 seconds\n",
|
|||
|
|
"Solve Time: 5.1766 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2020-01-01 to 2023-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (9 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"PWR 0.272 ( 27.18%)\n",
|
|||
|
|
"STLD 0.224 ( 22.41%)\n",
|
|||
|
|
"LLY 0.210 ( 20.96%)\n",
|
|||
|
|
"MCK 0.174 ( 17.37%)\n",
|
|||
|
|
"EQT 0.102 ( 10.24%)\n",
|
|||
|
|
"NVDA 0.100 ( 10.00%)\n",
|
|||
|
|
"BBWI 0.052 ( 5.24%)\n",
|
|||
|
|
"ON 0.046 ( 4.56%)\n",
|
|||
|
|
"DECK 0.019 ( 1.86%)\n",
|
|||
|
|
"Total Long 1.198 (119.82%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"CCL -0.300 (-30.00%)\n",
|
|||
|
|
"SWK -0.079 ( -7.93%)\n",
|
|||
|
|
"MTCH -0.011 ( -1.11%)\n",
|
|||
|
|
"Total Short -0.390 (-39.04%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.808 ( 80.78%)\n",
|
|||
|
|
"Total Portfolio 1.008 (100.78%)\n",
|
|||
|
|
"Gross Exposure 1.589 (158.86%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.001400, Time: 5.1766s--------------------------------\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Processing Regime: recent\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CLARABEL ---\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CLARABEL\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2022-01-01 to 2024-07-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003073 (0.3073%)\n",
|
|||
|
|
"CVaR (95%): 0.026250 (2.6250%)\n",
|
|||
|
|
"Objective Value: -0.001678\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.4617 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.3704 seconds\n",
|
|||
|
|
"Solve Time: 40.2861 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CLARABEL_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2022-01-01 to 2024-07-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (9 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.387 ( 38.74%)\n",
|
|||
|
|
"FICO 0.277 ( 27.73%)\n",
|
|||
|
|
"NVDA 0.164 ( 16.37%)\n",
|
|||
|
|
"MCK 0.123 ( 12.34%)\n",
|
|||
|
|
"GE 0.100 ( 9.97%)\n",
|
|||
|
|
"XOM 0.049 ( 4.93%)\n",
|
|||
|
|
"VLO 0.044 ( 4.36%)\n",
|
|||
|
|
"PGR 0.041 ( 4.12%)\n",
|
|||
|
|
"STLD 0.014 ( 1.43%)\n",
|
|||
|
|
"Total Long 1.200 (119.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.207 (-20.66%)\n",
|
|||
|
|
"ILMN -0.116 (-11.56%)\n",
|
|||
|
|
"EL -0.078 ( -7.78%)\n",
|
|||
|
|
"Total Short -0.400 (-40.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.01%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 79.99%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.00%)\n",
|
|||
|
|
"Gross Exposure 1.600 (159.99%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CLARABEL - Objective: -0.001678, Time: 40.2861s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"--- Testing Solver: CUOPT ---\n",
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"Setting parameter absolute_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_dual_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_primal_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter absolute_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"Setting parameter relative_gap_tolerance to 1.000000e-04\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2022-01-01 to 2024-07-01\n",
|
|||
|
|
"Scenarios: 20,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.003074 (0.3074%)\n",
|
|||
|
|
"CVaR (95%): 0.026240 (2.6240%)\n",
|
|||
|
|
"Objective Value: -0.001680\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.3406 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0988 seconds\n",
|
|||
|
|
"Solve Time: 4.8934 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2022-01-01 to 2024-07-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (9 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.388 ( 38.81%)\n",
|
|||
|
|
"FICO 0.277 ( 27.75%)\n",
|
|||
|
|
"NVDA 0.163 ( 16.35%)\n",
|
|||
|
|
"MCK 0.123 ( 12.34%)\n",
|
|||
|
|
"GE 0.100 ( 9.99%)\n",
|
|||
|
|
"XOM 0.050 ( 4.99%)\n",
|
|||
|
|
"VLO 0.043 ( 4.28%)\n",
|
|||
|
|
"PGR 0.040 ( 4.02%)\n",
|
|||
|
|
"STLD 0.015 ( 1.47%)\n",
|
|||
|
|
"Total Long 1.200 (119.99%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (3 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.206 (-20.65%)\n",
|
|||
|
|
"ILMN -0.116 (-11.58%)\n",
|
|||
|
|
"EL -0.078 ( -7.80%)\n",
|
|||
|
|
"Total Short -0.400 (-40.03%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.02%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 79.96%)\n",
|
|||
|
|
"Total Portfolio 1.000 ( 99.98%)\n",
|
|||
|
|
"Gross Exposure 1.600 (160.02%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
" ✓ CUOPT - Objective: -0.001680, Time: 4.8934s--------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"Optimization Complete!\n",
|
|||
|
|
"======================================================================\n",
|
|||
|
|
"\n",
|
|||
|
|
"\n",
|
|||
|
|
"Results saved to: ./results/regime_results/both_results_sp500_20000.csv\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# CVaR parameters for regime comparison\n",
|
|||
|
|
"regime_comparison_cvar_params = CvarParameters(\n",
|
|||
|
|
" w_min={\"NVDA\":0.1, \"others\": -0.3}, w_max={\"NVDA\": 0.6, \"others\": 0.4}, # Asset weight allocation bounds\n",
|
|||
|
|
" c_min=0.0, c_max=0.2, # Cash holdings bounds\n",
|
|||
|
|
" L_tar=1.6, T_tar=None, # Leverage and turnover (None for this example)\n",
|
|||
|
|
" cvar_limit=None, # Max CVaR (None = unconstrained for this example)\n",
|
|||
|
|
" cardinality = None, # Cardinality constraints\n",
|
|||
|
|
" risk_aversion=1, # Risk aversion level\n",
|
|||
|
|
" confidence=0.95, # CVaR confidence level (alpha)\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# User inputs for regime comparison\n",
|
|||
|
|
"regime_comparison_dataset_name = \"sp500\"\n",
|
|||
|
|
"regime_comparison_num_scen = 20000\n",
|
|||
|
|
"regime_comparison_returns_compute_settings = {'return_type': 'LOG', 'freq': 1}\n",
|
|||
|
|
"regime_comparison_scenario_generation_settings = {'num_scen': regime_comparison_num_scen, # Number of return scenarios to simulate \n",
|
|||
|
|
" 'fit_type': 'kde', \n",
|
|||
|
|
" 'kde_settings': {'bandwidth': 0.01, \n",
|
|||
|
|
" 'kernel': 'gaussian', \n",
|
|||
|
|
" 'device': 'GPU'\n",
|
|||
|
|
" },\n",
|
|||
|
|
" 'verbose': False\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Prepare output directory and file name\n",
|
|||
|
|
"regime_comparison_output_folder = \"./results/regime_results\"\n",
|
|||
|
|
"os.makedirs(regime_comparison_output_folder, exist_ok=True)\n",
|
|||
|
|
"regime_comparison_results_csv_path = os.path.join(\n",
|
|||
|
|
" regime_comparison_output_folder,\n",
|
|||
|
|
" f\"both_results_{regime_comparison_dataset_name}_{regime_comparison_num_scen}.csv\"\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Regime settings (customize as needed)\n",
|
|||
|
|
"regime_comparison_selected_dict = {\n",
|
|||
|
|
" \"pre_crisis\" : (\"2005-01-01\", \"2007-10-01\"),\n",
|
|||
|
|
" \"crisis\" : (\"2007-10-01\", \"2009-04-01\"),\n",
|
|||
|
|
" \"post_crisis\" : (\"2009-06-30\", \"2014-06-30\"),\n",
|
|||
|
|
" \"oil_price_crash\" : (\"2014-06-01\", \"2016-03-01\"),\n",
|
|||
|
|
" \"FAANG_surge\" : (\"2015-01-01\", \"2021-01-01\"),\n",
|
|||
|
|
" \"covid\" : (\"2020-01-01\", \"2023-01-01\"),\n",
|
|||
|
|
" \"recent\" : (\"2022-01-01\", \"2024-07-01\")\n",
|
|||
|
|
"}\n",
|
|||
|
|
"\n",
|
|||
|
|
"# List of solvers to compare - any supported solver on CVXPY can be used.\n",
|
|||
|
|
"solver_settings_list = [\n",
|
|||
|
|
" {\"solver\": cp.CLARABEL, \"verbose\": False, \"tol_gap_abs\": 1e-4, \"tol_gap_rel\": 1e-4, \"tol_feas\": 1e-4}, \n",
|
|||
|
|
" {\"solver\":cp.CUOPT, \"verbose\": False, \"solver_method\": \"PDLP\", \"optimality\": 1e-4}\n",
|
|||
|
|
"]\n",
|
|||
|
|
"\n",
|
|||
|
|
"regime_comparison_dataset_path = f\"./data/stock_data/{regime_comparison_dataset_name}.csv\"\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Run CPU vs. GPU comparison across selected regimes\n",
|
|||
|
|
"regime_comparison_results_df = cvar_utils.optimize_market_regimes(\n",
|
|||
|
|
" input_file_name=regime_comparison_dataset_path,\n",
|
|||
|
|
" returns_compute_settings=regime_comparison_returns_compute_settings,\n",
|
|||
|
|
" scenario_generation_settings=regime_comparison_scenario_generation_settings,\n",
|
|||
|
|
" all_regimes=regime_comparison_selected_dict,\n",
|
|||
|
|
" cvar_params=regime_comparison_cvar_params,\n",
|
|||
|
|
" solver_settings_list=solver_settings_list,\n",
|
|||
|
|
" results_csv_file_name=regime_comparison_results_csv_path\n",
|
|||
|
|
")\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 19,
|
|||
|
|
"id": "21b08082-b0b3-4564-b69d-a7973f384359",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"text/html": [
|
|||
|
|
"<div>\n",
|
|||
|
|
"<style scoped>\n",
|
|||
|
|
" .dataframe tbody tr th:only-of-type {\n",
|
|||
|
|
" vertical-align: middle;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .dataframe tbody tr th {\n",
|
|||
|
|
" vertical-align: top;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"\n",
|
|||
|
|
" .dataframe thead th {\n",
|
|||
|
|
" text-align: right;\n",
|
|||
|
|
" }\n",
|
|||
|
|
"</style>\n",
|
|||
|
|
"<table border=\"1\" class=\"dataframe\">\n",
|
|||
|
|
" <thead>\n",
|
|||
|
|
" <tr style=\"text-align: right;\">\n",
|
|||
|
|
" <th></th>\n",
|
|||
|
|
" <th>regime</th>\n",
|
|||
|
|
" <th>CLARABEL-obj</th>\n",
|
|||
|
|
" <th>CLARABEL-solve_time</th>\n",
|
|||
|
|
" <th>CLARABEL-return</th>\n",
|
|||
|
|
" <th>CLARABEL-CVaR</th>\n",
|
|||
|
|
" <th>CLARABEL-optimal_portfolio</th>\n",
|
|||
|
|
" <th>CUOPT-obj</th>\n",
|
|||
|
|
" <th>CUOPT-solve_time</th>\n",
|
|||
|
|
" <th>CUOPT-return</th>\n",
|
|||
|
|
" <th>CUOPT-CVaR</th>\n",
|
|||
|
|
" <th>CUOPT-optimal_portfolio</th>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </thead>\n",
|
|||
|
|
" <tbody>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>0</th>\n",
|
|||
|
|
" <td>pre_crisis</td>\n",
|
|||
|
|
" <td>-0.001916</td>\n",
|
|||
|
|
" <td>40.963183</td>\n",
|
|||
|
|
" <td>0.003253</td>\n",
|
|||
|
|
" <td>0.027550</td>\n",
|
|||
|
|
" <td>({'AAPL': 0.1685073593576531, 'AMD': -0.033126...</td>\n",
|
|||
|
|
" <td>-0.001917</td>\n",
|
|||
|
|
" <td>3.249603</td>\n",
|
|||
|
|
" <td>0.003253</td>\n",
|
|||
|
|
" <td>0.027507</td>\n",
|
|||
|
|
" <td>({'AAPL': 0.16860751658281875, 'AMD': -0.03328...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>1</th>\n",
|
|||
|
|
" <td>crisis</td>\n",
|
|||
|
|
" <td>-0.003765</td>\n",
|
|||
|
|
" <td>48.614852</td>\n",
|
|||
|
|
" <td>0.005043</td>\n",
|
|||
|
|
" <td>0.061742</td>\n",
|
|||
|
|
" <td>({'AIG': -0.16812210214261433, 'AZO': 0.399955...</td>\n",
|
|||
|
|
" <td>-0.003764</td>\n",
|
|||
|
|
" <td>8.738473</td>\n",
|
|||
|
|
" <td>0.005039</td>\n",
|
|||
|
|
" <td>0.061607</td>\n",
|
|||
|
|
" <td>({'AIG': -0.16815012352088726, 'AZO': 0.4, 'EW...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>2</th>\n",
|
|||
|
|
" <td>post_crisis</td>\n",
|
|||
|
|
" <td>-0.000929</td>\n",
|
|||
|
|
" <td>38.870057</td>\n",
|
|||
|
|
" <td>0.001885</td>\n",
|
|||
|
|
" <td>0.024646</td>\n",
|
|||
|
|
" <td>({'AAPL': 0.02358144584078945, 'AMD': -0.07975...</td>\n",
|
|||
|
|
" <td>-0.000930</td>\n",
|
|||
|
|
" <td>3.468889</td>\n",
|
|||
|
|
" <td>0.001886</td>\n",
|
|||
|
|
" <td>0.024644</td>\n",
|
|||
|
|
" <td>({'AAPL': 0.022262262417416197, 'AMD': -0.0793...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>3</th>\n",
|
|||
|
|
" <td>oil_price_crash</td>\n",
|
|||
|
|
" <td>-0.001877</td>\n",
|
|||
|
|
" <td>40.830537</td>\n",
|
|||
|
|
" <td>0.003050</td>\n",
|
|||
|
|
" <td>0.026816</td>\n",
|
|||
|
|
" <td>({'AMZN': 0.051964279112029, 'DPZ': 0.12105432...</td>\n",
|
|||
|
|
" <td>-0.001878</td>\n",
|
|||
|
|
" <td>5.625769</td>\n",
|
|||
|
|
" <td>0.003051</td>\n",
|
|||
|
|
" <td>0.026809</td>\n",
|
|||
|
|
" <td>({'AMZN': 0.05237064378401218, 'DPZ': 0.121522...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>4</th>\n",
|
|||
|
|
" <td>FAANG_surge</td>\n",
|
|||
|
|
" <td>-0.001038</td>\n",
|
|||
|
|
" <td>44.222174</td>\n",
|
|||
|
|
" <td>0.002204</td>\n",
|
|||
|
|
" <td>0.035408</td>\n",
|
|||
|
|
" <td>({'ALGN': 0.06974858672725494, 'AMD': 0.098709...</td>\n",
|
|||
|
|
" <td>-0.001039</td>\n",
|
|||
|
|
" <td>4.476395</td>\n",
|
|||
|
|
" <td>0.002205</td>\n",
|
|||
|
|
" <td>0.035420</td>\n",
|
|||
|
|
" <td>({'ALGN': 0.06872191517563653, 'AMD': 0.099075...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>5</th>\n",
|
|||
|
|
" <td>covid</td>\n",
|
|||
|
|
" <td>-0.001398</td>\n",
|
|||
|
|
" <td>48.021944</td>\n",
|
|||
|
|
" <td>0.002585</td>\n",
|
|||
|
|
" <td>0.038982</td>\n",
|
|||
|
|
" <td>({'BBWI': 0.05343440949863733, 'CCL': -0.29996...</td>\n",
|
|||
|
|
" <td>-0.001400</td>\n",
|
|||
|
|
" <td>5.176596</td>\n",
|
|||
|
|
" <td>0.002586</td>\n",
|
|||
|
|
" <td>0.038959</td>\n",
|
|||
|
|
" <td>({'BBWI': 0.05235860238493561, 'CCL': -0.3, 'D...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" <tr>\n",
|
|||
|
|
" <th>6</th>\n",
|
|||
|
|
" <td>recent</td>\n",
|
|||
|
|
" <td>-0.001678</td>\n",
|
|||
|
|
" <td>40.286131</td>\n",
|
|||
|
|
" <td>0.003073</td>\n",
|
|||
|
|
" <td>0.026250</td>\n",
|
|||
|
|
" <td>({'EL': -0.07779108743969854, 'FICO': 0.277290...</td>\n",
|
|||
|
|
" <td>-0.001680</td>\n",
|
|||
|
|
" <td>4.893435</td>\n",
|
|||
|
|
" <td>0.003074</td>\n",
|
|||
|
|
" <td>0.026240</td>\n",
|
|||
|
|
" <td>({'EL': -0.07802863183939351, 'FICO': 0.277490...</td>\n",
|
|||
|
|
" </tr>\n",
|
|||
|
|
" </tbody>\n",
|
|||
|
|
"</table>\n",
|
|||
|
|
"</div>"
|
|||
|
|
],
|
|||
|
|
"text/plain": [
|
|||
|
|
" regime CLARABEL-obj CLARABEL-solve_time CLARABEL-return \\\n",
|
|||
|
|
"0 pre_crisis -0.001916 40.963183 0.003253 \n",
|
|||
|
|
"1 crisis -0.003765 48.614852 0.005043 \n",
|
|||
|
|
"2 post_crisis -0.000929 38.870057 0.001885 \n",
|
|||
|
|
"3 oil_price_crash -0.001877 40.830537 0.003050 \n",
|
|||
|
|
"4 FAANG_surge -0.001038 44.222174 0.002204 \n",
|
|||
|
|
"5 covid -0.001398 48.021944 0.002585 \n",
|
|||
|
|
"6 recent -0.001678 40.286131 0.003073 \n",
|
|||
|
|
"\n",
|
|||
|
|
" CLARABEL-CVaR CLARABEL-optimal_portfolio \\\n",
|
|||
|
|
"0 0.027550 ({'AAPL': 0.1685073593576531, 'AMD': -0.033126... \n",
|
|||
|
|
"1 0.061742 ({'AIG': -0.16812210214261433, 'AZO': 0.399955... \n",
|
|||
|
|
"2 0.024646 ({'AAPL': 0.02358144584078945, 'AMD': -0.07975... \n",
|
|||
|
|
"3 0.026816 ({'AMZN': 0.051964279112029, 'DPZ': 0.12105432... \n",
|
|||
|
|
"4 0.035408 ({'ALGN': 0.06974858672725494, 'AMD': 0.098709... \n",
|
|||
|
|
"5 0.038982 ({'BBWI': 0.05343440949863733, 'CCL': -0.29996... \n",
|
|||
|
|
"6 0.026250 ({'EL': -0.07779108743969854, 'FICO': 0.277290... \n",
|
|||
|
|
"\n",
|
|||
|
|
" CUOPT-obj CUOPT-solve_time CUOPT-return CUOPT-CVaR \\\n",
|
|||
|
|
"0 -0.001917 3.249603 0.003253 0.027507 \n",
|
|||
|
|
"1 -0.003764 8.738473 0.005039 0.061607 \n",
|
|||
|
|
"2 -0.000930 3.468889 0.001886 0.024644 \n",
|
|||
|
|
"3 -0.001878 5.625769 0.003051 0.026809 \n",
|
|||
|
|
"4 -0.001039 4.476395 0.002205 0.035420 \n",
|
|||
|
|
"5 -0.001400 5.176596 0.002586 0.038959 \n",
|
|||
|
|
"6 -0.001680 4.893435 0.003074 0.026240 \n",
|
|||
|
|
"\n",
|
|||
|
|
" CUOPT-optimal_portfolio \n",
|
|||
|
|
"0 ({'AAPL': 0.16860751658281875, 'AMD': -0.03328... \n",
|
|||
|
|
"1 ({'AIG': -0.16815012352088726, 'AZO': 0.4, 'EW... \n",
|
|||
|
|
"2 ({'AAPL': 0.022262262417416197, 'AMD': -0.0793... \n",
|
|||
|
|
"3 ({'AMZN': 0.05237064378401218, 'DPZ': 0.121522... \n",
|
|||
|
|
"4 ({'ALGN': 0.06872191517563653, 'AMD': 0.099075... \n",
|
|||
|
|
"5 ({'BBWI': 0.05235860238493561, 'CCL': -0.3, 'D... \n",
|
|||
|
|
"6 ({'EL': -0.07802863183939351, 'FICO': 0.277490... "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"execution_count": 19,
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "execute_result"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Display regime comparison results\n",
|
|||
|
|
"regime_comparison_results_df"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 20,
|
|||
|
|
"id": "c922c623",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"data": {
|
|||
|
|
"text/plain": [
|
|||
|
|
"regime\n",
|
|||
|
|
"pre_crisis 12.605598\n",
|
|||
|
|
"crisis 5.563312\n",
|
|||
|
|
"post_crisis 11.205334\n",
|
|||
|
|
"oil_price_crash 7.257770\n",
|
|||
|
|
"FAANG_surge 9.878970\n",
|
|||
|
|
"covid 9.276743\n",
|
|||
|
|
"recent 8.232689\n",
|
|||
|
|
"dtype: float64"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
"execution_count": 20,
|
|||
|
|
"metadata": {},
|
|||
|
|
"output_type": "execute_result"
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Show the speed-up ratio of CPU solvers vs cuOpt GPU LP solver \n",
|
|||
|
|
"regime_comparison_results_df.index = regime_comparison_results_df['regime']\n",
|
|||
|
|
"speed_comparison_df = regime_comparison_results_df['CLARABEL-solve_time'] / regime_comparison_results_df['CUOPT-solve_time'] # CPU solve time / GPU solve time\n",
|
|||
|
|
"speed_comparison_df"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "b48ae7b9",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"---\n",
|
|||
|
|
"\n",
|
|||
|
|
"<a id='appendix'></a>\n",
|
|||
|
|
"## 6. Appendix\n",
|
|||
|
|
"\n",
|
|||
|
|
"### 6.1 Optional: Parameter Constraints\n",
|
|||
|
|
"Optional to define weight and cash constraints as CVXPY parameter for faster iteration. \n",
|
|||
|
|
"\n",
|
|||
|
|
"In some use cases, there is a need to update the weight and cash constraints while keeping the rest of the original problem (dataset and other constraints), this is the faster way without re-building the entire problem. \n",
|
|||
|
|
"\n",
|
|||
|
|
"Note that in `cvar_optimizer.py` the weight and cash constraints are defaulted to be variable bounds for the weight variable ${w}$ and cash variable $c$, i.e. \n",
|
|||
|
|
"```\n",
|
|||
|
|
"self.w = cp.Variable(num_assets, name=\"weights\", bounds=[self.params.w_min, self.params.w_max])\n",
|
|||
|
|
"```\n",
|
|||
|
|
"because empirically cuOpt LP solver is faster when constraints are set as variable bounds. "
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 21,
|
|||
|
|
"id": "e44a8167",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"Setting parameter log_to_console to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: CUOPT\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"Scenarios: 10,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002556 (0.2556%)\n",
|
|||
|
|
"CVaR (95%): 0.025915 (2.5915%)\n",
|
|||
|
|
"Objective Value: -0.001447\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 0.2948 seconds\n",
|
|||
|
|
"CVXPY API Overhead: 0.0465 seconds\n",
|
|||
|
|
"Solve Time: 1.6466 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.291 ( 29.06%)\n",
|
|||
|
|
"NVDA 0.173 ( 17.31%)\n",
|
|||
|
|
"MCK 0.168 ( 16.84%)\n",
|
|||
|
|
"JBL 0.101 ( 10.13%)\n",
|
|||
|
|
"COP 0.098 ( 9.79%)\n",
|
|||
|
|
"IRM 0.090 ( 9.00%)\n",
|
|||
|
|
"PWR 0.088 ( 8.84%)\n",
|
|||
|
|
"IT 0.062 ( 6.19%)\n",
|
|||
|
|
"NUE 0.051 ( 5.11%)\n",
|
|||
|
|
"FICO 0.040 ( 4.03%)\n",
|
|||
|
|
"STLD 0.038 ( 3.76%)\n",
|
|||
|
|
"Total Long 1.200 (120.04%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (2 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.279 (-27.90%)\n",
|
|||
|
|
"ILMN -0.122 (-12.15%)\n",
|
|||
|
|
"Total Short -0.401 (-40.06%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual 0.000 ( 0.04%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 79.99%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.03%)\n",
|
|||
|
|
"Gross Exposure 1.601 (160.10%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Instantiate CVaR optimization problem for the S&P 500 example\n",
|
|||
|
|
"api_settings = {\n",
|
|||
|
|
" \"api\": \"cvxpy\", # \"cvxpy\" or \"cuopt_python\"\n",
|
|||
|
|
" \"weight_constraints_type\": \"parameter\", # \"parameter\" or \"bounds\" (CVXPY only)\n",
|
|||
|
|
" \"cash_constraints_type\": \"parameter\", # \"parameter\" or \"bounds\" (CVXPY only)\n",
|
|||
|
|
" }\n",
|
|||
|
|
"cvar_problem = cvar_optimizer.CVaR(\n",
|
|||
|
|
" returns_dict=returns_dict,\n",
|
|||
|
|
" cvar_params=cvar_params,\n",
|
|||
|
|
" api_settings=api_settings\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solve on GPU\n",
|
|||
|
|
"gpu_solver_settings = {\"solver\":cp.CUOPT, \"verbose\": False, \"solver_method\": \"PDLP\"} \n",
|
|||
|
|
"gpu_results, gpu_portfolio = cvar_problem.solve_optimization_problem(solver_settings=gpu_solver_settings)\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "1a4724a6",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"### 6.2 Optional: cuOpt Python API\n",
|
|||
|
|
"Instead of using CVXPY modeling framework, we can build the problem directly in the cuOpt native python API by choosing `api_settings`.\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "code",
|
|||
|
|
"execution_count": 22,
|
|||
|
|
"id": "3dd08270",
|
|||
|
|
"metadata": {},
|
|||
|
|
"outputs": [
|
|||
|
|
{
|
|||
|
|
"name": "stdout",
|
|||
|
|
"output_type": "stream",
|
|||
|
|
"text": [
|
|||
|
|
"==================================================\n",
|
|||
|
|
"cuOpt PROBLEM SETUP COMPLETED\n",
|
|||
|
|
"==================================================\n",
|
|||
|
|
"Variables: 392 weights + 1 cash + 10000 auxiliary + 1 threshold\n",
|
|||
|
|
" + 784 leverage decomposition\n",
|
|||
|
|
"Constraints: Budget + 10000 CVaR scenarios + additional constraints\n",
|
|||
|
|
"Problem Type: LP\n",
|
|||
|
|
"==================================================\n",
|
|||
|
|
"Setting parameter log_to_console to true\n",
|
|||
|
|
"Setting parameter presolve to false\n",
|
|||
|
|
"Setting parameter method to 1\n",
|
|||
|
|
"cuOpt version: 25.10.1, git hash: 876fcfc, host arch: aarch64, device archs: 75-real,80-real,86-real,90a-real,100f-real,120a-real,120\n",
|
|||
|
|
"CPU: Unknown, threads (physical/logical): 1/20, RAM: 46.66 GiB\n",
|
|||
|
|
"CUDA 13.0, device: NVIDIA GB10 (ID 0), VRAM: 119.70 GiB\n",
|
|||
|
|
"CUDA device UUID: 978712c9-013d-7aa8-c22e-fd237bb0e910\n",
|
|||
|
|
"\n",
|
|||
|
|
"Solving a problem with 10394 constraints, 11178 variables (0 integers), and 3942353 nonzeros\n",
|
|||
|
|
"Problem scaling:\n",
|
|||
|
|
"Objective coefficents range: [6e-07, 4e-02]\n",
|
|||
|
|
"Constraint matrix coefficients range: [2e-08, 1e+00]\n",
|
|||
|
|
"Constraint rhs / bounds range: [0e+00, 2e+00]\n",
|
|||
|
|
"Variable bounds range: [1e-01, 6e-01]\n",
|
|||
|
|
"Warning: input problem contains a large range of coefficients: consider reformulating to avoid numerical difficulties.\n",
|
|||
|
|
"\n",
|
|||
|
|
"Third-party presolve is disabled, skipping\n",
|
|||
|
|
"Objective offset 0.000000 scaling_factor 1.000000\n",
|
|||
|
|
" Iter Primal Obj. Dual Obj. Gap Primal Res. Dual Res. Time\n",
|
|||
|
|
" 0 +0.00000000e+00 +0.00000000e+00 0.00e+00 1.00e+00 4.53e-02 0.097s\n",
|
|||
|
|
" 1000 -1.52650212e-03 -1.38184241e-03 1.45e-04 7.00e-02 2.12e-04 0.809s\n",
|
|||
|
|
" 2000 -1.44908759e-03 -1.44508348e-03 4.00e-06 2.98e-03 1.38e-05 1.292s\n",
|
|||
|
|
" 2800 -1.44522073e-03 -1.44546814e-03 2.47e-07 2.42e-04 2.82e-06 1.671s\n",
|
|||
|
|
"LP Solver status: Optimal\n",
|
|||
|
|
"Primal objective: -1.44522073e-03\n",
|
|||
|
|
"Dual objective: -1.44546814e-03\n",
|
|||
|
|
"Duality gap (abs/rel): +2.47e-07 / +2.47e-07\n",
|
|||
|
|
"Primal infeasibility (abs/rel): +2.42e-04 / +8.37e-05\n",
|
|||
|
|
"Dual infeasibility (abs/rel): +2.82e-06 / +2.70e-06\n",
|
|||
|
|
"PDLP finished\n",
|
|||
|
|
"Status: Optimal Objective: -1.44522073e-03 Iterations: 2800 Time: 1.673s, Total time 1.688s\n",
|
|||
|
|
"cuOpt solution found in 1.69 seconds\n",
|
|||
|
|
"Status: Optimal\n",
|
|||
|
|
"Objective value: -0.001445\n",
|
|||
|
|
"\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"CVaR OPTIMIZATION RESULTS\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"PROBLEM CONFIGURATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Solver: cuOpt\n",
|
|||
|
|
"Regime: recent\n",
|
|||
|
|
"Time Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"Scenarios: 10,000\n",
|
|||
|
|
"Assets: 392\n",
|
|||
|
|
"Confidence Level: 95.0%\n",
|
|||
|
|
"\n",
|
|||
|
|
"PERFORMANCE METRICS\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Expected Return: 0.002552 (0.2552%)\n",
|
|||
|
|
"CVaR (95%): 0.025864 (2.5864%)\n",
|
|||
|
|
"Objective Value: -0.001445\n",
|
|||
|
|
"\n",
|
|||
|
|
"SOLVING PERFORMANCE\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"Setup Time: 6.5339 seconds\n",
|
|||
|
|
"cuOpt API Overhead: 0.4624 seconds\n",
|
|||
|
|
"Solve Time: 1.6879 seconds\n",
|
|||
|
|
"\n",
|
|||
|
|
"OPTIMAL PORTFOLIO ALLOCATION\n",
|
|||
|
|
"------------------------------\n",
|
|||
|
|
"\n",
|
|||
|
|
"PORTFOLIO: CUOPT_OPTIMAL\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"Period: 2021-01-01 to 2024-01-01\n",
|
|||
|
|
"\n",
|
|||
|
|
"LONG POSITIONS (11 assets)\n",
|
|||
|
|
"-------------------------\n",
|
|||
|
|
"LLY 0.289 ( 28.89%)\n",
|
|||
|
|
"NVDA 0.172 ( 17.18%)\n",
|
|||
|
|
"MCK 0.167 ( 16.70%)\n",
|
|||
|
|
"JBL 0.102 ( 10.16%)\n",
|
|||
|
|
"COP 0.096 ( 9.65%)\n",
|
|||
|
|
"IRM 0.091 ( 9.12%)\n",
|
|||
|
|
"PWR 0.089 ( 8.86%)\n",
|
|||
|
|
"IT 0.064 ( 6.36%)\n",
|
|||
|
|
"NUE 0.051 ( 5.07%)\n",
|
|||
|
|
"FICO 0.043 ( 4.25%)\n",
|
|||
|
|
"STLD 0.038 ( 3.76%)\n",
|
|||
|
|
"Total Long 1.200 (120.00%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"SHORT POSITIONS (2 assets)\n",
|
|||
|
|
"--------------------------\n",
|
|||
|
|
"MTCH -0.279 (-27.91%)\n",
|
|||
|
|
"ILMN -0.121 (-12.07%)\n",
|
|||
|
|
"Total Short -0.400 (-39.98%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"CASH & SUMMARY\n",
|
|||
|
|
"--------------------\n",
|
|||
|
|
"Cash 0.200 ( 20.00%)\n",
|
|||
|
|
"Residual -0.000 ( -0.02%)\n",
|
|||
|
|
"\n",
|
|||
|
|
"Net Equity 0.800 ( 80.02%)\n",
|
|||
|
|
"Total Portfolio 1.000 (100.00%)\n",
|
|||
|
|
"Gross Exposure 1.600 (159.99%)\n",
|
|||
|
|
"----------------------------------------\n",
|
|||
|
|
"============================================================\n",
|
|||
|
|
"\n"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"source": [
|
|||
|
|
"# Instantiate CVaR optimization problem using cuOpt Python API\n",
|
|||
|
|
"cvar_problem = cvar_optimizer.CVaR(\n",
|
|||
|
|
" returns_dict=returns_dict,\n",
|
|||
|
|
" cvar_params=cvar_params,\n",
|
|||
|
|
" api_settings={\"api\": \"cuopt_python\"}\n",
|
|||
|
|
")\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solver settings for cuOpt Python API\n",
|
|||
|
|
"cuopt_settings = {\"log_to_console\":True, \"presolve\": False, \"method\": 1}\n",
|
|||
|
|
"\n",
|
|||
|
|
"# Solve using cuOpt Python API\n",
|
|||
|
|
"cuopt_gpu_results, cuopt_gpu_portfolio = cvar_problem.solve_optimization_problem(solver_settings=cuopt_settings)\n"
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
"cell_type": "markdown",
|
|||
|
|
"id": "75b81e78",
|
|||
|
|
"metadata": {},
|
|||
|
|
"source": [
|
|||
|
|
"SPDX-FileCopyrightText: Copyright (c) 2023-2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. \n",
|
|||
|
|
"\n",
|
|||
|
|
"SPDX-License-Identifier: Apache-2.0\n",
|
|||
|
|
"\n",
|
|||
|
|
"Licensed under the Apache License, Version 2.0 (the \"License\");you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License."
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
],
|
|||
|
|
"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.13.7"
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
"nbformat": 4,
|
|||
|
|
"nbformat_minor": 5
|
|||
|
|
}
|