diff --git a/cookbook/2-Mean-Variance-Optimisation.ipynb b/cookbook/2-Mean-Variance-Optimisation.ipynb index 7aba6f28..f88fad24 100644 --- a/cookbook/2-Mean-Variance-Optimisation.ipynb +++ b/cookbook/2-Mean-Variance-Optimisation.ipynb @@ -29,9 +29,9 @@ "\n", "Please consult the [docs](https://pyportfolioopt.readthedocs.io/) for more info.\n", "\n", - "## Downloading data\n", + "## Importing data\n", "\n", - "To download data, we will use `yfinance`, an excellent library that provides free price data from Yahoo Finance, no API key needed.\n", + "We will use `load_stockdata`, to import some example price data.\n", "\n", "[](https://colab.research.google.com/github/pyportfolio/pyportfolioopt/blob/master/cookbook/2-Mean-Variance-Optimisation.ipynb)\n", " \n", @@ -44,379 +44,158 @@ }, { "cell_type": "code", + "execution_count": 1, "metadata": { + "ExecuteTime": { + "end_time": "2025-11-12T08:10:54.267009Z", + "start_time": "2025-11-12T08:10:53.573242Z" + }, "colab": { "base_uri": "https://localhost:8080/" }, "id": "69vaYVwZ-Cxz", - "outputId": "dee1bf4a-82ee-4909-e26b-217899258cf2", - "ExecuteTime": { - "end_time": "2025-11-12T08:10:54.267009Z", - "start_time": "2025-11-12T08:10:53.573242Z" - } + "outputId": "dee1bf4a-82ee-4909-e26b-217899258cf2" }, - "source": [ - "!pip install pandas numpy matplotlib yfinance PyPortfolioOpt\n", - "import os\n", - "if not os.path.isdir('data'):\n", - " os.system('git clone https://github.com/pyportfolio/pyportfolioopt.git')\n", - " os.chdir('PyPortfolioOpt/cookbook')" - ], "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: pandas in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (2.3.3)\r\n", - "Requirement already satisfied: numpy in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (2.3.4)\r\n", - "Requirement already satisfied: matplotlib in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (3.10.7)\r\n", - "Requirement already satisfied: yfinance in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (0.2.66)\r\n", - "Requirement already satisfied: PyPortfolioOpt in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (1.5.6)\r\n", - "Requirement already satisfied: python-dateutil>=2.8.2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from pandas) (2.9.0.post0)\r\n", - "Requirement already satisfied: pytz>=2020.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from pandas) (2025.2)\r\n", - "Requirement already satisfied: tzdata>=2022.7 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from pandas) (2025.2)\r\n", - "Requirement already satisfied: contourpy>=1.0.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (1.3.3)\r\n", - "Requirement already satisfied: cycler>=0.10 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (0.12.1)\r\n", - "Requirement already satisfied: fonttools>=4.22.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (4.60.1)\r\n", - "Requirement already satisfied: kiwisolver>=1.3.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (1.4.9)\r\n", - "Requirement already satisfied: packaging>=20.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (25.0)\r\n", - "Requirement already satisfied: pillow>=8 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (12.0.0)\r\n", - "Requirement already satisfied: pyparsing>=3 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from matplotlib) (3.2.5)\r\n", - "Requirement already satisfied: requests>=2.31 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (2.32.5)\r\n", - "Requirement already satisfied: multitasking>=0.0.7 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (0.0.12)\r\n", - "Requirement already satisfied: platformdirs>=2.0.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (4.5.0)\r\n", - "Requirement already satisfied: frozendict>=2.3.4 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (2.4.7)\r\n", - "Requirement already satisfied: peewee>=3.16.2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (3.18.3)\r\n", - "Requirement already satisfied: beautifulsoup4>=4.11.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (4.14.2)\r\n", - "Requirement already satisfied: curl_cffi>=0.7 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (0.13.0)\r\n", - "Requirement already satisfied: protobuf>=3.19.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (6.33.0)\r\n", - "Requirement already satisfied: websockets>=13.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from yfinance) (15.0.1)\r\n", - "Requirement already satisfied: cvxpy>=1.1.19 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from PyPortfolioOpt) (1.7.3)\r\n", - "Requirement already satisfied: scikit-learn>=0.24.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from PyPortfolioOpt) (1.7.2)\r\n", - "Requirement already satisfied: scipy>=1.3.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from PyPortfolioOpt) (1.16.3)\r\n", - "Requirement already satisfied: soupsieve>1.2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from beautifulsoup4>=4.11.1->yfinance) (2.8)\r\n", - "Requirement already satisfied: typing-extensions>=4.0.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from beautifulsoup4>=4.11.1->yfinance) (4.15.0)\r\n", - "Requirement already satisfied: cffi>=1.12.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from curl_cffi>=0.7->yfinance) (2.0.0)\r\n", - "Requirement already satisfied: certifi>=2024.2.2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from curl_cffi>=0.7->yfinance) (2025.11.12)\r\n", - "Requirement already satisfied: osqp>=1.0.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (1.0.5)\r\n", - "Requirement already satisfied: clarabel>=0.5.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (0.11.1)\r\n", - "Requirement already satisfied: scs>=3.2.4.post1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (3.2.9)\r\n", - "Requirement already satisfied: six>=1.5 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)\r\n", - "Requirement already satisfied: charset_normalizer<4,>=2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance) (3.4.4)\r\n", - "Requirement already satisfied: idna<4,>=2.5 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance) (3.11)\r\n", - "Requirement already satisfied: urllib3<3,>=1.21.1 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from requests>=2.31->yfinance) (2.5.0)\r\n", - "Requirement already satisfied: joblib>=1.2.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from scikit-learn>=0.24.1->PyPortfolioOpt) (1.5.2)\r\n", - "Requirement already satisfied: threadpoolctl>=3.1.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from scikit-learn>=0.24.1->PyPortfolioOpt) (3.6.0)\r\n", - "Requirement already satisfied: pycparser in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from cffi>=1.12.0->curl_cffi>=0.7->yfinance) (2.23)\r\n", - "Requirement already satisfied: jinja2 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (3.1.6)\r\n", - "Requirement already satisfied: setuptools in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (80.9.0)\r\n", - "Requirement already satisfied: MarkupSafe>=2.0 in /Users/thomasschmelzer/projects/PyPortfolioOpt/.venv/lib/python3.12/site-packages (from jinja2->osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (3.0.3)\r\n", - "\r\n", - "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m A new release of pip is available: \u001B[0m\u001B[31;49m24.3.1\u001B[0m\u001B[39;49m -> \u001B[0m\u001B[32;49m25.3\u001B[0m\r\n", - "\u001B[1m[\u001B[0m\u001B[34;49mnotice\u001B[0m\u001B[1;39;49m]\u001B[0m\u001B[39;49m To update, run: \u001B[0m\u001B[32;49mpip install --upgrade pip\u001B[0m\r\n" + "Requirement already satisfied: pandas in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (2.2.3)\n", + "Requirement already satisfied: numpy in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (2.4.2)\n", + "Requirement already satisfied: matplotlib in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (3.10.0)\n", + "Requirement already satisfied: PyPortfolioOpt in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (1.6.0)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from pandas) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from pandas) (2025.1)\n", + "Requirement already satisfied: tzdata>=2022.7 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from pandas) (2025.1)\n", + "Requirement already satisfied: contourpy>=1.0.1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (1.3.1)\n", + "Requirement already satisfied: cycler>=0.10 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (4.56.0)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (1.4.8)\n", + "Requirement already satisfied: packaging>=20.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (24.2)\n", + "Requirement already satisfied: pillow>=8 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (11.1.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from matplotlib) (3.2.1)\n", + "Requirement already satisfied: cvxpy>=1.1.19 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from PyPortfolioOpt) (1.8.1)\n", + "Requirement already satisfied: scikit-base<0.14.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from PyPortfolioOpt) (0.13.1)\n", + "Requirement already satisfied: scikit-learn>=0.24.1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from PyPortfolioOpt) (1.6.1)\n", + "Requirement already satisfied: scipy>=1.3.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from PyPortfolioOpt) (1.15.2)\n", + "Requirement already satisfied: osqp>=1.0.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (1.1.1)\n", + "Requirement already satisfied: clarabel>=0.5.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (0.11.1)\n", + "Requirement already satisfied: scs>=3.2.4.post1 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (3.2.11)\n", + "Requirement already satisfied: highspy>=1.11.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from cvxpy>=1.1.19->PyPortfolioOpt) (1.13.1)\n", + "Requirement already satisfied: six>=1.5 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from python-dateutil>=2.8.2->pandas) (1.17.0)\n", + "Requirement already satisfied: joblib>=1.2.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from scikit-learn>=0.24.1->PyPortfolioOpt) (1.4.2)\n", + "Requirement already satisfied: threadpoolctl>=3.1.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from scikit-learn>=0.24.1->PyPortfolioOpt) (3.5.0)\n", + "Requirement already satisfied: cffi in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from clarabel>=0.5.0->cvxpy>=1.1.19->PyPortfolioOpt) (1.17.1)\n", + "Requirement already satisfied: jinja2 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (3.1.5)\n", + "Requirement already satisfied: setuptools in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (65.5.0)\n", + "Requirement already satisfied: pycparser in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from cffi->clarabel>=0.5.0->cvxpy>=1.1.19->PyPortfolioOpt) (2.22)\n", + "Requirement already satisfied: MarkupSafe>=2.0 in c:\\users\\shuvam\\appdata\\local\\programs\\python\\python311\\lib\\site-packages (from jinja2->osqp>=1.0.0->cvxpy>=1.1.19->PyPortfolioOpt) (2.1.5)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "[notice] A new release of pip available: 22.3 -> 26.0.1\n", + "[notice] To update, run: python.exe -m pip install --upgrade pip\n" ] } ], - "execution_count": 7 + "source": [ + "!pip install pandas numpy matplotlib PyPortfolioOpt\n", + "import os\n", + "if not os.path.isdir('data'):\n", + " os.system('git clone https://github.com/pyportfolio/pyportfolioopt.git')\n", + " os.chdir('PyPortfolioOpt/cookbook')" + ] }, { "cell_type": "code", + "execution_count": 2, "metadata": { - "id": "shuJGGeo9ny8", "ExecuteTime": { "end_time": "2025-11-12T08:10:54.280850Z", "start_time": "2025-11-12T08:10:54.278023Z" - } + }, + "id": "shuJGGeo9ny8" }, + "outputs": [], "source": [ - "import yfinance as yf\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", - "import numpy as np" - ], - "outputs": [], - "execution_count": 8 + "import numpy as np\n", + "from pypfopt.data.data_loader import load_stockdata" + ] }, { "cell_type": "code", + "execution_count": 3, "metadata": { - "id": "c4r8LJdC9ny8", "ExecuteTime": { "end_time": "2025-11-12T08:10:54.304666Z", "start_time": "2025-11-12T08:10:54.301956Z" - } + }, + "id": "c4r8LJdC9ny8" }, + "outputs": [], "source": [ "tickers = [\"MSFT\", \"AMZN\", \"KO\", \"MA\", \"COST\", \n", " \"LUV\", \"XOM\", \"PFE\", \"JPM\", \"UNH\", \n", " \"ACN\", \"DIS\", \"GILD\", \"F\", \"TSLA\"] " - ], - "outputs": [], - "execution_count": 9 + ] }, { "cell_type": "code", + "execution_count": 5, "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "XWdfXpB69ny9", - "outputId": "e60980bf-21e3-470f-a4f7-99da82c820a4", "ExecuteTime": { - "end_time": "2025-11-12T08:10:56.505627Z", - "start_time": "2025-11-12T08:10:54.345590Z" - } - }, - "source": "ohlc = yf.download(tickers, period=\"max\").loc[\"1990\":]", - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/var/folders/_3/k_9k5d5n5zz57w7qfll9rzs40000gn/T/ipykernel_59786/3860718606.py:1: FutureWarning: YF.download() has changed argument auto_adjust default to True\n", - " ohlc = yf.download(tickers, period=\"max\").loc[\"1990\":]\n", - "[*********************100%***********************] 15 of 15 completed\n" - ] - } - ], - "execution_count": 10 - }, - { - "cell_type": "code", - "metadata": { + "end_time": "2025-11-12T08:10:56.559652Z", + "start_time": "2025-11-12T08:10:56.550372Z" + }, "colab": { "base_uri": "https://localhost:8080/", "height": 388 }, "id": "S7voZG_T9ny-", - "outputId": "de26041a-af6d-4554-eb32-1eb9d57d5f3e", - "ExecuteTime": { - "end_time": "2025-11-12T08:10:56.559652Z", - "start_time": "2025-11-12T08:10:56.550372Z" - } + "outputId": "de26041a-af6d-4554-eb32-1eb9d57d5f3e" }, + "outputs": [], "source": [ - "prices = ohlc[\"Close\"].dropna(how=\"all\")\n", - "prices.tail()" - ], - "outputs": [ - { - "data": { - "text/plain": [ - "Ticker ACN AMZN COST DIS F \\\n", - "Date \n", - "2025-11-05 247.820007 250.199997 935.030029 111.360001 12.960114 \n", - "2025-11-06 241.339996 243.039993 923.580017 110.489998 12.969999 \n", - "2025-11-07 245.759995 244.410004 922.739990 110.739998 13.210000 \n", - "2025-11-10 244.550003 248.399994 915.559998 112.239998 13.160000 \n", - "2025-11-11 242.559998 249.100006 913.859985 114.849998 13.300000 \n", - "\n", - "Ticker GILD JPM KO LUV MA \\\n", - "Date \n", - "2025-11-05 122.580002 311.679993 68.510002 31.620001 553.309998 \n", - "2025-11-06 123.400002 313.420013 69.059998 31.510000 553.280029 \n", - "2025-11-07 118.839996 314.209991 70.550003 32.450001 551.969971 \n", - "2025-11-10 118.150002 316.890015 70.519997 32.660000 552.960022 \n", - "2025-11-11 122.559998 315.619995 71.610001 31.990000 558.349976 \n", - "\n", - "Ticker MSFT PFE TSLA UNH XOM \n", - "Date \n", - "2025-11-05 507.160004 24.184153 462.070007 327.739990 113.680000 \n", - "2025-11-06 497.100006 24.420000 445.910004 321.559998 114.500000 \n", - "2025-11-07 496.820007 24.430000 429.519989 324.209991 117.220001 \n", - "2025-11-10 506.000000 24.389999 445.230011 321.579987 118.220001 \n", - "2025-11-11 508.679993 25.510000 439.619995 327.450012 119.779999 " - ], - "text/html": [ - "
| Ticker | \n", - "ACN | \n", - "AMZN | \n", - "COST | \n", - "DIS | \n", - "F | \n", - "GILD | \n", - "JPM | \n", - "KO | \n", - "LUV | \n", - "MA | \n", - "MSFT | \n", - "PFE | \n", - "TSLA | \n", - "UNH | \n", - "XOM | \n", - "
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Date | \n", - "\n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " | \n", - " |
| 2025-11-05 | \n", - "247.820007 | \n", - "250.199997 | \n", - "935.030029 | \n", - "111.360001 | \n", - "12.960114 | \n", - "122.580002 | \n", - "311.679993 | \n", - "68.510002 | \n", - "31.620001 | \n", - "553.309998 | \n", - "507.160004 | \n", - "24.184153 | \n", - "462.070007 | \n", - "327.739990 | \n", - "113.680000 | \n", - "
| 2025-11-06 | \n", - "241.339996 | \n", - "243.039993 | \n", - "923.580017 | \n", - "110.489998 | \n", - "12.969999 | \n", - "123.400002 | \n", - "313.420013 | \n", - "69.059998 | \n", - "31.510000 | \n", - "553.280029 | \n", - "497.100006 | \n", - "24.420000 | \n", - "445.910004 | \n", - "321.559998 | \n", - "114.500000 | \n", - "
| 2025-11-07 | \n", - "245.759995 | \n", - "244.410004 | \n", - "922.739990 | \n", - "110.739998 | \n", - "13.210000 | \n", - "118.839996 | \n", - "314.209991 | \n", - "70.550003 | \n", - "32.450001 | \n", - "551.969971 | \n", - "496.820007 | \n", - "24.430000 | \n", - "429.519989 | \n", - "324.209991 | \n", - "117.220001 | \n", - "
| 2025-11-10 | \n", - "244.550003 | \n", - "248.399994 | \n", - "915.559998 | \n", - "112.239998 | \n", - "13.160000 | \n", - "118.150002 | \n", - "316.890015 | \n", - "70.519997 | \n", - "32.660000 | \n", - "552.960022 | \n", - "506.000000 | \n", - "24.389999 | \n", - "445.230011 | \n", - "321.579987 | \n", - "118.220001 | \n", - "
| 2025-11-11 | \n", - "242.559998 | \n", - "249.100006 | \n", - "913.859985 | \n", - "114.849998 | \n", - "13.300000 | \n", - "122.559998 | \n", - "315.619995 | \n", - "71.610001 | \n", - "31.990000 | \n", - "558.349976 | \n", - "508.679993 | \n", - "25.510000 | \n", - "439.619995 | \n", - "327.450012 | \n", - "119.779999 | \n", - "
90&&i.log(\"Long binary search...\"),f-1},e.sorterAsc=function(t,e){return t-e},e.sorterDes=function(t,e){return e-t},e.distinctVals=function(t){var r,n=t.slice();for(n.sort(e.sorterAsc),r=n.length-1;r>-1&&n[r]===o;r--);for(var i,a=n[r]-n[0]||1,s=a/(r||1)/1e4,l=[],c=0;c<=r;c++){var u=n[c],h=u-i;void 0===i?(l.push(u),i=u):h>s&&(a=Math.min(a,h),l.push(u),i=u)}return{vals:l,minDiff:a}},e.roundUp=function(t,e,r){for(var n,i=0,a=e.length-1,o=0,s=r?0:1,l=r?1:0,c=r?Math.ceil:Math.floor;i0&&(n=1),r&&n)return t.sort(e)}return n?t:t.reverse()},e.findIndexOfMin=function(t,e){e=e||a;for(var r,n=1/0,i=0;i
/i;e.BR_TAG_ALL=/
/gi;var b=/(^|[\\s\"'])style\\s*=\\s*(\"([^\"]*);?\"|'([^']*);?')/i,w=/(^|[\\s\"'])href\\s*=\\s*(\"([^\"]*)\"|'([^']*)')/i,T=/(^|[\\s\"'])target\\s*=\\s*(\"([^\"\\s]*)\"|'([^'\\s]*)')/i,k=/(^|[\\s\"'])popup\\s*=\\s*(\"([\\w=,]*)\"|'([\\w=,]*)')/i;function A(t,e){if(!t)return null;var r=t.match(e),n=r&&(r[3]||r[4]);return n&&C(n)}var M=/(^|;)\\s*color:/;e.plainText=function(t,e){for(var r=void 0!==(e=e||{}).len&&-1!==e.len?e.len:1/0,n=void 0!==e.allowedTags?e.allowedTags:[\"br\"],i=t.split(v),a=[],o=\"\",s=0,l=0;l
\"+l;e.text=c}(t,o,r,c):\"log\"===u?function(t,e,r,n,a){var o=t.dtick,l=e.x,c=t.tickformat,u=\"string\"==typeof o&&o.charAt(0);if(\"never\"===a&&(a=\"\"),n&&\"L\"!==u&&(o=\"L3\",u=\"L\"),c||\"L\"===u)e.text=wt(Math.pow(10,l),t,a,n);else if(i(o)||\"D\"===u&&s.mod(l+.01,1)<.1){var h=Math.round(l),f=Math.abs(h),p=t.exponentformat;\"power\"===p||_t(p)&&bt(h)?(e.text=0===h?1:1===h?\"10\":\"10\"+(h>1?\"\":z)+f+\"\",e.fontSize*=1.25):(\"e\"===p||\"E\"===p)&&f>2?e.text=\"1\"+p+(h>0?\"+\":z)+f:(e.text=wt(Math.pow(10,l),t,\"\",\"fakehover\"),\"D1\"===o&&\"y\"===t._id.charAt(0)&&(e.dy-=e.fontSize/6))}else{if(\"D\"!==u)throw\"unrecognized dtick \"+String(o);e.text=String(Math.round(Math.pow(10,s.mod(l,1)))),e.fontSize*=.75}if(\"D1\"===t.dtick){var d=String(e.text).charAt(0);\"0\"!==d&&\"1\"!==d||(\"y\"===t._id.charAt(0)?e.dx-=e.fontSize/4:(e.dy+=e.fontSize/2,e.dx+=(t.range[1]>t.range[0]?1:-1)*e.fontSize*(l<0?.5:.25)))}}(t,o,0,c,g):\"category\"===u?function(t,e){var r=t._categories[Math.round(e.x)];void 0===r&&(r=\"\"),e.text=String(r)}(t,o):\"multicategory\"===u?function(t,e,r){var n=Math.round(e.x),i=t._categories[n]||[],a=void 0===i[1]?\"\":String(i[1]),o=void 0===i[0]?\"\":String(i[0]);r?e.text=o+\" - \"+a:(e.text=a,e.text2=o)}(t,o,r):Rt(t)?function(t,e,r,n,i){if(\"radians\"!==t.thetaunit||r)e.text=wt(e.x,t,i,n);else{var a=e.x/180;if(0===a)e.text=\"0\";else{var o=function(t){function e(t,e){return Math.abs(t-e)<=1e-6}var r=function(t){for(var r=1;!e(Math.round(t*r)/r,t);)r*=10;return r}(t),n=t*r,i=Math.abs(function t(r,n){return e(n,0)?r:t(n,r%n)}(n,r));return[Math.round(n/i),Math.round(r/i)]}(a);if(o[1]>=100)e.text=wt(s.deg2rad(e.x),t,i,n);else{var l=e.x<0;1===o[1]?1===o[0]?e.text=\"π\":e.text=o[0]+\"π\":e.text=[\"\",o[0],\"\",\"⁄\",\"\",o[1],\"\",\"π\"].join(\"\"),l&&(e.text=z+e.text)}}}}(t,o,r,c,g):function(t,e,r,n,i){\"never\"===i?i=\"\":\"all\"===t.showexponent&&Math.abs(e.x/t.dtick)<1e-6&&(i=\"hide\"),e.text=wt(e.x,t,i,n)}(t,o,0,c,g),n||(t.tickprefix&&!m(t.showtickprefix)&&(o.text=t.tickprefix+o.text),t.ticksuffix&&!m(t.showticksuffix)&&(o.text+=t.ticksuffix)),t.labelalias&&t.labelalias.hasOwnProperty(o.text)){var y=t.labelalias[o.text];\"string\"==typeof y&&(o.text=y)}return(\"boundaries\"===t.tickson||t.showdividers)&&(o.xbnd=[f(o.x-.5),f(o.x+t.dtick-.5)]),o},Z.hoverLabelText=function(t,e,r){r&&(t=s.extendFlat({},t,{hoverformat:r}));var n=s.isArrayOrTypedArray(e)?e[0]:e,i=s.isArrayOrTypedArray(e)?e[1]:void 0;if(void 0!==i&&i!==n)return Z.hoverLabelText(t,n,r)+\" - \"+Z.hoverLabelText(t,i,r);var a=\"log\"===t.type&&n<=0,o=Z.tickText(t,t.c2l(a?-n:n),\"hover\").text;return a?0===n?\"0\":z+o:o};var xt=[\"f\",\"p\",\"n\",\"μ\",\"m\",\"\",\"k\",\"M\",\"G\",\"T\"];function _t(t){return\"SI\"===t||\"B\"===t}function bt(t){return t>14||t<-15}function wt(t,e,r,n){var a=t<0,o=e._tickround,l=r||e.exponentformat||\"B\",c=e._tickexponent,u=Z.getTickFormat(e),h=e.separatethousands;if(n){var f={exponentformat:l,minexponent:e.minexponent,dtick:\"none\"===e.showexponent?e.dtick:i(t)&&Math.abs(t)||1,range:\"none\"===e.showexponent?e.range.map(e.r2d):[0,t||1]};yt(f),o=(Number(f._tickround)||0)+4,c=f._tickexponent,e.hoverformat&&(u=e.hoverformat)}if(u)return e._numFormat(u)(t).replace(/-/g,z);var p,d=Math.pow(10,-o)/2;if(\"none\"===l&&(c=0),(t=Math.abs(t))
\")):x=f.textLabel;var C={x:f.traceCoordinate[0],y:f.traceCoordinate[1],z:f.traceCoordinate[2],data:b._input,fullData:b,curveNumber:b.index,pointNumber:T};d.appendArrayPointValue(C,b,T),t._module.eventData&&(C=b._module.eventData(C,f,b,{},T));var L={points:[C]};if(e.fullSceneLayout.hovermode){var I=[];d.loneHover({trace:b,x:(.5+.5*v[0]/v[3])*s,y:(.5-.5*v[1]/v[3])*l,xLabel:k.xLabel,yLabel:k.yLabel,zLabel:k.zLabel,text:x,name:u.name,color:d.castHoverOption(b,T,\"bgcolor\")||u.color,borderColor:d.castHoverOption(b,T,\"bordercolor\"),fontFamily:d.castHoverOption(b,T,\"font.family\"),fontSize:d.castHoverOption(b,T,\"font.size\"),fontColor:d.castHoverOption(b,T,\"font.color\"),nameLength:d.castHoverOption(b,T,\"namelength\"),textAlign:d.castHoverOption(b,T,\"align\"),hovertemplate:h.castOption(b,T,\"hovertemplate\"),hovertemplateLabels:h.extendFlat({},C,k),eventData:[C]},{container:n,gd:r,inOut_bbox:I}),C.bbox=I[0]}f.distance<5&&(f.buttons||w)?r.emit(\"plotly_click\",L):r.emit(\"plotly_hover\",L),this.oldEventData=L}else d.loneUnhover(n),this.oldEventData&&r.emit(\"plotly_unhover\",this.oldEventData),this.oldEventData=void 0;e.drawAnnotations(e)},k.recoverContext=function(){var t=this;t.glplot.dispose();var e=function(){t.glplot.gl.isContextLost()?requestAnimationFrame(e):t.initializeGLPlot()?t.plot.apply(t,t.plotArgs):h.error(\"Catastrophic and unrecoverable WebGL error. Context lost.\")};requestAnimationFrame(e)};var M=[\"xaxis\",\"yaxis\",\"zaxis\"];function S(t,e,r){for(var n=t.fullSceneLayout,i=0;i<3;i++){var a=M[i],o=a.charAt(0),s=n[a],l=e[o],c=e[o+\"calendar\"],u=e[\"_\"+o+\"length\"];if(h.isArrayOrTypedArray(l))for(var f,p=0;p<(u||l.length);p++)if(h.isArrayOrTypedArray(l[p]))for(var d=0;d
\");y.text(_).attr(\"data-unformatted\",_).call(u.convertToTspans,t),v=c.bBox(y.node())}y.attr(\"transform\",i(-3,8-v.height)),g.insert(\"rect\",\".static-attribution\").attr({x:-v.width-6,y:-v.height-3,width:v.width+6,height:v.height+3,fill:\"rgba(255, 255, 255, 0.75)\"});var b=1;v.width+6>x&&(b=x/(v.width+6));var w=[n.l+n.w*p.x[1],n.t+n.h*(1-p.y[0])];g.attr(\"transform\",i(w[0],w[1])+a(b))}},e.updateFx=function(t){for(var e=t._fullLayout,r=e._subplots[f],n=0;n
\");_.text(T).attr(\"data-unformatted\",T).call(h.convertToTspans,t),b=u.bBox(_.node())}_.attr(\"transform\",a(-3,8-b.height)),x.insert(\"rect\",\".static-attribution\").attr({x:-b.width-6,y:-b.height-3,width:b.width+6,height:b.height+3,fill:\"rgba(255, 255, 255, 0.75)\"});var k=1;b.width+6>w&&(k=w/(b.width+6));var A=[n.l+n.w*f.x[1],n.t+n.h*(1-f.y[0])];x.attr(\"transform\",a(A[0],A[1])+o(k))}},e.updateFx=function(t){for(var e=t._fullLayout,r=e._subplots[p],n=0;n