diff --git a/.github/workflows/action_python.yaml b/.github/workflows/action_python.yaml index 2a1e1f8b..b85e3c61 100644 --- a/.github/workflows/action_python.yaml +++ b/.github/workflows/action_python.yaml @@ -29,11 +29,10 @@ jobs: uses: actions/setup-python@v4 with: python-version: '3.10' + cache: 'poetry' - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install . - pip install .[dev] + poetry install - name: Test with pytest run: | pytest --cov=src tests/ --doctest-modules --junitxml=cover/xunit-result.xml --cov-report xml:cover/coverage.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 758822b9..ad1d87d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -6,12 +6,12 @@ repos: rev: 0.6.1 hooks: - id: nbstripout - - repo: https://github.com/cmhughes/latexindent.pl.git - rev: V3.19.1 - hooks: - - id: latexindent + # - repo: https://github.com/cmhughes/latexindent.pl.git + # rev: V3.19.1 + # hooks: + # - id: latexindent - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.5.0 hooks: - id: trailing-whitespace - id: check-added-large-files @@ -26,7 +26,7 @@ repos: - id: mixed-line-ending - id: trailing-whitespace - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.991 + rev: v1.6.1 hooks: - id: mypy # yaml requires additional stubs. diff --git a/notebooks/3.0a-mb-explanatory-data-analysis.ipynb b/notebooks/3.0a-mb-explanatory-data-analysis.ipynb index 6814b503..a0e2d981 100644 --- a/notebooks/3.0a-mb-explanatory-data-analysis.ipynb +++ b/notebooks/3.0a-mb-explanatory-data-analysis.ipynb @@ -1,3455 +1,3455 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "EMApm-vLnME4" - }, - "outputs": [], - "source": [ - "from __future__ import annotations\n", - "\n", - "import os\n", - "import random\n", - "import warnings\n", - "\n", - "import dateutil.relativedelta as relativedelta\n", - "\n", - "warnings.simplefilter(action=\"ignore\", category=FutureWarning)\n", - "\n", - "from typing import Any, List\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import pandas as pd\n", - "import pandas_datareader.data as web\n", - "import seaborn as sns\n", - "from scipy import stats\n", - "from scipy.cluster import hierarchy\n", - "from sklearn.manifold import TSNE\n", - "from sklearn.preprocessing import StandardScaler" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "BRFyckmGEHXL" - }, - "outputs": [], - "source": [ - "# set N used in n-largest or smallest\n", - "N = 10\n", - "\n", - "# set style\n", - "plt.style.use(\"seaborn-notebook\")\n", - "\n", - "# set ratio of figure\n", - "ratio = (16, 9)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "a-f2aByNtJTK" - }, - "outputs": [], - "source": [ - "# set fixed seed\n", - "def seed_everything(seed) -> None:\n", - " \"\"\"\n", - " Seeds basic parameters for reproducibility of results.\n", - " \"\"\"\n", - " os.environ[\"PYTHONHASHSEED\"] = str(seed)\n", - " random.seed(seed)\n", - " # pandas and numpy as discussed here: https://stackoverflow.com/a/52375474/5755604\n", - " np.random.seed(seed)\n", - "\n", - "\n", - "seed = 42\n", - "seed_everything(seed)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "9MOW2bJSmY8x" - }, - "source": [ - "This notebook performs an eda on the training set only to avoid data leakage. ⚠️" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "EF0_Mz8DYjGz" - }, - "outputs": [], - "source": [ - "data = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/train_set_extended_60.parquet\"\n", - ").sample(frac=0.1, axis=0, random_state=seed)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "NDz5ZzVl_QGD" - }, - "source": [ - "## Notes on data set πŸ—ƒοΈ" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "yAWnmnei39o5" - }, - "source": [ - "**Overview on ticker symbols:**\n", - "- `others` identified by issue type.\n", - "- 5th letter has a special meaning as found in [this table](https://en.wikipedia.org/wiki/Ticker_symbol):\n", - "\n", - "| Letter | Letter contd. | Letter contd. |\n", - "|--------------------------------|-------------------------------------|------------------------------------------------|\n", - "| A – Class \"A\" | K – Nonvoting (common) | U – Units |\n", - "| B – Class \"B\" | L – Miscellaneous | V – Pending issue and distribution |\n", - "| C – NextShares | M – fourth class – preferred shares | W – Warrants |\n", - "| D – New issue or reverse split | N – third class – preferred shares | X – Mutual fund |\n", - "| E – Delinquent SEC filings | O – second class – preferred shares | Y – American depositary receipt (ADR) |\n", - "| F – Foreign | P – first class preferred shares | Z – Miscellaneous situations |\n", - "| G – first convertible bond | Q – In bankruptcy | Special codes |\n", - "| H – second convertible bond | R – Rights | PK – A Pink Sheet, indicating over-the-counter |\n", - "| I – third convertible bond | S – Shares of beneficial interest | SC – Nasdaq Small Cap |\n", - "| J – Voting share – special | T – With warrants or rights | NM – Nasdaq National Market |\n", - "\n", - "\n", - "**Coverage:**\n", - "\n", - "*\tOptions on U.S. listed Stock, ETFs, and Indices disseminated over the Options Price Reporting Authority (OPRA) market data feed \n", - "*\tGlobal Trading Hours (GTH) trades are included if between 03:00am-09:15am U.S. Eastern, and for the 16:15pm 17:00pm Curb session. GTH trades outside of these time ranges will *not* be included. \n", - "\n", - "Found [here.](https://datashop.cboe.com/documents/Option_Trades_Layout.pdf)\n", - "\n", - "**Exchange Identifier:**\n", - "\n", - "- 5 = Chicago Board Options Exchange (CBOE)\n", - "- 6 = International Securities Exchange (ISE)\n", - "\n", - "Found [here.](https://datashop.cboe.com/documents/livevol_exchange_ids.csv)\n", - "\n", - "\n", - "**Issue Types:**\n", - "\n", - "Issue Type = the type of security: \n", - "- 0 = Common Stock \n", - "- A = Market index \n", - "- 7 = Mutual or investment trust fund \n", - "- F = ADR/ADS \n", - "- % = Exchange-traded fund \n", - "- (blank) = Unspecified\n", - "\n", - "Received from supervisor." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "amt068Np3EFV" - }, - "source": [ - "Adapted from the cboe data shop found at [option trades](https://datashop.cboe.com/documents/Option_Trades_Layout.pdf) and [option quotes](https://datashop.cboe.com/documents/Option_Quotes_Layout.pdf).\n", - "\n", - "| Column Label | Data Type | Description |\n", - "|---------------------------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n", - "| underlying_symbol | string | The underlying stock or index. An index will utilize a caret (^) prefix, i.e. ^NDX,^SPX,^VIX…etc. Underlyings with classes may utilize a dot (.) instead of a slash or space, i.e. BRK.B, RDS.A, RDS.B. |\n", - "| quote_datetime | datetime | The trading date and timestamp of the trade in U.S. Eastern time. Ex: yyyymm-dd hh:mm:ss.000 |\n", - "| sequence_number | integer | Trade Sequence Number for the execution reported by OPRA |\n", - "| root | string | The option trading class symbol. Non-standard roots may end with a digit |\n", - "| expiration | date | The explicit expiration date of the option: yyyy-mm-dd |\n", - "| strike | numeric | The exercise/strike price of the option |\n", - "| option_type | string | C for Call options, P for Put options |\n", - "| exchange_id | integer | An identifier for the options exchange the trade was executed on. For a mapping, please see Exchange ID Mappings |\n", - "| trade_size | integer | The trade quantity |\n", - "| trade_price | numeric | The trade price |\n", - "| trade_condition_id | integer | The trade or sale condition of the execution. For a mapping, please see Trade Condition ID Mapping |\n", - "| canceled_trade_condition_id | integer | This field is no longer supported and will default to 0 (zero). See IDs 40-43 in the Trade Condition ID Mapping file above |\n", - "| best_bid | numeric | The best bid price (NBB) at the time of the trade |\n", - "| best_ask | numeric | The best ask/offer price (NBO) at the time of the trade |\n", - "| bid_size | integer | The largest size from an options exchange participant on the best bid price (NBB) |\n", - "| bid | numeric | The best bid price (NBB) at the interval time stamp |\n", - "| ask_size | integer | The largest size from an options exchange participant on the best offer price (NBO) |\n", - "| ask | numeric | The best offer price (NBO) at the interval time stamp |" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "iQ4euCPwEjW0" - }, - "source": [ - "## Dtypes, distributions, and memory consumption πŸ”­" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 236 - }, - "id": "RO2KMtPiTACz", - "outputId": "f2d1f1a8-0731-4e65-95f7-62f006641f41" - }, - "outputs": [], - "source": [ - "data.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 300 - }, - "id": "aqk_p5ocEjDU", - "outputId": "8b78aa0f-cb00-4d7a-bcb3-a3aa3c1716f6" - }, - "outputs": [], - "source": [ - "data.describe()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "hfQwaYDo6Zqj", - "outputId": "3095bf4b-1098-40f0-da5f-f0a7e210a7c1" - }, - "outputs": [], - "source": [ - "data.info()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "AQALJAsMTElF", - "outputId": "5d3b9d82-83ad-4b74-f9ab-71e211bba302" - }, - "outputs": [], - "source": [ - "print(data.shape)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "_vilf7lRTL9D", - "outputId": "40456f7d-8378-4943-b2b7-bc6c2e28083f" - }, - "outputs": [], - "source": [ - "print(data.shape)\n", - "# drop identical rows, if present\n", - "data.drop_duplicates(inplace=True)\n", - "print(data.shape)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "wyqaDfoVwhGc" - }, - "source": [ - "**Observation:**\n", - "- Shape matches the shape reported in table 1 (panel A) of Grauer et al. paper.\n", - "- No duplicates" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "6iDCXTOo63QM", - "outputId": "fdd237ec-d488-453c-9641-cd1703dd4c27" - }, - "outputs": [], - "source": [ - "data.nunique()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 739 - }, - "id": "l0aNIyjVhU_l", - "outputId": "26c485d7-e8c5-4c48-f211-2dd6e8cf279d" - }, - "outputs": [], - "source": [ - "data.head().T\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "JvmC00M4ggXa" - }, - "source": [ - "## Basic features🧸" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "_mwfnC3c11S3" - }, - "source": [ - "Analysis of numerical features without any feature engineering." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "apYQeTxc_A85" - }, - "source": [ - "### Correlations 🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 430 - }, - "id": "xnCgvNWigo4v", - "outputId": "577879b8-4b4b-48cb-c894-14abb39cbdca" - }, - "outputs": [], - "source": [ - "corr: pd.DataFrame = data.corr()\n", - "sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "zCx-OV5A1nbW" - }, - "source": [ - "**Observation:**\n", - "* There are many highly correlated columns. The correlations are intuitive e. g., between `price_all_lead` and `price_ex_lead`.\n", - "* Few columns show a weak correlation with target (see also below)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "GfS9_g8lLwCk", - "outputId": "069d5158-9b9e-47d8-82d2-ad804883fe32" - }, - "outputs": [], - "source": [ - "sample = data.sample(n=1000, random_state=seed)\n", - "sns.pairplot(\n", - " sample,\n", - " vars=[\n", - " \"STRK_PRC\",\n", - " \"TRADE_SIZE\",\n", - " \"TRADE_PRICE\",\n", - " \"BEST_BID\",\n", - " \"BEST_ASK\",\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"ask_size_ex\",\n", - " \"bid_size_ex\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"day_vol\",\n", - " ],\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "dhBUygocshi6" - }, - "source": [ - "### Correlation with target 🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 582 - }, - "id": "qeid5BACbK4h", - "outputId": "ec4ddbd4-e684-43ce-af4a-ed47242e5409" - }, - "outputs": [], - "source": [ - "sort_criteria = corr[\"buy_sell\"].abs().sort_values(ascending=False)\n", - "corr_target = corr.sort_values(\"buy_sell\", ascending=False)[\"buy_sell\"]\n", - "corr_target.loc[sort_criteria.index].to_frame()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "-0DAc8QweT3x" - }, - "source": [ - "**Observation:**\n", - "* Overall correlations are relatively low. Typical for financial data due to low signal-to-noise ratio.\n", - "* Size-related features like `ask_size_ex` or `bid_size_ex` have the highest correlation with the target. Thus, can be promising to be included in the model. Consider size features when constructing feature sets.\n", - "* Features like `optionid`, `order_id`, and `SEQUENCE_NUMBER` are also among the features with the highest correlations. Remove them, as the correlation is misleading." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "UGdvq8OImPBy" - }, - "outputs": [], - "source": [ - "# remove some columns, which will NOT be used in model\n", - "data.drop(columns=[\"optionid\"], inplace=True)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "jh83FQtksq0p" - }, - "source": [ - "### Collinearity of features 🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "ZXMC40PcnsR1", - "outputId": "e3e6475e-7392-4b6f-d9a4-041225178134" - }, - "outputs": [], - "source": [ - "# adapted from here: https://www.kaggle.com/code/willkoehrsen/featuretools-for-good\n", - "threshold = 0.975\n", - "# Select upper triangle of correlation matrix\n", - "upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))\n", - "\n", - "# Find index of feature columns with correlation greater than 0.975\n", - "to_drop = [column for column in upper.columns if any(abs(upper[column]) > threshold)]\n", - "\n", - "print(to_drop)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "cCy-QCa7whGl" - }, - "source": [ - "**Observation:**\n", - "- Columns suggested for removal are intuitive\n", - "- Do not blindly remove columns, but preserve a pattern or groups" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "HJ1kEvpmpPho" - }, - "outputs": [], - "source": [ - "# Set the threshold\n", - "threshold = 0.975\n", - "\n", - "# Empty dictionary to hold correlated variables\n", - "above_threshold_vars = {}\n", - "\n", - "# For each column, record the variables that are above the threshold\n", - "for col in corr:\n", - " above_threshold_vars[col] = list(corr.index[corr[col] > threshold])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "l151G9vXqPQI", - "outputId": "f6ed1077-2bb0-4c97-c07a-00d927f2d7df" - }, - "outputs": [], - "source": [ - "pd.Series(above_threshold_vars)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "tL1pblZKriNJ" - }, - "source": [ - "**Observations:**\n", - "* Some columns are highly correlated. This is very intuitive.\n", - "* It seems problematic to include both `BEST_BID` and `bid_ex`. This is also true for `BEST_ASK` and `ask_ex`. `price_all_lead` and `price_all_lag` seem to be less problematic.\n", - "* Define feature sets so that the number of highly correlated variables is minimized. But maintain groups so that a comparsion with classical rules is still possible." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "NCtxwwaFY9HS" - }, - "source": [ - "## $t$-SNE\n", - "\n", - "Project data down using [t-SNE](https://lvdmaaten.github.io/tsne/). Also look at [umap algorithm](https://github.com/lmcinnes/umap), which is a similar effort. \n", - "\n", - "This [post](https://distill.pub/2016/misread-tsne/) gives some intuition on the parameters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 236 - }, - "id": "A7NuFKhNijdn", - "outputId": "961ce721-3552-4f58-8cd2-285b61298486" - }, - "outputs": [], - "source": [ - "data.head()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "jQxIPgGun_Ih" - }, - "outputs": [], - "source": [ - "sample = data.select_dtypes(include=np.number).fillna(0).drop(columns=[\"buy_sell\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "1Qm5AT8YY9HS" - }, - "outputs": [], - "source": [ - "tsne = TSNE(\n", - " n_components=2,\n", - " init=\"random\",\n", - " random_state=0,\n", - " perplexity=30,\n", - " learning_rate=\"auto\",\n", - " n_iter=300,\n", - ")\n", - "Y = tsne.fit_transform(sample)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "vdqORozgk0GZ" - }, - "outputs": [], - "source": [ - "dims = pd.DataFrame(Y, columns=[\"x\", \"y\"], index=data.index)\n", - "dims[\"class\"] = data[\"buy_sell\"]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "lCROet2zpKoN" - }, - "outputs": [], - "source": [ - "dims[\"class\"] = data.buy_sell\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 557 - }, - "id": "bv80agonloiS", - "outputId": "d1c49f02-3f00-4440-927e-457671043067" - }, - "outputs": [], - "source": [ - "fig, ax = plt.subplots(1, figsize=ratio)\n", - "scatter = plt.scatter(dims[\"x\"], dims[\"y\"], c=dims[\"class\"], cmap=plt.cm.rainbow)\n", - "plt.setp(ax, xticks=[], yticks=[])\n", - "plt.title(\"t-SNE of dataset\")\n", - "plt.legend(handles=scatter.legend_elements()[0], labels=[\"-1\", \"1\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "4G3EmKH9tfir" - }, - "outputs": [], - "source": [ - "del sample\n", - "del dims\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "knWT_eurs_yl" - }, - "source": [ - "Unfortunately, **no** clear pattern visible." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "KBSJWMKGhFlP" - }, - "source": [ - "## Preparation πŸ₯—" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "P3up1N46inpz" - }, - "source": [ - "### Time features ⏰" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "XACNa17ehnr_" - }, - "outputs": [], - "source": [ - "# apply positional encoding to dates\n", - "data[\"date_month_sin\"] = np.sin(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.month / 12)\n", - "data[\"date_month_cos\"] = np.cos(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.month / 12)\n", - "\n", - "days_in_month = 31 # at max :-)\n", - "data[\"date_day_sin\"] = np.sin(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.day / days_in_month)\n", - "data[\"date_day_cos\"] = np.cos(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.day / days_in_month)\n", - "\n", - "# time (daily)\n", - "seconds_in_day = 24 * 60 * 60\n", - "seconds = (\n", - " data[\"QUOTE_DATETIME\"] - data[\"QUOTE_DATETIME\"].dt.normalize()\n", - ").dt.total_seconds()\n", - "\n", - "data[\"date_time_sin\"] = np.sin(2 * np.pi * seconds / seconds_in_day)\n", - "data[\"date_time_cos\"] = np.cos(2 * np.pi * seconds / seconds_in_day)\n", - "\n", - "# weekday\n", - "days_in_week = 7\n", - "data[\"date_weekday_sin\"] = np.sin(\n", - " 2 * np.pi * data[\"QUOTE_DATETIME\"].dt.dayofweek / days_in_week\n", - ")\n", - "data[\"date_weekday_cos\"] = np.cos(\n", - " 2 * np.pi * data[\"QUOTE_DATETIME\"].dt.dayofweek / days_in_week\n", - ")\n", - "\n", - "# time to maturity\n", - "data[\"ttm\"] = (\n", - " data[\"EXPIRATION\"].dt.to_period(\"M\") - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", - ").apply(lambda x: x.n)\n", - "\n", - "# day, month and year\n", - "data[\"day\"] = data[\"QUOTE_DATETIME\"].dt.day\n", - "data[\"month\"] = data[\"QUOTE_DATETIME\"].dt.month\n", - "data[\"year\"] = data[\"QUOTE_DATETIME\"].dt.year\n", - "data[\"date\"] = data[\"QUOTE_DATETIME\"].dt.date\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "GGWJjuPciwh7" - }, - "source": [ - "### Binned features πŸ₯«" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "W6vEtB7T-KNy" - }, - "source": [ - "Bin features similarily to how they are used in the robustness tests." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "5HML91_Bit9A" - }, - "outputs": [], - "source": [ - "bins_tradesize = [0, 1, 3, 5, 11, np.inf]\n", - "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", - "data[\"TRADE_SIZE_binned\"] = pd.cut(\n", - " data[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", - ")\n", - "\n", - "bins_years = [2004, 2007, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]\n", - "year_labels = [\n", - " \"2005-2007\",\n", - " \"2008-2010\",\n", - " \"2011\",\n", - " \"2012\",\n", - " \"2013\",\n", - " \"2014\",\n", - " \"2015\",\n", - " \"2016\",\n", - " \"2017\",\n", - "]\n", - "data[\"year_binned\"] = pd.cut(data[\"year\"], bins_years, labels=year_labels)\n", - "\n", - "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", - "ttm_labels = [\n", - " \"ttm <= 1 month\",\n", - " \"ttm (1-2] month\",\n", - " \"ttm (2-3] month\",\n", - " \"ttm (3-6] month\",\n", - " \"ttm (6-12] month\",\n", - " \"ttm > 12 month\",\n", - "]\n", - "data[\"ttm_binned\"] = pd.cut(data[\"ttm\"], bins_ttm, labels=ttm_labels)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fNul91d8XCzv" - }, - "source": [ - "### Trade features πŸ’΄\n", - "Construct features that are used in classical rules." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "B4CnoIjyWDo1" - }, - "outputs": [], - "source": [ - "# Calculate change similar to (reverse) tick rule\n", - "data[\"chg_ex_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lead\"]\n", - "data[\"chg_ex_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lag\"]\n", - "data[\"chg_all_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lead\"]\n", - "data[\"chg_all_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lag\"]\n", - "\n", - "# Midspread\n", - "mid_ex = 0.5 * (data[\"ask_ex\"] + data[\"bid_ex\"])\n", - "mid_best = 0.5 * (data[\"BEST_ASK\"] + data[\"BEST_BID\"])\n", - "data[\"mid_ex\"] = mid_ex\n", - "data[\"mid_best\"] = mid_best\n", - "\n", - "# spread (abs)\n", - "spread_ex = data[\"ask_ex\"] - data[\"bid_ex\"]\n", - "spread_best = data[\"BEST_ASK\"] - data[\"BEST_BID\"]\n", - "\n", - "# depth rule (usually only applied to mid spread transactions)\n", - "data[\"bid_ask_size_ratio_ex\"] = data[\"bid_size_ex\"] / data[\"ask_size_ex\"]\n", - "\n", - "# Degree how much trade size is filled -> similar to trade size rule\n", - "# Trade size rule would just classify if\n", - "data[\"rel_bid_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"bid_size_ex\"]\n", - "data[\"rel_ask_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"ask_size_ex\"]\n", - "\n", - "# EMO / CLNV / quote rule\n", - "data[\"prox_ex\"] = (data[\"TRADE_PRICE\"] - mid_ex) / (0.5 * spread_ex)\n", - "data[\"prox_best\"] = (data[\"TRADE_PRICE\"] - mid_best) / (0.5 * spread_best)\n", - "\n", - "# custom\n", - "data[\"price_rel_nbo\"] = (data[\"TRADE_PRICE\"] - data[\"BEST_ASK\"]) / (\n", - " data[\"BEST_ASK\"] - mid_best\n", - ")\n", - "data[\"price_rel_nbb\"] = (data[\"TRADE_PRICE\"] - data[\"BEST_BID\"]) / (\n", - " mid_best - data[\"BEST_BID\"]\n", - ")\n", - "data[\"bid_ask_ratio_ex\"] = data[\"bid_ex\"] / data[\"ask_ex\"]\n", - "data[\"depth_ex\"] = data[\"bid_size_ex\"] - data[\"ask_size_ex\"]\n", - "\n", - "data[\"abs_mid_ex\"] = data[\"TRADE_PRICE\"] - mid_ex\n", - "data[\"abs_mid_BEST\"] = data[\"TRADE_PRICE\"] - mid_best\n", - "\n", - "data[\"spread_ex\"] = spread_ex\n", - "data[\"spread_best\"] = spread_best\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "M6gxVMmgNwQs" - }, - "source": [ - "### Underlying features πŸ«€" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "PaBwUMFzNsnu" - }, - "outputs": [], - "source": [ - "data[\"symbol_is_index\"] = data[\"ROOT\"].str.startswith(\"^\").astype(int)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 236 - }, - "id": "dWCeS44oY9Hj", - "outputId": "38f6ccc8-9606-40b2-cfda-40bab25d4152" - }, - "outputs": [], - "source": [ - "data.head()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "A0KFTHrDK5Uo" - }, - "source": [ - "### Categorical features 🎰" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "l4ZbZXdlKbRT" - }, - "source": [ - "### Visualization helper 🐜" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "_jLvcBEyKfDi" - }, - "outputs": [], - "source": [ - "def plot_kde_target(var_name: str, clip: List[float] | None = None):\n", - " \"\"\"\n", - " Plot kde plots for buys (+1) and sells (-1) with regard to the feature 'var_name'.\n", - "\n", - " Args:\n", - " var_name (str): name of feature\n", - " clip (List[float] | None, optional): clipping range. Defaults to None.\n", - " \"\"\"\n", - " corr_var = data[\"buy_sell\"].corr(data[var_name])\n", - "\n", - " median_sell = data[data[\"buy_sell\"] == -1][var_name].median()\n", - " median_buy = data[data[\"buy_sell\"] == 1][var_name].median()\n", - "\n", - " _, ax = plt.subplots()\n", - " for i in [-1, 1]:\n", - " sns.kdeplot(\n", - " data=data[data[\"buy_sell\"] == i],\n", - " x=var_name,\n", - " clip=clip,\n", - " label=str(i),\n", - " cumulative=False,\n", - " common_grid=True,\n", - " )\n", - " ax.title.set_text(f\"Distribution of '{var_name}'\")\n", - " ax.legend()\n", - " sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n", - " plt.show()\n", - " print(\n", - " f\"The correlation between '{var_name}' and the 'buy_sell' is {corr_var: 0.4f}\"\n", - " )\n", - " print(f\"Median value of sells = {median_sell: 0.4f}\")\n", - " print(f\"Median value of buys = {median_buy: 0.4f}\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "kmkh8Ze7Xys_" - }, - "outputs": [], - "source": [ - "def plot_kde_target_comparsion(\n", - " var_name: str,\n", - " clip: float | None = None,\n", - " years: List[int] = [2006, 2010, 2013],\n", - ") -> None:\n", - " \"\"\"\n", - " Plot several kde plots side by side for the feature.\n", - "\n", - " Args:\n", - " var_name (str): name of the feature\n", - " clip (float | None, optional): clipping range. Defaults to None.\n", - " years (List[int], optional): years to compare. Defaults to [2006, 2010, 2013].\n", - " \"\"\"\n", - " fig, ax = plt.subplots(nrows=1, ncols=len(years), figsize=(18, 4))\n", - "\n", - " fig.suptitle(f\"Distribution of `{var_name}`\")\n", - "\n", - " for y, year in enumerate(years):\n", - " for i in [-1, 1]:\n", - " sns.kdeplot(\n", - " data=data[(data[\"buy_sell\"] == i) & (data[\"year\"] == year)],\n", - " x=var_name,\n", - " clip=clip,\n", - " # supress any other but first label using '_'\n", - " # see https://stackoverflow.com/a/44633022/5755604\n", - " label=\"_\" * y + str(i),\n", - " cumulative=False,\n", - " common_grid=True,\n", - " ax=ax[y],\n", - " )\n", - " ax[y].xaxis.label.set_text(str(year))\n", - "\n", - " fig.legend()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "k9QXRQrxOCJ3" - }, - "outputs": [], - "source": [ - "us_rec = web.DataReader(\"USREC\", \"fred\", data[\"date\"].min(), data[\"date\"].max())\n", - "\n", - "\n", - "def plot_recessions() -> None:\n", - " \"\"\"\n", - " Add recession indicator to plot and entry to legend.\n", - " \"\"\"\n", - " l = 0\n", - " month = relativedelta.relativedelta(months=+1)\n", - " for date, val in us_rec[\"USREC\"].items():\n", - " if val == 1:\n", - " # if boolean = 1 -> print bar until next month\n", - " # '_' labels are ignored in legend https://stackoverflow.com/a/44633022/5755604\n", - " plt.axvspan(\n", - " date,\n", - " date + month,\n", - " edgecolor=\"none\",\n", - " alpha=0.25,\n", - " label=\"_\" * l + \"recession\",\n", - " )\n", - " l += 1\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "HHFM5-flQo-9" - }, - "outputs": [], - "source": [ - "def plot_time_series(\n", - " feature: str | List[str], aggregation: str | List[Any] = \"count\"\n", - ") -> pd.DataFrame:\n", - " \"\"\"\n", - " Plot feature over time. Aggregate using 'aggregation'.\n", - "\n", - " Args:\n", - " feature (str | List[str]): features to plot.\n", - " aggregation (str | List[Any], optional): aggregation operation. Defaults to \"count\".\n", - "\n", - " Returns:\n", - " pd.DataFrame: time series\n", - " \"\"\"\n", - " if isinstance(feature, str):\n", - " feature = [feature]\n", - " if isinstance(aggregation, str):\n", - " aggregation = [aggregation]\n", - "\n", - " time_series = data[feature].groupby(data[\"date\"]).agg(aggregation)\n", - " time_series.columns = time_series.columns.to_flat_index()\n", - "\n", - " ax = sns.lineplot(data=time_series)\n", - " ax.yaxis.label.set_text(\" / \".join(aggregation))\n", - " ax.title.set_text(f\"'{' / '.join(feature)}' over time\")\n", - " plot_recessions()\n", - " ax.legend()\n", - " plt.show()\n", - "\n", - " return time_series\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "6rbpLrGVKlqY", - "outputId": "1a470d5b-be8d-417c-a779-15778e71cbf4" - }, - "outputs": [], - "source": [ - "# select categorical e. g., option type and strings e. g., ticker\n", - "cat_columns = data.select_dtypes(include=[\"category\", \"object\"]).columns.tolist()\n", - "print(cat_columns)\n", - "\n", - "# assign \"bin_\" column prefix\n", - "cat_columns_bin = [\"bin_\" + x for x in cat_columns]\n", - "\n", - "# binarize categorical similar to Borisov et al.\n", - "data[cat_columns_bin] = data[cat_columns].apply(lambda x: pd.factorize(x)[0]) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "9vmqZlzAPHLF" - }, - "source": [ - "## General overview πŸŒ„" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ryHukUSOiFvs" - }, - "source": [ - "### Trade price and sizes 🀝" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "TGlJU8wrm_J4" - }, - "source": [ - "#### Trades over time ⌚" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "CNdxNP8VnJ8m", - "outputId": "ec1aecfd-2817-4ed4-dce1-775d44d5b325" - }, - "outputs": [], - "source": [ - "trades_per_day = plot_time_series(\"TRADE_PRICE\", \"count\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "C5GRI4vE08RB", - "outputId": "857d0e7b-6d45-4811-c15f-07679580b616" - }, - "outputs": [], - "source": [ - "trades_per_day.iloc[:, 0].nlargest(N)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "DmK1pdA63P55", - "outputId": "db1f51cc-75e9-41da-8fd3-483bdf75ee07" - }, - "outputs": [], - "source": [ - "trades_per_day.iloc[:, 0].nsmallest(N)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "u4rLQllo9yWs" - }, - "source": [ - "**Observation:**\n", - "* Number of trades increases over time.\n", - "* There is no obvious explanation why the number of trades spikes at certain days." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "YvBsMmZ0Rwro" - }, - "source": [ - "#### Trade size" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "f-YPNDG3fzDO", - "outputId": "adb9ba84-973c-4db9-f90a-5c0c56642d15" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"TRADE_SIZE\", bins=50) \n", - "ax.title.set_text(\"Histogram of trade size\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "txa7AqLShrZn" - }, - "source": [ - "**Observation:**\n", - "* highly skewed with few outliers.\n", - "* Similar to the price, $\\log(\\cdot)$ transform could help." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "3oGv6NbNZ8mR", - "outputId": "c4cb8988-e100-4499-a278-934ea968eeb2" - }, - "outputs": [], - "source": [ - "trades_over_time = plot_time_series(\"TRADE_SIZE\", [\"mean\", \"median\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "_fm0mKy9nGWr", - "outputId": "aa8b4cb6-eda1-4d48-8213-be05f6e3debe" - }, - "outputs": [], - "source": [ - "trade_ask_bid_size = plot_time_series(\n", - " [\"TRADE_SIZE\", \"ask_size_ex\", \"bid_size_ex\"], \"mean\"\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "IKBxGSqe-FBC" - }, - "source": [ - "**Observation:**\n", - "* There is a slow downward trend in `TRADE_SIZE` (mean).\n", - "* Controversely, the number of trades per day (mean) increases over time.\n", - "* Market share of ISE has decrease over time, as reported in https://www.sifma.org/wp-content/uploads/2022/03/SIFMA-Insights-Market-Structure-Compendium-March-2022.pdf. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "PfPmlqkdhhiQ", - "outputId": "21cc85d6-6f43-4e66-a4b1-c76a8839da50" - }, - "outputs": [], - "source": [ - "data[\"TRADE_SIZE\"].describe()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 110 - }, - "id": "dmKu4OXF-p9P", - "outputId": "cc65a9b2-552a-43c8-8df6-eb3597916f40" - }, - "outputs": [], - "source": [ - "data[data[\"TRADE_SIZE\"].max() == data[\"TRADE_SIZE\"]]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 424 - }, - "id": "ZL3iVg-mgrv1", - "outputId": "97444ae1-612f-4be5-c17a-c91576e8b27f" - }, - "outputs": [], - "source": [ - "data.nlargest(N, \"TRADE_SIZE\", keep=\"first\").T\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "eL3Lxj2yhrB4", - "outputId": "e7b356fb-afaa-4424-af70-4d2edda48726" - }, - "outputs": [], - "source": [ - "data[\"log_trade_size\"] = np.log1p(data[\"TRADE_SIZE\"])\n", - "ax = sns.histplot(data, x=\"log_trade_size\", bins=50) \n", - "ax.title.set_text(f\"Histogram of trade size (log1p)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "BQGC_grZ2quQ", - "outputId": "b73c0027-f7d8-4e19-b8b0-1569b010323d" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_trade_size\", clip=[0, 6])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0TbVsjVrwhG_" - }, - "source": [ - "**Observation:**\n", - "- Size features do hardly profit from a $\\log$ transform. Might want to keep as-is." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "kro_boa2VSpD" - }, - "source": [ - "#### Trade price" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "c2bA2XcPg0qg", - "outputId": "bfaa6076-a60b-41f5-dabd-9df36dc53404" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"TRADE_PRICE\", bins=50) \n", - "ax.title.set_text(\"Histogram of trade price\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "CULpt3OGoMBS", - "outputId": "25a6a024-47e6-4025-bbc8-d3d318365673" - }, - "outputs": [], - "source": [ - "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"TRADE_PRICE\")\n", - "ax.title.set_text(\"Box plot of 'TRADE_PRICE' for buys (1) and sells (-1)\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nKm00we7oQmJ" - }, - "source": [ - "**Observations:**\n", - "* Very few, very large trade prices, many very small trade prices.\n", - "* Scaling can be problematic, if outliers affect scaling much. Try $\\log(\\cdot)$ transform to correct skewness of distribution. Could improve results.\n", - "* Trade price is hardly informative, as distribution is very similar." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "k47VwHkJoYHj" - }, - "outputs": [], - "source": [ - "data[\"log_trade_price\"] = np.log1p(data[\"TRADE_PRICE\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 398 - }, - "id": "cULJ2a5voezf", - "outputId": "fff08c96-14cb-4031-a6be-900624f406f2" - }, - "outputs": [], - "source": [ - "fig, ax = plt.subplots()\n", - "\n", - "sns.histplot(data, x=\"log_trade_price\", bins=50, stat=\"density\", label=\"log price\") \n", - "\n", - "# extract the limits for the x-axis and fit normal distributon\n", - "x0, x1 = ax.get_xlim()\n", - "x_pdf = np.linspace(x0, x1, 100)\n", - "y_pdf = stats.norm.pdf(x_pdf)\n", - "\n", - "pdf = pd.DataFrame({\"x\": x_pdf, \"y\": y_pdf})\n", - "sns.lineplot(data=pdf, x=\"x\", y=\"y\", label=\"pdf\", color=\"r\")\n", - "\n", - "\n", - "ax.title.set_text(\"Distribution of log prices\")\n", - "ax.legend()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "9DpqVxM3o8G8", - "outputId": "b9ad92e2-da89-4dfc-9a67-98aa8b5440b4" - }, - "outputs": [], - "source": [ - "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"log_trade_price\")\n", - "ax.title.set_text(\"Box plot of log prices for buys (1) and sells (-1)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 424 - }, - "id": "lwtkIErXg8iZ", - "outputId": "b9a4e4c9-3e4f-496d-fac9-a5b5c22e36f4" - }, - "outputs": [], - "source": [ - "data.nlargest(N, \"TRADE_PRICE\", keep=\"first\").T\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "5HndBdq-hKmJ", - "outputId": "2f721ab4-3827-441b-ca08-6c627a4b457d" - }, - "outputs": [], - "source": [ - "trade_price_over_time = plot_time_series(\"TRADE_PRICE\", [\"mean\", \"median\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "DhvRYVA-pjzX", - "outputId": "86cf5bfa-9a17-4481-a346-e1d8bbda25f4" - }, - "outputs": [], - "source": [ - "trade_price_over_time = plot_time_series(\n", - " [\"TRADE_PRICE\", \"price_ex_lead\", \"price_ex_lag\"], \"mean\"\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "bTNiMADmqxI4", - "outputId": "1440ed7d-2dfa-42dc-8778-e519b3e0cb3a" - }, - "outputs": [], - "source": [ - "trade_price_over_time = plot_time_series(\n", - " [\"TRADE_PRICE\", \"price_ex_lead\", \"price_ex_lag\"], \"median\"\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Z234Di7gwhHD" - }, - "source": [ - "**Observation:**\n", - "* `TRADE_PRICE` remains roughly constant over time. Median decreases over time.\n", - "* Large difference between median and mean. " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "S5rHAylRzt1d" - }, - "source": [ - "### Time to maturity ⌚" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "YOtWJYd1mRAx", - "outputId": "ca0c87b0-b957-4b70-cde4-bc028a206521" - }, - "outputs": [], - "source": [ - "ttm_over_time = plot_time_series(\"ttm\", \"mean\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "WIiLkBmymu6n", - "outputId": "9a1b8ae7-4002-425f-d843-c728654c9222" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data=data[data[\"bid_ex\"] == 0.0], x=\"ttm\", bins=50) \n", - "ax.title.set_text(\"Count of transactions with regard to time to maturity (months)\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "uEYVInVtwhHF" - }, - "source": [ - "**Observation:**\n", - "- Most options have a short time-to-maturity\n", - "- Binning or cut-off could be helpful" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "HIPLWci8m2MD", - "outputId": "808cf9b4-1954-4ff4-f19e-0bfbf7c1db02" - }, - "outputs": [], - "source": [ - "# TODO: ask of zero plausible?\n", - "sns.histplot(data=data[data[\"ask_ex\"] == 0.0], x=\"ttm\", bins=50) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "q5WCxCtC6N1r" - }, - "source": [ - "### Strike price" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "shLvgI6_6pob", - "outputId": "922e91ab-de04-4135-b03c-3d4b07adcdf0" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"STRK_PRC\", bins=50) \n", - "ax.title.set_text(\"Histogram of strike price\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "FF4T32MV7MRf", - "outputId": "0473dab3-ee9b-42a3-9be3-b25ade066846" - }, - "outputs": [], - "source": [ - "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"STRK_PRC\")\n", - "ax.title.set_text(\"Box plot of strike prices for buys (1) and sells (-1)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "v0YTFt-Y6QlA", - "outputId": "f0b3388f-d801-4b31-cb53-b74b13a1cff6" - }, - "outputs": [], - "source": [ - "strike_over_time = plot_time_series(\"STRK_PRC\", \"mean\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "ai93sNiywhHI" - }, - "source": [ - "**Observation:**\n", - "- Distribution of strike price is highly skewed\n", - "- Average strike price grows over time. Thus, very large and previously unobserved trade prices could be part of the test set, but not in the train set.\n", - "- Try $\\log$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "E4zueI8_6_zh" - }, - "outputs": [], - "source": [ - "data[\"log_strk_prc\"] = np.log1p(data[\"STRK_PRC\"])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "HsYMWQOs6jUt", - "outputId": "b3eab404-16e8-46ce-a9a5-8d78b217d58e" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"log_strk_prc\", bins=50) \n", - "ax.title.set_text(\"Histogram of strike price (log1p)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "ubhwxzaO7jD0", - "outputId": "fbf6839f-2903-4a0d-db26-c6b89843d797" - }, - "outputs": [], - "source": [ - "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"log_strk_prc\")\n", - "ax.title.set_text(\"Box plot of strike prices for buys (1) and sells (-1)\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "9of8S3X52_WS" - }, - "source": [ - "### Buy Sell πŸ‘›" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "EpSh473iHU3W", - "outputId": "76566198-8e47-420a-8884-cef391e1b477" - }, - "outputs": [], - "source": [ - "ratio_buy_sell = data[\"buy_sell\"].value_counts() / data[\"buy_sell\"].count()\n", - "ratio_buy_sell.head()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "deJhfCrxHy8Y" - }, - "source": [ - "**Observation:**\n", - "* Ratios similar to the one reported in Grauer et. al. Yet not identical as calculation is done on a sample.\n", - "* As both classes have a $\\approx~0.5$ probability, I would not rebalance. Rebalancing through sampling etc. itself has a bias.\n", - "* Ratios seem to be stable over time (see below). Thus, distribution is similar for training, validation, and test set.\n", - "* With regard to time-to-maturity the distribution changes slightly for longer periods." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "IYXjbdNOScZ5" - }, - "source": [ - "#### By option type" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 431 - }, - "id": "r4zDI-vV4QHT", - "outputId": "128120ff-5846-4e26-b121-3c90cbfc5633" - }, - "outputs": [], - "source": [ - "ax = sns.countplot(data=data, x=\"OPTION_TYPE\", hue=\"buy_sell\")\n", - "ax.title.set_text(\"Distribution of Buy / Sell indicator with regard to option type\")\n", - "sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3pOzIcdrSjaU" - }, - "source": [ - "#### By year" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 405 - }, - "id": "L1rT2d3m2-8L", - "outputId": "bf6a4809-5585-4e6a-94d2-c7969cb3292a" - }, - "outputs": [], - "source": [ - "ax = sns.countplot(data=data, x=\"year_binned\", hue=\"buy_sell\")\n", - "ax.title.set_text(\"Distribution of Buy / Sell indicator with regard to year (binned)\")\n", - "ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha=\"center\")\n", - "plt.tight_layout()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "LO_Y_3LlSoOq" - }, - "source": [ - "#### By time time to maturity" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 405 - }, - "id": "mhZopwr-4ITf", - "outputId": "341b30a7-6a9c-44d9-ba4d-fe45145dd8b9" - }, - "outputs": [], - "source": [ - "ax = sns.countplot(data=data, x=\"ttm_binned\", hue=\"buy_sell\")\n", - "ax.title.set_text(\n", - " \"Distribution of Buy / Sell indicator with regard to time to maturity (binned)\"\n", - ")\n", - "ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha=\"center\")\n", - "plt.tight_layout()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "vCaz459vUzIM", - "outputId": "e91328c8-9367-41ee-ba13-56a6161f356d" - }, - "outputs": [], - "source": [ - "ax = sns.scatterplot(data=sample, x=\"ttm\", y=\"bid_ex\", hue=\"OPTION_TYPE\")\n", - "ax.title.set_text(\"Scatter plot of time to maturity (months) and bid (ex)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "fkEKGH4-RDHc", - "outputId": "4cf0dd8f-4d50-42a0-9c54-be7e81e59b11" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data=data[data[\"bid_ex\"] == 0.0], x=\"ttm\", bins=50) \n", - "ax.title.set_text(\"Count of transactions with regard to time to maturity (months)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "YNF09VisR6ox", - "outputId": "ee9fcbd9-3632-43a8-995d-8d38f9889a3b" - }, - "outputs": [], - "source": [ - "# TODO: ask of zero plausible?\n", - "sns.histplot(data=data[data[\"ask_ex\"] == 0.0], x=\"ttm\", bins=50) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "VKOYYMjdSwmq" - }, - "source": [ - "#### Over time" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 571 - }, - "id": "gR6c5UUC3WHf", - "outputId": "f92abde5-5df1-446b-ce09-e1a78f0b8a3c" - }, - "outputs": [], - "source": [ - "trades_over_time = (\n", - " data.groupby(data[\"date\"])[\"buy_sell\"].value_counts().unstack(fill_value=0)\n", - ")\n", - "ax = trades_over_time.plot(\n", - " kind=\"line\",\n", - " figsize=ratio,\n", - " title=\"buy / sell count over time\",\n", - " xlabel=\"date\",\n", - " ylabel=\"sell (-1) / buy (1)\",\n", - ")\n", - "plot_recessions()\n", - "ax.legend()\n", - "plt.show()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "uNN4ksMGlTQm" - }, - "source": [ - "### $n$ most frequent symbols, indices, and special codes πŸ”’" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "waAefSrZY9Ij" - }, - "source": [ - "See how frequent symbols are, as they can lead to an explosion in cardinality." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "znjnZIdMY9Ik", - "outputId": "cced72f2-2128-44cf-b594-16b625a6b26e" - }, - "outputs": [], - "source": [ - "frequency_symbols = data[\"ROOT\"].value_counts().reset_index(name=\"Count\")\n", - "frequency_symbols.rename(columns={\"index\": \"Symbol\"}, inplace=True)\n", - "frequency_symbols.sort_values(\"Count\", ascending=True)\n", - "sns.histplot(data=frequency_symbols, x=\"Count\", bins=200)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "5aRfobVAY9Il", - "outputId": "e19feb4f-4591-487a-dd33-a1af7b1666b6" - }, - "outputs": [], - "source": [ - "frequency_symbols[frequency_symbols[\"Count\"] <= 5].count()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 424 - }, - "id": "cLvzcvrQY9Im", - "outputId": "dcdddacf-a78f-43a7-9c3c-fdf89d4b14c1" - }, - "outputs": [], - "source": [ - "frequency_symbols\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 726 - }, - "id": "qLVCUu8WOqGG", - "outputId": "8058bfb0-031a-4d61-ebda-b84cb7e9d5a7" - }, - "outputs": [], - "source": [ - "most_frequent_symbols = data[\"ROOT\"].value_counts().head(N).reset_index(name=\"Count\")\n", - "most_frequent_symbols.rename(columns={\"index\": \"Symbol\"}, inplace=True)\n", - "\n", - "ax = sns.barplot(data=most_frequent_symbols, x=\"Symbol\", y=\"Count\")\n", - "ax.title.set_text(f\"{N} most frequently traded symbols\")\n", - "\n", - "most_frequent_symbols.head(N)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "balcupvypq5_" - }, - "outputs": [], - "source": [ - "list_freq_symbols = most_frequent_symbols.Symbol.tolist()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "vxI2kyFypzmb" - }, - "outputs": [], - "source": [ - "frequent_symbols_over_time = data[data[\"ROOT\"].isin(list_freq_symbols)]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Ui_bSf3JrdjE" - }, - "outputs": [], - "source": [ - "frequent_symbols_trades_per_day = (\n", - " frequent_symbols_over_time.groupby(\n", - " [frequent_symbols_over_time.QUOTE_DATETIME.dt.to_period(\"m\"), \"ROOT\"]\n", - " )[\"TRADE_SIZE\"]\n", - " .count()\n", - " .reset_index()\n", - " .rename(columns={\"TRADE_SIZE\": \"count\", \"QUOTE_DATETIME\": \"date\", \"ROOT\": \"Symbol\"})\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "r9NQn8JojaHq" - }, - "outputs": [], - "source": [ - "frequent_symbols_over_time = (\n", - " frequent_symbols_trades_per_day.groupby([\"date\", \"Symbol\"])[\"count\"]\n", - " .first()\n", - " .unstack()\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 397 - }, - "id": "xKynCukCly3K", - "outputId": "5f968ff8-407c-4c00-e44c-d909380719dd" - }, - "outputs": [], - "source": [ - "frequent_symbols_over_time.plot(\n", - " kind=\"line\", title=f\"{N} most frequently traded underlyings over time\"\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "SvzXOQXJY9Ir" - }, - "outputs": [], - "source": [ - "root_time_train = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/train_set_extended_60.parquet\",\n", - " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", - ")\n", - "root_time_val = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/val_set_extended_20.parquet\",\n", - " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", - ")\n", - "root_time_test = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/test_set_extended_20.parquet\",\n", - " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", - ")\n", - "\n", - "roots_over_time = pd.concat([root_time_train, root_time_val, root_time_test])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "f1GkQvJQY9Is" - }, - "outputs": [], - "source": [ - "# randomly sample N symbols and check when they appear for the first and last time\n", - "roots_sample = (\n", - " roots_over_time.groupby(\"ROOT\")[\"QUOTE_DATETIME\"]\n", - " .agg([\"min\", \"max\"])\n", - " .reset_index()\n", - " .sample(N)\n", - " .T\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "9Myp0ocfY9It" - }, - "outputs": [], - "source": [ - "# see 2.0-mb-data_preprocessing_loading_splitting.ipynb\n", - "dti = pd.date_range(\"2005-05-02\", \"2017-05-31\", freq=\"d\")\n", - "plot_df = pd.DataFrame(index=dti)\n", - "\n", - "for i, col in enumerate(roots_sample.columns):\n", - " plot_df[roots_sample.iloc[0, i]] = np.where(\n", - " np.logical_and(\n", - " plot_df.index >= roots_sample.iloc[1, i],\n", - " plot_df.index <= roots_sample.iloc[2, i],\n", - " ),\n", - " i / N,\n", - " np.nan,\n", - " )\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 383 - }, - "id": "gz4UzN30Y9Iu", - "outputId": "fa727147-f8b8-444f-e29e-082165c6bb77" - }, - "outputs": [], - "source": [ - "ax = plot_df.plot(legend=False, style=\".\")\n", - "ax.set_yticks(np.linspace(0, (N - 1) / N, N))\n", - "ax.set_yticklabels(plot_df.columns)\n", - "# beginning of validation and test set\n", - "ax.axvline(\"2013-10-25\", color=\"gray\")\n", - "ax.axvline(\"2015-11-06\", color=\"gray\")\n", - "ax.set_title(\"roots over time (min / max appearance)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 431 - }, - "id": "S-Kd5_JSOO6R", - "outputId": "6dad31cd-2920-4226-e668-6910c0ce98b3" - }, - "outputs": [], - "source": [ - "# TODO: investigate why there is no True group\n", - "ax = sns.countplot(data=data, x=\"symbol_is_index\", hue=\"buy_sell\")\n", - "ax.title.set_text(\n", - " \"Distribution of Buy / Sell indicator with regard to whether underlying is an index\"\n", - ")\n", - "sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "9ZPOB0DDPlaA", - "outputId": "dd796dd9-5e4e-4500-df78-39f3e06ae8aa" - }, - "outputs": [], - "source": [ - "ratios_is_index = (\n", - " data.groupby([\"symbol_is_index\", \"buy_sell\"])[\"buy_sell\"].count()\n", - " / data.groupby([\"symbol_is_index\"])[\"buy_sell\"].count()\n", - ")\n", - "ratios_is_index.head()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "cvLHx_iNOtgo" - }, - "source": [ - "**Observation:**\n", - "- Feature can be important, as it's much more likely for trade to be sell, rather than buy, if and only if the underlying is no index option.\n", - "- Difference isn't too pronounced and could be due to sampling effects." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "7cm4CSLELZLy", - "outputId": "3d3531b2-a7d0-4610-e5c1-b7eb1d764d3a" - }, - "outputs": [], - "source": [ - "data[\"issue_type\"].value_counts(dropna=False)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "hI-NvLxx_p1P", - "outputId": "237340be-a1bb-4b4a-8159-b7720477c445" - }, - "outputs": [], - "source": [ - "ax = sns.countplot(data=data, x=\"issue_type\")\n", - "ax.title.set_text(\"No. of transactions by issue type\")\n", - "ax.xaxis.label.set_text(\"issue type\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "puN3bdGmUPLh" - }, - "source": [ - "### Ask and bidπŸ‘¨β€βš–οΈ" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 380 - }, - "id": "ObXgSwSxq2E_", - "outputId": "30df67d5-2601-4921-cf1b-a0c21db8f55a" - }, - "outputs": [], - "source": [ - "bid_ask_over_time = plot_time_series(\n", - " [\"bid_ex\", \"ask_ex\", \"BEST_ASK\", \"BEST_BID\"], \"mean\"\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "bS2PiyAl8XYP" - }, - "source": [ - "#### Ask" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "KwtMkQfIUPLi", - "outputId": "88b78791-b8fd-40ce-ccc7-8410ddf4a763" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"ask_ex\", bins=50) \n", - "ax.title.set_text(\"Histogram of ask (exchange)\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "MrinpS5KwhHX" - }, - "source": [ - "**Observation:**\n", - "* Distribution is highly skewed, try correction with $\\log$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "t9Od_ss68Uf7", - "outputId": "0dbb2688-1e93-4e5d-82bc-51889dd8011e" - }, - "outputs": [], - "source": [ - "data[\"log_ask_ex\"] = np.log1p(data[\"ask_ex\"])\n", - "ax = sns.histplot(data, x=\"log_ask_ex\", bins=50) \n", - "ax.title.set_text(f\"Histogram of ask exchange (log1p)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "JHc4tuDw8UHG", - "outputId": "1d102fa7-b1b9-4871-e7d8-f726bb262b33" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_ask_ex\", clip=[0, 5])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "hneiYOS1whHY" - }, - "source": [ - "**Observation:**\n", - "* Applying a $\\log$ transform leads to a easily distinguishable distribution" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "7jVN_izn8a43" - }, - "source": [ - "#### Bid" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "qap6DPAb8if7", - "outputId": "d0f16e78-d0d2-46f1-aef1-2f8979f9f989" - }, - "outputs": [], - "source": [ - "ax = sns.histplot(data, x=\"bid_ex\", bins=50) \n", - "ax.title.set_text(\"Histogram of bid (exchange)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "3w88oBOpUPLj", - "outputId": "cf90db94-d616-4191-836e-56c0d784cd43" - }, - "outputs": [], - "source": [ - "data[\"log_bid_ex\"] = np.log1p(data[\"bid_ex\"])\n", - "ax = sns.histplot(data, x=\"log_bid_ex\", bins=50) \n", - "ax.title.set_text(f\"Histogram of bid exchange (log1p)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "hlsQokLcUPLj", - "outputId": "5b8d9db8-5d10-4b9c-a907-cf5f666defcb" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_bid_ex\", clip=[0, 5])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 381 - }, - "id": "_JBE-ymdUPLk", - "outputId": "cd61daed-cfeb-45da-9fa4-a31278e884a6" - }, - "outputs": [], - "source": [ - "data[\"log_bid_ex\"] = np.log1p(data[\"bid_ex\"])\n", - "ax = sns.histplot(data, x=\"log_bid_ex\", bins=50) \n", - "ax.title.set_text(\"Histogram of bid exchange (log1p)\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "biafaSUqUPLk", - "outputId": "8d4404c6-79e4-4e6e-eed7-11d14e58d4d7" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_bid_ex\", clip=[-5, 6])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vesyvNMPUPLk" - }, - "source": [ - "**Observation:**\n", - "- One can choose different constants, but small constants, e. g., `const=1e-2` gives fuzzy, yet distributions that are easier to distinguish. Also note the higher correlation with the target. \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "fnrbwIFTYHr_" - }, - "source": [ - "**Observation:**\n", - "- log on size seems to worsen results.\n", - "- `TODO:` investigate further, what the reason is. e. g., how many outliers..." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "UUbWmbEtS2Ve" - }, - "source": [ - "# NaNs πŸͺ²" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "lYGJpMvzEhyc" - }, - "outputs": [], - "source": [ - "def visualize_nan():\n", - " \"\"\"\n", - " Visualize NaN values in a heatmap to learn about patterns.\n", - " \"\"\"\n", - " plt.subplots()\n", - " sns.heatmap(data.head(50).isnull(), cbar=False)\n", - " plt.xlabel(\"feature\")\n", - " plt.ylabel(\"row\")\n", - " plt.title(\"Missing values (colored in bright beige)\")\n", - " plt.show()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 470 - }, - "id": "glhx2wHHEtkU", - "outputId": "a26fefb3-fff4-4910-c8bb-01972d6d81a7" - }, - "outputs": [], - "source": [ - "visualize_nan()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 668 - }, - "id": "2JOoXJtHIKXE", - "outputId": "32053749-fa94-4608-c354-6dfa65e7a326" - }, - "outputs": [], - "source": [ - "isna_vals = data.isna().sum().sort_values(ascending=False)\n", - "isna_vals = isna_vals.loc[lambda x: x > 0]\n", - "\n", - "ax = isna_vals.T.plot(\n", - " kind=\"bar\",\n", - " figsize=ratio,\n", - " legend=False,\n", - " xlabel=\"No. of missing values\",\n", - " ylabel=\"feature\",\n", - " title=\"Missing values\",\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 588 - }, - "id": "swu5wGjNLZbF", - "outputId": "b04cb287-4483-48bb-f41f-77cca1c34bb8" - }, - "outputs": [], - "source": [ - "isna_vals_over_time = (\n", - " data[isna_vals.index.tolist()]\n", - " .groupby(data[\"QUOTE_DATETIME\"].dt.date)\n", - " .agg(lambda x: x.isnull().sum())\n", - ")\n", - "isna_vals_over_time.plot(\n", - " kind=\"line\",\n", - " figsize=ratio,\n", - " title=\"Missing values over time\",\n", - " xlabel=\"Timestamp\",\n", - " ylabel=\"No. of missing values\",\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 654 - }, - "id": "Bk7kdwU0Nh9X", - "outputId": "761bca49-09cf-4dac-c9be-09f9604a693b" - }, - "outputs": [], - "source": [ - "# adapted from: https://github.com/ResidentMario/missingno/blob/master/missingno/missingno.py\n", - "\n", - "isna_data = data.iloc[\n", - " :, [i for i, n in enumerate(np.var(data.isnull(), axis=\"rows\")) if n > 0]\n", - "]\n", - "\n", - "corr_mat = isna_data.isnull().corr()\n", - "mask = np.zeros_like(corr_mat)\n", - "mask[np.triu_indices_from(mask)] = True\n", - "\n", - "fig, ax = plt.subplots(figsize=(9, 9))\n", - "ax = sns.heatmap(corr_mat, mask=mask, annot=False, annot_kws={\"size\": 10}, ax=ax)\n", - "ax.title.set_text(\"Correlation between missing features\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 446 - }, - "id": "Dokt9B3BEvor", - "outputId": "bc9ccd5a-4d1f-488b-c4bf-b2978744a414" - }, - "outputs": [], - "source": [ - "# adapted from: https://github.com/ResidentMario/missingno/blob/master/missingno/missingno.py\n", - "\n", - "# sample down for performance reasons\n", - "isna_data = data.sample(frac=0.05)\n", - "\n", - "plt.figure()\n", - "ax0 = plt.gca()\n", - "\n", - "# Link the hierarchical output matrix, figure out orientation, construct base dendrogram.\n", - "x = np.transpose(isna_data.isnull().astype(int).values)\n", - "z = hierarchy.linkage(x, \"average\")\n", - "\n", - "hierarchy.dendrogram(\n", - " z,\n", - " labels=isna_data.columns.tolist(),\n", - " distance_sort=False,\n", - " link_color_func=lambda c: \"black\",\n", - " ax=ax0,\n", - ")\n", - "\n", - "# Remove extraneous default visual elements.\n", - "ax0.set_aspect(\"auto\")\n", - "ax0.set_title(\"Dendrogram of missing values\")\n", - "\n", - "ax0\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "dXduwXBWwhHl" - }, - "source": [ - "**Observation:**\n", - "- Note that also important features like `price_all_lead` or `price_ex_lag` are missing. This has an impact, whether it is possible to calculate the classical rules like the trade rule. Consider this when reporting results.\n", - "- Missing values become more of a problem towards the end of the data set. At the same time the number of trades also increases." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "hB5ZELdNm8fG" - }, - "source": [ - "# Correlations of engineered features 🎲" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Wq61_ag29Sxe" - }, - "source": [ - "### Correlations 🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 482 - }, - "id": "WwYnaW2zwJ9e", - "outputId": "2c430d9f-a63d-470b-e658-e5aaadc2cb3c" - }, - "outputs": [], - "source": [ - "corr = data.corr()\n", - "\n", - "sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values) \n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8KUisq6b5TeN" - }, - "source": [ - "### Correlation with target 🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000 - }, - "id": "TeyU4_ev4gzx", - "outputId": "2b1d054d-f525-401d-8c18-2dcd560e33f1" - }, - "outputs": [], - "source": [ - "sort_criteria = corr[\"buy_sell\"].abs().sort_values(ascending=False)\n", - "corr_target = corr.sort_values(\"buy_sell\", ascending=False)[\"buy_sell\"]\n", - "corr_target.loc[sort_criteria.index].to_frame()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "KP4WCZV54j_0", - "outputId": "fe13968d-59a7-47f6-b377-7aedbdad4fd5" - }, - "outputs": [], - "source": [ - "# adapted from here: https://www.kaggle.com/code/willkoehrsen/featuretools-for-good\n", - "\n", - "# Select upper triangle of correlation matrix\n", - "upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))\n", - "\n", - "# Find index of feature columns with correlation greater than 0.95\n", - "to_drop = [column for column in upper.columns if any(abs(upper[column]) > 0.975)]\n", - "\n", - "print(to_drop)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0DFHkf2rwhHn" - }, - "source": [ - "**Observation:**\n", - "- Newly engineered features have a high correlation with the target, which is positive. Investigate if the correlation is due to randomness or whether a pattern is observable.\n", - "- `_ex` and `BEST_` features seem to be rather redundant, even if a high threshold for correlation is chosen." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "1_T0SJq85dBz" - }, - "source": [ - "### Collinearity of features🎲" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "2AzhGW0P4qf0", - "outputId": "0e925abf-372e-453a-ec82-9a6f1e6d64c4" - }, - "outputs": [], - "source": [ - "# Set the threshold\n", - "threshold = 0.975\n", - "\n", - "# Empty dictionary to hold correlated variables\n", - "above_threshold_vars = {}\n", - "\n", - "# For each column, record the variables that are above the threshold\n", - "for col in corr:\n", - " above_threshold_vars[col] = list(corr.index[corr[col] > threshold])\n", - "\n", - "pd.Series(above_threshold_vars)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Si_KbJ4L9vXX" - }, - "source": [ - "# Analyses of engineered features" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 110 - }, - "id": "Ia0PqSQ1-Ky1", - "outputId": "249d3820-8779-4b3d-b399-68cf926d8562" - }, - "outputs": [], - "source": [ - "corr_target.loc[sort_criteria.index].to_frame().T\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "8ZqYGILc-F35" - }, - "source": [ - "### What works βœ”οΈ" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "eqCs_1OnhisK" - }, - "source": [ - "#### Trade price vs distance from mid\n", - "\n", - "Similar to `EMO`, where the applied rule depends on whether the trade is at the ask or bid. Similarily `CLVN` uses percentage bounds e. g., $~20~\\%$ of spread." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "A1y0c6y0hqtB", - "outputId": "0fddf5eb-a51d-4082-84fe-619bb690532c" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"prox_ex\", clip=[-2, 2])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "eblbyBtLh32U", - "outputId": "3b7b6db7-db3e-4534-c778-fa2389f7aa02" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"prox_ex\", years=[2006, 2010, 2013], clip=[-2, 2])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Jc3nlqEai9aa" - }, - "source": [ - "#### Depth\n", - "\n", - "Implicitly used in depth rule. Depth rule would assign a buy if `bid_ask_size_ratio_ex` is above one and a sell if it is below zero. But only used for mid-spread trades." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "WugmHPe5jAXi", - "outputId": "1ef9dd30-5f93-4468-933b-cb9cb69db9d7" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"bid_ask_size_ratio_ex\", clip=[0, 100])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "EelrGS3ijA2d", - "outputId": "b23088da-5cea-4eb6-e642-6d966bb95741" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\n", - " \"bid_ask_size_ratio_ex\", years=[2006, 2010, 2013], clip=[0, 100]\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "La0E9-xeDznH" - }, - "source": [ - "#### $\\log$ bid ex" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "azwaPAaR-hMH", - "outputId": "da0d0833-13b6-45be-ee1f-c4d1de93a19e" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_bid_ex\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "bD0Vrrue-3bI", - "outputId": "6d5ecd65-97ff-47c5-e0c7-c978999d6ded" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"log_bid_ex\", years=[2006, 2010, 2013])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "nMDoG_7ZwhHu" - }, - "source": [ - "**Observation:**\n", - "- Application of the $\\log$ leads to highly differentiable distributions, that remain stable over time." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "mAnyPoUuDvmW" - }, - "source": [ - "#### $\\log$ trade price" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "7UYh_BnU_MeW", - "outputId": "56e56a26-1e71-461a-81c0-8d2828c343cb" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_trade_price\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "83OwlI_H_X6e", - "outputId": "68ed276e-fdcf-411b-b50e-0cbe6e92905b" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"log_trade_price\", years=[2006, 2010, 2013])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "KNqBQJWwwhHv" - }, - "source": [ - "**Observation:**\n", - "- Application of the $\\log$ leads to highly differentiable distributions, that remain stable over time." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "gpdek3I2DsIS" - }, - "source": [ - "#### Ask size" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "mhljYe2-_xlb", - "outputId": "8e6edcc4-4447-4e1e-ff44-a7a0b9cee687" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"ask_size_ex\", clip=[0, 2000])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "6WLZVYMTAISn", - "outputId": "ae4d16da-5c95-4985-e41f-1a0c7f6214e7" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"ask_size_ex\", years=[2006, 2010, 2013], clip=[0, 2000])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "NC-jnOsVDo4b" - }, - "source": [ - "#### Bid size" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "7auGIaX5AtuF", - "outputId": "102c88e5-b9c8-441a-b467-6880fdc96409" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"bid_size_ex\", clip=[0, 1000])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "k4d6zmPJBbQe", - "outputId": "d7444269-ae64-42fd-faf1-2c399a697ba7" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"bid_size_ex\", years=[2006, 2010, 2013], clip=[0, 1000])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "VL6hJO_ADgrS" - }, - "source": [ - "#### Quote rule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "y8nKJs-xCHvF", - "outputId": "8123dcb6-26ea-42d9-aeba-97b37d033c7b" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"abs_mid_ex\", clip=[-0.5, 0.5])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "YkRp65M7CN7M", - "outputId": "e3c2b158-d139-4f2c-8951-6339dcd78100" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"abs_mid_ex\", years=[2006, 2010, 2013], clip=[-0.5, 0.5])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "xHh4GiFOwhHy" - }, - "source": [ - "**Observation:**\n", - "- Compared with tick rule or reverse tick rule, quote rule is the only classical rule, where distributions are somewhat distinguishable\n", - "- On can clearly see that the quote rule works better at the beginning of the data set and its performance worsens over time." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "JljvKUsVEL6H" - }, - "source": [ - "#### Day of the month" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "wvhCypnJD6_y", - "outputId": "0ac7f3c4-449b-4442-9369-56ee57ce0441" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"day\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "j2pP-JoWGT3a", - "outputId": "89da927d-9628-4f45-fc27-5755cb81f4d6" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"year\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "GU6-LKPrGftY" - }, - "source": [ - "**Observation:**\n", - "* Judging from the plot there seems to be a seasonal pattern e. g., more buys \n", - "at the beginning of the month and more sells towards the end of the month. \n", - "* Due to the distributions it could make sense to include date features in some feature sets. But do not include in the most basic data set." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "KDAoxtxJ-TkV" - }, - "source": [ - "## What doesn't ❌" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "vm-KQmTLFAhR" - }, - "source": [ - "#### tick rule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "HgyVpqkhAn2A", - "outputId": "a9ad17e6-fb4a-428d-e75f-8e18b0e46f0f" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"chg_ex_lead\", clip=[-5, 5])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "QjY46fg-Fn4q", - "outputId": "d3a069e2-3f0c-41a1-e0b1-ed78b0178507" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"chg_ex_lead\", years=[2006, 2010, 2013], clip=[-5, 5])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "s_60zom2whH1" - }, - "source": [ - "**Observation:**\n", - "- Distributions are hardly distinguishable. \n", - "- Results seem to worsen over time, which is consistent to the observations of Grauer et. al." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Vc3gKTf7FHID" - }, - "source": [ - "#### reverse tick rule" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "V-XTdok0FKJw", - "outputId": "01b29cc6-f889-4b98-9718-eec0047b016e" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"chg_ex_lag\", years=[2006, 2010, 2013], clip=[-5, 5])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 312 - }, - "id": "1egDxKiVF3x_", - "outputId": "4460c8ce-13fb-4d30-b6ad-1dab281233cf" - }, - "outputs": [], - "source": [ - "plot_kde_target_comparsion(\"chg_ex_lag\", years=[2006, 2010, 2013], clip=[-5, 5])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "d7F0yjcxwhH2" - }, - "source": [ - "**Observation:**\n", - "- Distributions are hardly distinguishable. \n", - "- Results worsen over time." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "mCid1bvHUPuu", - "outputId": "9f615b6f-4162-44e4-f699-9f2a910c0454" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_bid_ex\", clip=[-5, 8])\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "UY_U1fSnU9w-" - }, - "outputs": [], - "source": [ - "data.replace([np.inf, -np.inf], np.nan, inplace=True)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "7DuDX2elUTE7" - }, - "outputs": [], - "source": [ - "scaler = StandardScaler()\n", - "data[\"log_bid_ex_scaled\"] = scaler.fit_transform(\n", - " X=data[\"log_bid_ex\"].values.reshape(-1, 1)\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "zsdRVJVTWGUe", - "outputId": "83bbe197-c18e-4f44-b29c-5c250586b2da" - }, - "outputs": [], - "source": [ - "data[\"log_bid_ex_scaled\"].describe()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 483 - }, - "id": "cJVUGKqMUjWY", - "outputId": "88145966-8677-476b-ee33-a8bc0ef55999" - }, - "outputs": [], - "source": [ - "plot_kde_target(\"log_bid_ex_scaled\", clip=[-5, 5])\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "TDCrqcp8Y9Js" - }, - "source": [ - "Results as expected. Scaling using `StandardScaler` does not affect distribution of data." - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "F781YhmiGY_u" - }, - "source": [ - "# Conclusion πŸ”—\n", - "\n", - "**Observation:**\n", - "* $log$ transform makes no difference for gbms as shown in `3.0b-mb-comparsion-transformations.ipynb`. This is consistent with literature, as trees don't consider distributions. $log$\n", - "* Imputation makes hardly any differnce for gbms as shown in `3.0b-mb-comparsion-transformations.ipynb`. Passing missing values to the model yields slightly better results. This is also expected.\n", - "* Incorporating highly correlated columns is no problem for gbms and neural nets from a theoretical standpoint.\n", - "- Features of Grauer et. al seem to work. \n", - "- Binning gives mixed results e. g., for trade size and ttm.\n", - "- Theoretically, highly correlated columns don't matter for gradient boosting and neural networks.\n" - ] - } - ], - "metadata": { - "colab": { - "machine_shape": "hm", - "name": "Untitled2.ipynb", - "provenance": [] - }, - "gpuClass": "premium", - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.4 (tags/v3.9.4:1f2e308, Apr 6 2021, 13:40:21) [MSC v.1928 64 bit (AMD64)]" - }, - "vscode": { - "interpreter": { - "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "EMApm-vLnME4" + }, + "outputs": [], + "source": [ + "from __future__ import annotations\n", + "\n", + "import os\n", + "import random\n", + "import warnings\n", + "\n", + "import dateutil.relativedelta as relativedelta\n", + "\n", + "warnings.simplefilter(action=\"ignore\", category=FutureWarning)\n", + "\n", + "from typing import Any, List\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import pandas_datareader.data as web\n", + "import seaborn as sns\n", + "from scipy import stats\n", + "from scipy.cluster import hierarchy\n", + "from sklearn.manifold import TSNE\n", + "from sklearn.preprocessing import StandardScaler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "BRFyckmGEHXL" + }, + "outputs": [], + "source": [ + "# set N used in n-largest or smallest\n", + "N = 10\n", + "\n", + "# set style\n", + "plt.style.use(\"seaborn-notebook\")\n", + "\n", + "# set ratio of figure\n", + "ratio = (16, 9)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "a-f2aByNtJTK" + }, + "outputs": [], + "source": [ + "# set fixed seed\n", + "def seed_everything(seed) -> None:\n", + " \"\"\"\n", + " Seeds basic parameters for reproducibility of results.\n", + " \"\"\"\n", + " os.environ[\"PYTHONHASHSEED\"] = str(seed)\n", + " random.seed(seed)\n", + " # pandas and numpy as discussed here: https://stackoverflow.com/a/52375474/5755604\n", + " np.random.seed(seed)\n", + "\n", + "\n", + "seed = 42\n", + "seed_everything(seed)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9MOW2bJSmY8x" + }, + "source": [ + "This notebook performs an eda on the training set only to avoid data leakage. ⚠️" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "EF0_Mz8DYjGz" + }, + "outputs": [], + "source": [ + "data = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/train_set_extended_60.parquet\"\n", + ").sample(frac=0.1, axis=0, random_state=seed)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NDz5ZzVl_QGD" + }, + "source": [ + "## Notes on data set πŸ—ƒοΈ" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "yAWnmnei39o5" + }, + "source": [ + "**Overview on ticker symbols:**\n", + "- `others` identified by issue type.\n", + "- 5th letter has a special meaning as found in [this table](https://en.wikipedia.org/wiki/Ticker_symbol):\n", + "\n", + "| Letter | Letter contd. | Letter contd. |\n", + "|--------------------------------|-------------------------------------|------------------------------------------------|\n", + "| A – Class \"A\" | K – Nonvoting (common) | U – Units |\n", + "| B – Class \"B\" | L – Miscellaneous | V – Pending issue and distribution |\n", + "| C – NextShares | M – fourth class – preferred shares | W – Warrants |\n", + "| D – New issue or reverse split | N – third class – preferred shares | X – Mutual fund |\n", + "| E – Delinquent SEC filings | O – second class – preferred shares | Y – American depositary receipt (ADR) |\n", + "| F – Foreign | P – first class preferred shares | Z – Miscellaneous situations |\n", + "| G – first convertible bond | Q – In bankruptcy | Special codes |\n", + "| H – second convertible bond | R – Rights | PK – A Pink Sheet, indicating over-the-counter |\n", + "| I – third convertible bond | S – Shares of beneficial interest | SC – Nasdaq Small Cap |\n", + "| J – Voting share – special | T – With warrants or rights | NM – Nasdaq National Market |\n", + "\n", + "\n", + "**Coverage:**\n", + "\n", + "*\tOptions on U.S. listed Stock, ETFs, and Indices disseminated over the Options Price Reporting Authority (OPRA) market data feed \n", + "*\tGlobal Trading Hours (GTH) trades are included if between 03:00am-09:15am U.S. Eastern, and for the 16:15pm 17:00pm Curb session. GTH trades outside of these time ranges will *not* be included. \n", + "\n", + "Found [here.](https://datashop.cboe.com/documents/Option_Trades_Layout.pdf)\n", + "\n", + "**Exchange Identifier:**\n", + "\n", + "- 5 = Chicago Board Options Exchange (CBOE)\n", + "- 6 = International Securities Exchange (ISE)\n", + "\n", + "Found [here.](https://datashop.cboe.com/documents/livevol_exchange_ids.csv)\n", + "\n", + "\n", + "**Issue Types:**\n", + "\n", + "Issue Type = the type of security: \n", + "- 0 = Common Stock \n", + "- A = Market index \n", + "- 7 = Mutual or investment trust fund \n", + "- F = ADR/ADS \n", + "- % = Exchange-traded fund \n", + "- (blank) = Unspecified\n", + "\n", + "Received from supervisor." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "amt068Np3EFV" + }, + "source": [ + "Adapted from the cboe data shop found at [option trades](https://datashop.cboe.com/documents/Option_Trades_Layout.pdf) and [option quotes](https://datashop.cboe.com/documents/Option_Quotes_Layout.pdf).\n", + "\n", + "| Column Label | Data Type | Description |\n", + "|---------------------------------------------------------------------------|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n", + "| underlying_symbol | string | The underlying stock or index. An index will utilize a caret (^) prefix, i.e. ^NDX,^SPX,^VIX…etc. Underlyings with classes may utilize a dot (.) instead of a slash or space, i.e. BRK.B, RDS.A, RDS.B. |\n", + "| quote_datetime | datetime | The trading date and timestamp of the trade in U.S. Eastern time. Ex: yyyymm-dd hh:mm:ss.000 |\n", + "| sequence_number | integer | Trade Sequence Number for the execution reported by OPRA |\n", + "| root | string | The option trading class symbol. Non-standard roots may end with a digit |\n", + "| expiration | date | The explicit expiration date of the option: yyyy-mm-dd |\n", + "| strike | numeric | The exercise/strike price of the option |\n", + "| option_type | string | C for Call options, P for Put options |\n", + "| exchange_id | integer | An identifier for the options exchange the trade was executed on. For a mapping, please see Exchange ID Mappings |\n", + "| trade_size | integer | The trade quantity |\n", + "| trade_price | numeric | The trade price |\n", + "| trade_condition_id | integer | The trade or sale condition of the execution. For a mapping, please see Trade Condition ID Mapping |\n", + "| canceled_trade_condition_id | integer | This field is no longer supported and will default to 0 (zero). See IDs 40-43 in the Trade Condition ID Mapping file above |\n", + "| best_bid | numeric | The best bid price (NBB) at the time of the trade |\n", + "| best_ask | numeric | The best ask/offer price (NBO) at the time of the trade |\n", + "| bid_size | integer | The largest size from an options exchange participant on the best bid price (NBB) |\n", + "| bid | numeric | The best bid price (NBB) at the interval time stamp |\n", + "| ask_size | integer | The largest size from an options exchange participant on the best offer price (NBO) |\n", + "| ask | numeric | The best offer price (NBO) at the interval time stamp |" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "iQ4euCPwEjW0" + }, + "source": [ + "## Dtypes, distributions, and memory consumption πŸ”­" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 236 + }, + "id": "RO2KMtPiTACz", + "outputId": "f2d1f1a8-0731-4e65-95f7-62f006641f41" + }, + "outputs": [], + "source": [ + "data.head()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 300 + }, + "id": "aqk_p5ocEjDU", + "outputId": "8b78aa0f-cb00-4d7a-bcb3-a3aa3c1716f6" + }, + "outputs": [], + "source": [ + "data.describe()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "hfQwaYDo6Zqj", + "outputId": "3095bf4b-1098-40f0-da5f-f0a7e210a7c1" + }, + "outputs": [], + "source": [ + "data.info()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "AQALJAsMTElF", + "outputId": "5d3b9d82-83ad-4b74-f9ab-71e211bba302" + }, + "outputs": [], + "source": [ + "print(data.shape)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "_vilf7lRTL9D", + "outputId": "40456f7d-8378-4943-b2b7-bc6c2e28083f" + }, + "outputs": [], + "source": [ + "print(data.shape)\n", + "# drop identical rows, if present\n", + "data.drop_duplicates(inplace=True)\n", + "print(data.shape)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "wyqaDfoVwhGc" + }, + "source": [ + "**Observation:**\n", + "- Shape matches the shape reported in table 1 (panel A) of Grauer et al. paper.\n", + "- No duplicates" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6iDCXTOo63QM", + "outputId": "fdd237ec-d488-453c-9641-cd1703dd4c27" + }, + "outputs": [], + "source": [ + "data.nunique()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 739 + }, + "id": "l0aNIyjVhU_l", + "outputId": "26c485d7-e8c5-4c48-f211-2dd6e8cf279d" + }, + "outputs": [], + "source": [ + "data.head().T\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JvmC00M4ggXa" + }, + "source": [ + "## Basic features🧸" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "_mwfnC3c11S3" + }, + "source": [ + "Analysis of numerical features without any feature engineering." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "apYQeTxc_A85" + }, + "source": [ + "### Correlations 🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 430 + }, + "id": "xnCgvNWigo4v", + "outputId": "577879b8-4b4b-48cb-c894-14abb39cbdca" + }, + "outputs": [], + "source": [ + "corr: pd.DataFrame = data.corr()\n", + "sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values) \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "zCx-OV5A1nbW" + }, + "source": [ + "**Observation:**\n", + "* There are many highly correlated columns. The correlations are intuitive e. g., between `price_all_lead` and `price_ex_lead`.\n", + "* Few columns show a weak correlation with target (see also below)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "GfS9_g8lLwCk", + "outputId": "069d5158-9b9e-47d8-82d2-ad804883fe32" + }, + "outputs": [], + "source": [ + "sample = data.sample(n=1000, random_state=seed)\n", + "sns.pairplot(\n", + " sample,\n", + " vars=[\n", + " \"STRK_PRC\",\n", + " \"TRADE_SIZE\",\n", + " \"TRADE_PRICE\",\n", + " \"BEST_BID\",\n", + " \"BEST_ASK\",\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"ask_size_ex\",\n", + " \"bid_size_ex\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"day_vol\",\n", + " ],\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dhBUygocshi6" + }, + "source": [ + "### Correlation with target 🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 582 + }, + "id": "qeid5BACbK4h", + "outputId": "ec4ddbd4-e684-43ce-af4a-ed47242e5409" + }, + "outputs": [], + "source": [ + "sort_criteria = corr[\"buy_sell\"].abs().sort_values(ascending=False)\n", + "corr_target = corr.sort_values(\"buy_sell\", ascending=False)[\"buy_sell\"]\n", + "corr_target.loc[sort_criteria.index].to_frame()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "-0DAc8QweT3x" + }, + "source": [ + "**Observation:**\n", + "* Overall correlations are relatively low. Typical for financial data due to low signal-to-noise ratio.\n", + "* Size-related features like `ask_size_ex` or `bid_size_ex` have the highest correlation with the target. Thus, can be promising to be included in the model. Consider size features when constructing feature sets.\n", + "* Features like `optionid`, `order_id`, and `SEQUENCE_NUMBER` are also among the features with the highest correlations. Remove them, as the correlation is misleading." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "UGdvq8OImPBy" + }, + "outputs": [], + "source": [ + "# remove some columns, which will NOT be used in model\n", + "data.drop(columns=[\"optionid\"], inplace=True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "jh83FQtksq0p" + }, + "source": [ + "### Collinearity of features 🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "ZXMC40PcnsR1", + "outputId": "e3e6475e-7392-4b6f-d9a4-041225178134" + }, + "outputs": [], + "source": [ + "# adapted from here: https://www.kaggle.com/code/willkoehrsen/featuretools-for-good\n", + "threshold = 0.975\n", + "# Select upper triangle of correlation matrix\n", + "upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))\n", + "\n", + "# Find index of feature columns with correlation greater than 0.975\n", + "to_drop = [column for column in upper.columns if any(abs(upper[column]) > threshold)]\n", + "\n", + "print(to_drop)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cCy-QCa7whGl" + }, + "source": [ + "**Observation:**\n", + "- Columns suggested for removal are intuitive\n", + "- Do not blindly remove columns, but preserve a pattern or groups" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "HJ1kEvpmpPho" + }, + "outputs": [], + "source": [ + "# Set the threshold\n", + "threshold = 0.975\n", + "\n", + "# Empty dictionary to hold correlated variables\n", + "above_threshold_vars = {}\n", + "\n", + "# For each column, record the variables that are above the threshold\n", + "for col in corr:\n", + " above_threshold_vars[col] = list(corr.index[corr[col] > threshold])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "l151G9vXqPQI", + "outputId": "f6ed1077-2bb0-4c97-c07a-00d927f2d7df" + }, + "outputs": [], + "source": [ + "pd.Series(above_threshold_vars)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "tL1pblZKriNJ" + }, + "source": [ + "**Observations:**\n", + "* Some columns are highly correlated. This is very intuitive.\n", + "* It seems problematic to include both `BEST_BID` and `bid_ex`. This is also true for `BEST_ASK` and `ask_ex`. `price_all_lead` and `price_all_lag` seem to be less problematic.\n", + "* Define feature sets so that the number of highly correlated variables is minimized. But maintain groups so that a comparsion with classical rules is still possible." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NCtxwwaFY9HS" + }, + "source": [ + "## $t$-SNE\n", + "\n", + "Project data down using [t-SNE](https://lvdmaaten.github.io/tsne/). Also look at [umap algorithm](https://github.com/lmcinnes/umap), which is a similar effort. \n", + "\n", + "This [post](https://distill.pub/2016/misread-tsne/) gives some intuition on the parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 236 + }, + "id": "A7NuFKhNijdn", + "outputId": "961ce721-3552-4f58-8cd2-285b61298486" + }, + "outputs": [], + "source": [ + "data.head()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "jQxIPgGun_Ih" + }, + "outputs": [], + "source": [ + "sample = data.select_dtypes(include=np.number).fillna(0).drop(columns=[\"buy_sell\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "1Qm5AT8YY9HS" + }, + "outputs": [], + "source": [ + "tsne = TSNE(\n", + " n_components=2,\n", + " init=\"random\",\n", + " random_state=0,\n", + " perplexity=30,\n", + " learning_rate=\"auto\",\n", + " n_iter=300,\n", + ")\n", + "Y = tsne.fit_transform(sample)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "vdqORozgk0GZ" + }, + "outputs": [], + "source": [ + "dims = pd.DataFrame(Y, columns=[\"x\", \"y\"], index=data.index)\n", + "dims[\"class\"] = data[\"buy_sell\"]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lCROet2zpKoN" + }, + "outputs": [], + "source": [ + "dims[\"class\"] = data.buy_sell\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 557 + }, + "id": "bv80agonloiS", + "outputId": "d1c49f02-3f00-4440-927e-457671043067" + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots(1, figsize=ratio)\n", + "scatter = plt.scatter(dims[\"x\"], dims[\"y\"], c=dims[\"class\"], cmap=plt.cm.rainbow)\n", + "plt.setp(ax, xticks=[], yticks=[])\n", + "plt.title(\"t-SNE of dataset\")\n", + "plt.legend(handles=scatter.legend_elements()[0], labels=[\"-1\", \"1\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "4G3EmKH9tfir" + }, + "outputs": [], + "source": [ + "del sample\n", + "del dims\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "knWT_eurs_yl" + }, + "source": [ + "Unfortunately, **no** clear pattern visible." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KBSJWMKGhFlP" + }, + "source": [ + "## Preparation πŸ₯—" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "P3up1N46inpz" + }, + "source": [ + "### Time features ⏰" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "XACNa17ehnr_" + }, + "outputs": [], + "source": [ + "# apply positional encoding to dates\n", + "data[\"date_month_sin\"] = np.sin(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.month / 12)\n", + "data[\"date_month_cos\"] = np.cos(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.month / 12)\n", + "\n", + "days_in_month = 31 # at max :-)\n", + "data[\"date_day_sin\"] = np.sin(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.day / days_in_month)\n", + "data[\"date_day_cos\"] = np.cos(2 * np.pi * data[\"QUOTE_DATETIME\"].dt.day / days_in_month)\n", + "\n", + "# time (daily)\n", + "seconds_in_day = 24 * 60 * 60\n", + "seconds = (\n", + " data[\"QUOTE_DATETIME\"] - data[\"QUOTE_DATETIME\"].dt.normalize()\n", + ").dt.total_seconds()\n", + "\n", + "data[\"date_time_sin\"] = np.sin(2 * np.pi * seconds / seconds_in_day)\n", + "data[\"date_time_cos\"] = np.cos(2 * np.pi * seconds / seconds_in_day)\n", + "\n", + "# weekday\n", + "days_in_week = 7\n", + "data[\"date_weekday_sin\"] = np.sin(\n", + " 2 * np.pi * data[\"QUOTE_DATETIME\"].dt.dayofweek / days_in_week\n", + ")\n", + "data[\"date_weekday_cos\"] = np.cos(\n", + " 2 * np.pi * data[\"QUOTE_DATETIME\"].dt.dayofweek / days_in_week\n", + ")\n", + "\n", + "# time to maturity\n", + "data[\"ttm\"] = (\n", + " data[\"EXPIRATION\"].dt.to_period(\"M\") - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", + ").apply(lambda x: x.n)\n", + "\n", + "# day, month and year\n", + "data[\"day\"] = data[\"QUOTE_DATETIME\"].dt.day\n", + "data[\"month\"] = data[\"QUOTE_DATETIME\"].dt.month\n", + "data[\"year\"] = data[\"QUOTE_DATETIME\"].dt.year\n", + "data[\"date\"] = data[\"QUOTE_DATETIME\"].dt.date\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GGWJjuPciwh7" + }, + "source": [ + "### Binned features πŸ₯«" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "W6vEtB7T-KNy" + }, + "source": [ + "Bin features similarily to how they are used in the robustness tests." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "5HML91_Bit9A" + }, + "outputs": [], + "source": [ + "bins_tradesize = [0, 1, 3, 5, 11, np.inf]\n", + "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", + "data[\"TRADE_SIZE_binned\"] = pd.cut(\n", + " data[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", + ")\n", + "\n", + "bins_years = [2004, 2007, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]\n", + "year_labels = [\n", + " \"2005-2007\",\n", + " \"2008-2010\",\n", + " \"2011\",\n", + " \"2012\",\n", + " \"2013\",\n", + " \"2014\",\n", + " \"2015\",\n", + " \"2016\",\n", + " \"2017\",\n", + "]\n", + "data[\"year_binned\"] = pd.cut(data[\"year\"], bins_years, labels=year_labels)\n", + "\n", + "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", + "ttm_labels = [\n", + " \"ttm <= 1 month\",\n", + " \"ttm (1-2] month\",\n", + " \"ttm (2-3] month\",\n", + " \"ttm (3-6] month\",\n", + " \"ttm (6-12] month\",\n", + " \"ttm > 12 month\",\n", + "]\n", + "data[\"ttm_binned\"] = pd.cut(data[\"ttm\"], bins_ttm, labels=ttm_labels)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fNul91d8XCzv" + }, + "source": [ + "### Trade features πŸ’΄\n", + "Construct features that are used in classical rules." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "B4CnoIjyWDo1" + }, + "outputs": [], + "source": [ + "# Calculate change similar to (reverse) tick rule\n", + "data[\"chg_ex_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lead\"]\n", + "data[\"chg_ex_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lag\"]\n", + "data[\"chg_all_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lead\"]\n", + "data[\"chg_all_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lag\"]\n", + "\n", + "# Midspread\n", + "mid_ex = 0.5 * (data[\"ask_ex\"] + data[\"bid_ex\"])\n", + "mid_best = 0.5 * (data[\"BEST_ASK\"] + data[\"BEST_BID\"])\n", + "data[\"mid_ex\"] = mid_ex\n", + "data[\"mid_best\"] = mid_best\n", + "\n", + "# spread (abs)\n", + "spread_ex = data[\"ask_ex\"] - data[\"bid_ex\"]\n", + "spread_best = data[\"BEST_ASK\"] - data[\"BEST_BID\"]\n", + "\n", + "# depth rule (usually only applied to mid spread transactions)\n", + "data[\"bid_ask_size_ratio_ex\"] = data[\"bid_size_ex\"] / data[\"ask_size_ex\"]\n", + "\n", + "# Degree how much trade size is filled -> similar to trade size rule\n", + "# Trade size rule would just classify if\n", + "data[\"rel_bid_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"bid_size_ex\"]\n", + "data[\"rel_ask_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"ask_size_ex\"]\n", + "\n", + "# EMO / CLNV / quote rule\n", + "data[\"prox_ex\"] = (data[\"TRADE_PRICE\"] - mid_ex) / (0.5 * spread_ex)\n", + "data[\"prox_best\"] = (data[\"TRADE_PRICE\"] - mid_best) / (0.5 * spread_best)\n", + "\n", + "# custom\n", + "data[\"price_rel_nbo\"] = (data[\"TRADE_PRICE\"] - data[\"BEST_ASK\"]) / (\n", + " data[\"BEST_ASK\"] - mid_best\n", + ")\n", + "data[\"price_rel_nbb\"] = (data[\"TRADE_PRICE\"] - data[\"BEST_BID\"]) / (\n", + " mid_best - data[\"BEST_BID\"]\n", + ")\n", + "data[\"bid_ask_ratio_ex\"] = data[\"bid_ex\"] / data[\"ask_ex\"]\n", + "data[\"depth_ex\"] = data[\"bid_size_ex\"] - data[\"ask_size_ex\"]\n", + "\n", + "data[\"abs_mid_ex\"] = data[\"TRADE_PRICE\"] - mid_ex\n", + "data[\"abs_mid_BEST\"] = data[\"TRADE_PRICE\"] - mid_best\n", + "\n", + "data[\"spread_ex\"] = spread_ex\n", + "data[\"spread_best\"] = spread_best\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "M6gxVMmgNwQs" + }, + "source": [ + "### Underlying features πŸ«€" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "PaBwUMFzNsnu" + }, + "outputs": [], + "source": [ + "data[\"symbol_is_index\"] = data[\"ROOT\"].str.startswith(\"^\").astype(int)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 236 + }, + "id": "dWCeS44oY9Hj", + "outputId": "38f6ccc8-9606-40b2-cfda-40bab25d4152" + }, + "outputs": [], + "source": [ + "data.head()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "A0KFTHrDK5Uo" + }, + "source": [ + "### Categorical features 🎰" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l4ZbZXdlKbRT" + }, + "source": [ + "### Visualization helper 🐜" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "_jLvcBEyKfDi" + }, + "outputs": [], + "source": [ + "def plot_kde_target(var_name: str, clip: List[float] | None = None):\n", + " \"\"\"\n", + " Plot kde plots for buys (+1) and sells (-1) with regard to the feature 'var_name'.\n", + "\n", + " Args:\n", + " var_name (str): name of feature\n", + " clip (List[float] | None, optional): clipping range. Defaults to None.\n", + " \"\"\"\n", + " corr_var = data[\"buy_sell\"].corr(data[var_name])\n", + "\n", + " median_sell = data[data[\"buy_sell\"] == -1][var_name].median()\n", + " median_buy = data[data[\"buy_sell\"] == 1][var_name].median()\n", + "\n", + " _, ax = plt.subplots()\n", + " for i in [-1, 1]:\n", + " sns.kdeplot(\n", + " data=data[data[\"buy_sell\"] == i],\n", + " x=var_name,\n", + " clip=clip,\n", + " label=str(i),\n", + " cumulative=False,\n", + " common_grid=True,\n", + " )\n", + " ax.title.set_text(f\"Distribution of '{var_name}'\")\n", + " ax.legend()\n", + " sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n", + " plt.show()\n", + " print(\n", + " f\"The correlation between '{var_name}' and the 'buy_sell' is {corr_var: 0.4f}\"\n", + " )\n", + " print(f\"Median value of sells = {median_sell: 0.4f}\")\n", + " print(f\"Median value of buys = {median_buy: 0.4f}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "kmkh8Ze7Xys_" + }, + "outputs": [], + "source": [ + "def plot_kde_target_comparsion(\n", + " var_name: str,\n", + " clip: float | None = None,\n", + " years: List[int] = [2006, 2010, 2013],\n", + ") -> None:\n", + " \"\"\"\n", + " Plot several kde plots side by side for the feature.\n", + "\n", + " Args:\n", + " var_name (str): name of the feature\n", + " clip (float | None, optional): clipping range. Defaults to None.\n", + " years (List[int], optional): years to compare. Defaults to [2006, 2010, 2013].\n", + " \"\"\"\n", + " fig, ax = plt.subplots(nrows=1, ncols=len(years), figsize=(18, 4))\n", + "\n", + " fig.suptitle(f\"Distribution of `{var_name}`\")\n", + "\n", + " for y, year in enumerate(years):\n", + " for i in [-1, 1]:\n", + " sns.kdeplot(\n", + " data=data[(data[\"buy_sell\"] == i) & (data[\"year\"] == year)],\n", + " x=var_name,\n", + " clip=clip,\n", + " # supress any other but first label using '_'\n", + " # see https://stackoverflow.com/a/44633022/5755604\n", + " label=\"_\" * y + str(i),\n", + " cumulative=False,\n", + " common_grid=True,\n", + " ax=ax[y],\n", + " )\n", + " ax[y].xaxis.label.set_text(str(year))\n", + "\n", + " fig.legend()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "k9QXRQrxOCJ3" + }, + "outputs": [], + "source": [ + "us_rec = web.DataReader(\"USREC\", \"fred\", data[\"date\"].min(), data[\"date\"].max())\n", + "\n", + "\n", + "def plot_recessions() -> None:\n", + " \"\"\"\n", + " Add recession indicator to plot and entry to legend.\n", + " \"\"\"\n", + " l = 0\n", + " month = relativedelta.relativedelta(months=+1)\n", + " for date, val in us_rec[\"USREC\"].items():\n", + " if val == 1:\n", + " # if boolean = 1 -> print bar until next month\n", + " # '_' labels are ignored in legend https://stackoverflow.com/a/44633022/5755604\n", + " plt.axvspan(\n", + " date,\n", + " date + month,\n", + " edgecolor=\"none\",\n", + " alpha=0.25,\n", + " label=\"_\" * l + \"recession\",\n", + " )\n", + " l += 1\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "HHFM5-flQo-9" + }, + "outputs": [], + "source": [ + "def plot_time_series(\n", + " feature: str | List[str], aggregation: str | List[Any] = \"count\"\n", + ") -> pd.DataFrame:\n", + " \"\"\"\n", + " Plot feature over time. Aggregate using 'aggregation'.\n", + "\n", + " Args:\n", + " feature (str | List[str]): features to plot.\n", + " aggregation (str | List[Any], optional): aggregation operation. Defaults to \"count\".\n", + "\n", + " Returns:\n", + " pd.DataFrame: time series\n", + " \"\"\"\n", + " if isinstance(feature, str):\n", + " feature = [feature]\n", + " if isinstance(aggregation, str):\n", + " aggregation = [aggregation]\n", + "\n", + " time_series = data[feature].groupby(data[\"date\"]).agg(aggregation)\n", + " time_series.columns = time_series.columns.to_flat_index()\n", + "\n", + " ax = sns.lineplot(data=time_series)\n", + " ax.yaxis.label.set_text(\" / \".join(aggregation))\n", + " ax.title.set_text(f\"'{' / '.join(feature)}' over time\")\n", + " plot_recessions()\n", + " ax.legend()\n", + " plt.show()\n", + "\n", + " return time_series\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "6rbpLrGVKlqY", + "outputId": "1a470d5b-be8d-417c-a779-15778e71cbf4" + }, + "outputs": [], + "source": [ + "# select categorical e. g., option type and strings e. g., ticker\n", + "cat_columns = data.select_dtypes(include=[\"category\", \"object\"]).columns.tolist()\n", + "print(cat_columns)\n", + "\n", + "# assign \"bin_\" column prefix\n", + "cat_columns_bin = [\"bin_\" + x for x in cat_columns]\n", + "\n", + "# binarize categorical similar to Borisov et al.\n", + "data[cat_columns_bin] = data[cat_columns].apply(lambda x: pd.factorize(x)[0]) \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9vmqZlzAPHLF" + }, + "source": [ + "## General overview πŸŒ„" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ryHukUSOiFvs" + }, + "source": [ + "### Trade price and sizes 🀝" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TGlJU8wrm_J4" + }, + "source": [ + "#### Trades over time ⌚" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "CNdxNP8VnJ8m", + "outputId": "ec1aecfd-2817-4ed4-dce1-775d44d5b325" + }, + "outputs": [], + "source": [ + "trades_per_day = plot_time_series(\"TRADE_PRICE\", \"count\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "C5GRI4vE08RB", + "outputId": "857d0e7b-6d45-4811-c15f-07679580b616" + }, + "outputs": [], + "source": [ + "trades_per_day.iloc[:, 0].nlargest(N)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "DmK1pdA63P55", + "outputId": "db1f51cc-75e9-41da-8fd3-483bdf75ee07" + }, + "outputs": [], + "source": [ + "trades_per_day.iloc[:, 0].nsmallest(N)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "u4rLQllo9yWs" + }, + "source": [ + "**Observation:**\n", + "* Number of trades increases over time.\n", + "* There is no obvious explanation why the number of trades spikes at certain days." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YvBsMmZ0Rwro" + }, + "source": [ + "#### Trade size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "f-YPNDG3fzDO", + "outputId": "adb9ba84-973c-4db9-f90a-5c0c56642d15" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"TRADE_SIZE\", bins=50) \n", + "ax.title.set_text(\"Histogram of trade size\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "txa7AqLShrZn" + }, + "source": [ + "**Observation:**\n", + "* highly skewed with few outliers.\n", + "* Similar to the price, $\\log(\\cdot)$ transform could help." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "3oGv6NbNZ8mR", + "outputId": "c4cb8988-e100-4499-a278-934ea968eeb2" + }, + "outputs": [], + "source": [ + "trades_over_time = plot_time_series(\"TRADE_SIZE\", [\"mean\", \"median\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "_fm0mKy9nGWr", + "outputId": "aa8b4cb6-eda1-4d48-8213-be05f6e3debe" + }, + "outputs": [], + "source": [ + "trade_ask_bid_size = plot_time_series(\n", + " [\"TRADE_SIZE\", \"ask_size_ex\", \"bid_size_ex\"], \"mean\"\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "IKBxGSqe-FBC" + }, + "source": [ + "**Observation:**\n", + "* There is a slow downward trend in `TRADE_SIZE` (mean).\n", + "* Controversely, the number of trades per day (mean) increases over time.\n", + "* Market share of ISE has decrease over time, as reported in https://www.sifma.org/wp-content/uploads/2022/03/SIFMA-Insights-Market-Structure-Compendium-March-2022.pdf. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "PfPmlqkdhhiQ", + "outputId": "21cc85d6-6f43-4e66-a4b1-c76a8839da50" + }, + "outputs": [], + "source": [ + "data[\"TRADE_SIZE\"].describe()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + }, + "id": "dmKu4OXF-p9P", + "outputId": "cc65a9b2-552a-43c8-8df6-eb3597916f40" + }, + "outputs": [], + "source": [ + "data[data[\"TRADE_SIZE\"].max() == data[\"TRADE_SIZE\"]]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "ZL3iVg-mgrv1", + "outputId": "97444ae1-612f-4be5-c17a-c91576e8b27f" + }, + "outputs": [], + "source": [ + "data.nlargest(N, \"TRADE_SIZE\", keep=\"first\").T\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "eL3Lxj2yhrB4", + "outputId": "e7b356fb-afaa-4424-af70-4d2edda48726" + }, + "outputs": [], + "source": [ + "data[\"log_trade_size\"] = np.log1p(data[\"TRADE_SIZE\"])\n", + "ax = sns.histplot(data, x=\"log_trade_size\", bins=50) \n", + "ax.title.set_text(f\"Histogram of trade size (log1p)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "BQGC_grZ2quQ", + "outputId": "b73c0027-f7d8-4e19-b8b0-1569b010323d" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_trade_size\", clip=[0, 6])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0TbVsjVrwhG_" + }, + "source": [ + "**Observation:**\n", + "- Size features do hardly profit from a $\\log$ transform. Might want to keep as-is." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "kro_boa2VSpD" + }, + "source": [ + "#### Trade price" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "c2bA2XcPg0qg", + "outputId": "bfaa6076-a60b-41f5-dabd-9df36dc53404" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"TRADE_PRICE\", bins=50) \n", + "ax.title.set_text(\"Histogram of trade price\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "CULpt3OGoMBS", + "outputId": "25a6a024-47e6-4025-bbc8-d3d318365673" + }, + "outputs": [], + "source": [ + "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"TRADE_PRICE\")\n", + "ax.title.set_text(\"Box plot of 'TRADE_PRICE' for buys (1) and sells (-1)\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nKm00we7oQmJ" + }, + "source": [ + "**Observations:**\n", + "* Very few, very large trade prices, many very small trade prices.\n", + "* Scaling can be problematic, if outliers affect scaling much. Try $\\log(\\cdot)$ transform to correct skewness of distribution. Could improve results.\n", + "* Trade price is hardly informative, as distribution is very similar." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "k47VwHkJoYHj" + }, + "outputs": [], + "source": [ + "data[\"log_trade_price\"] = np.log1p(data[\"TRADE_PRICE\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 398 + }, + "id": "cULJ2a5voezf", + "outputId": "fff08c96-14cb-4031-a6be-900624f406f2" + }, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "\n", + "sns.histplot(data, x=\"log_trade_price\", bins=50, stat=\"density\", label=\"log price\") \n", + "\n", + "# extract the limits for the x-axis and fit normal distributon\n", + "x0, x1 = ax.get_xlim()\n", + "x_pdf = np.linspace(x0, x1, 100)\n", + "y_pdf = stats.norm.pdf(x_pdf)\n", + "\n", + "pdf = pd.DataFrame({\"x\": x_pdf, \"y\": y_pdf})\n", + "sns.lineplot(data=pdf, x=\"x\", y=\"y\", label=\"pdf\", color=\"r\")\n", + "\n", + "\n", + "ax.title.set_text(\"Distribution of log prices\")\n", + "ax.legend()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "9DpqVxM3o8G8", + "outputId": "b9ad92e2-da89-4dfc-9a67-98aa8b5440b4" + }, + "outputs": [], + "source": [ + "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"log_trade_price\")\n", + "ax.title.set_text(\"Box plot of log prices for buys (1) and sells (-1)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "lwtkIErXg8iZ", + "outputId": "b9a4e4c9-3e4f-496d-fac9-a5b5c22e36f4" + }, + "outputs": [], + "source": [ + "data.nlargest(N, \"TRADE_PRICE\", keep=\"first\").T\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "5HndBdq-hKmJ", + "outputId": "2f721ab4-3827-441b-ca08-6c627a4b457d" + }, + "outputs": [], + "source": [ + "trade_price_over_time = plot_time_series(\"TRADE_PRICE\", [\"mean\", \"median\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "DhvRYVA-pjzX", + "outputId": "86cf5bfa-9a17-4481-a346-e1d8bbda25f4" + }, + "outputs": [], + "source": [ + "trade_price_over_time = plot_time_series(\n", + " [\"TRADE_PRICE\", \"price_ex_lead\", \"price_ex_lag\"], \"mean\"\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "bTNiMADmqxI4", + "outputId": "1440ed7d-2dfa-42dc-8778-e519b3e0cb3a" + }, + "outputs": [], + "source": [ + "trade_price_over_time = plot_time_series(\n", + " [\"TRADE_PRICE\", \"price_ex_lead\", \"price_ex_lag\"], \"median\"\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Z234Di7gwhHD" + }, + "source": [ + "**Observation:**\n", + "* `TRADE_PRICE` remains roughly constant over time. Median decreases over time.\n", + "* Large difference between median and mean. " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "S5rHAylRzt1d" + }, + "source": [ + "### Time to maturity ⌚" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "YOtWJYd1mRAx", + "outputId": "ca0c87b0-b957-4b70-cde4-bc028a206521" + }, + "outputs": [], + "source": [ + "ttm_over_time = plot_time_series(\"ttm\", \"mean\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "WIiLkBmymu6n", + "outputId": "9a1b8ae7-4002-425f-d843-c728654c9222" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data=data[data[\"bid_ex\"] == 0.0], x=\"ttm\", bins=50) \n", + "ax.title.set_text(\"Count of transactions with regard to time to maturity (months)\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uEYVInVtwhHF" + }, + "source": [ + "**Observation:**\n", + "- Most options have a short time-to-maturity\n", + "- Binning or cut-off could be helpful" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "HIPLWci8m2MD", + "outputId": "808cf9b4-1954-4ff4-f19e-0bfbf7c1db02" + }, + "outputs": [], + "source": [ + "# TODO: ask of zero plausible?\n", + "sns.histplot(data=data[data[\"ask_ex\"] == 0.0], x=\"ttm\", bins=50) \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "q5WCxCtC6N1r" + }, + "source": [ + "### Strike price" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "shLvgI6_6pob", + "outputId": "922e91ab-de04-4135-b03c-3d4b07adcdf0" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"STRK_PRC\", bins=50) \n", + "ax.title.set_text(\"Histogram of strike price\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "FF4T32MV7MRf", + "outputId": "0473dab3-ee9b-42a3-9be3-b25ade066846" + }, + "outputs": [], + "source": [ + "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"STRK_PRC\")\n", + "ax.title.set_text(\"Box plot of strike prices for buys (1) and sells (-1)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "v0YTFt-Y6QlA", + "outputId": "f0b3388f-d801-4b31-cb53-b74b13a1cff6" + }, + "outputs": [], + "source": [ + "strike_over_time = plot_time_series(\"STRK_PRC\", \"mean\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "ai93sNiywhHI" + }, + "source": [ + "**Observation:**\n", + "- Distribution of strike price is highly skewed\n", + "- Average strike price grows over time. Thus, very large and previously unobserved trade prices could be part of the test set, but not in the train set.\n", + "- Try $\\log$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "E4zueI8_6_zh" + }, + "outputs": [], + "source": [ + "data[\"log_strk_prc\"] = np.log1p(data[\"STRK_PRC\"])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "HsYMWQOs6jUt", + "outputId": "b3eab404-16e8-46ce-a9a5-8d78b217d58e" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"log_strk_prc\", bins=50) \n", + "ax.title.set_text(\"Histogram of strike price (log1p)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "ubhwxzaO7jD0", + "outputId": "fbf6839f-2903-4a0d-db26-c6b89843d797" + }, + "outputs": [], + "source": [ + "ax = sns.boxplot(data=data, x=\"buy_sell\", y=\"log_strk_prc\")\n", + "ax.title.set_text(\"Box plot of strike prices for buys (1) and sells (-1)\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "9of8S3X52_WS" + }, + "source": [ + "### Buy Sell πŸ‘›" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "EpSh473iHU3W", + "outputId": "76566198-8e47-420a-8884-cef391e1b477" + }, + "outputs": [], + "source": [ + "ratio_buy_sell = data[\"buy_sell\"].value_counts() / data[\"buy_sell\"].count()\n", + "ratio_buy_sell.head()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "deJhfCrxHy8Y" + }, + "source": [ + "**Observation:**\n", + "* Ratios similar to the one reported in Grauer et. al. Yet not identical as calculation is done on a sample.\n", + "* As both classes have a $\\approx~0.5$ probability, I would not rebalance. Rebalancing through sampling etc. itself has a bias.\n", + "* Ratios seem to be stable over time (see below). Thus, distribution is similar for training, validation, and test set.\n", + "* With regard to time-to-maturity the distribution changes slightly for longer periods." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "IYXjbdNOScZ5" + }, + "source": [ + "#### By option type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 431 + }, + "id": "r4zDI-vV4QHT", + "outputId": "128120ff-5846-4e26-b121-3c90cbfc5633" + }, + "outputs": [], + "source": [ + "ax = sns.countplot(data=data, x=\"OPTION_TYPE\", hue=\"buy_sell\")\n", + "ax.title.set_text(\"Distribution of Buy / Sell indicator with regard to option type\")\n", + "sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3pOzIcdrSjaU" + }, + "source": [ + "#### By year" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 405 + }, + "id": "L1rT2d3m2-8L", + "outputId": "bf6a4809-5585-4e6a-94d2-c7969cb3292a" + }, + "outputs": [], + "source": [ + "ax = sns.countplot(data=data, x=\"year_binned\", hue=\"buy_sell\")\n", + "ax.title.set_text(\"Distribution of Buy / Sell indicator with regard to year (binned)\")\n", + "ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha=\"center\")\n", + "plt.tight_layout()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "LO_Y_3LlSoOq" + }, + "source": [ + "#### By time time to maturity" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 405 + }, + "id": "mhZopwr-4ITf", + "outputId": "341b30a7-6a9c-44d9-ba4d-fe45145dd8b9" + }, + "outputs": [], + "source": [ + "ax = sns.countplot(data=data, x=\"ttm_binned\", hue=\"buy_sell\")\n", + "ax.title.set_text(\n", + " \"Distribution of Buy / Sell indicator with regard to time to maturity (binned)\"\n", + ")\n", + "ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha=\"center\")\n", + "plt.tight_layout()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "vCaz459vUzIM", + "outputId": "e91328c8-9367-41ee-ba13-56a6161f356d" + }, + "outputs": [], + "source": [ + "ax = sns.scatterplot(data=sample, x=\"ttm\", y=\"bid_ex\", hue=\"OPTION_TYPE\")\n", + "ax.title.set_text(\"Scatter plot of time to maturity (months) and bid (ex)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "fkEKGH4-RDHc", + "outputId": "4cf0dd8f-4d50-42a0-9c54-be7e81e59b11" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data=data[data[\"bid_ex\"] == 0.0], x=\"ttm\", bins=50) \n", + "ax.title.set_text(\"Count of transactions with regard to time to maturity (months)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "YNF09VisR6ox", + "outputId": "ee9fcbd9-3632-43a8-995d-8d38f9889a3b" + }, + "outputs": [], + "source": [ + "# TODO: ask of zero plausible?\n", + "sns.histplot(data=data[data[\"ask_ex\"] == 0.0], x=\"ttm\", bins=50) \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VKOYYMjdSwmq" + }, + "source": [ + "#### Over time" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 571 + }, + "id": "gR6c5UUC3WHf", + "outputId": "f92abde5-5df1-446b-ce09-e1a78f0b8a3c" + }, + "outputs": [], + "source": [ + "trades_over_time = (\n", + " data.groupby(data[\"date\"])[\"buy_sell\"].value_counts().unstack(fill_value=0)\n", + ")\n", + "ax = trades_over_time.plot(\n", + " kind=\"line\",\n", + " figsize=ratio,\n", + " title=\"buy / sell count over time\",\n", + " xlabel=\"date\",\n", + " ylabel=\"sell (-1) / buy (1)\",\n", + ")\n", + "plot_recessions()\n", + "ax.legend()\n", + "plt.show()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "uNN4ksMGlTQm" + }, + "source": [ + "### $n$ most frequent symbols, indices, and special codes πŸ”’" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "waAefSrZY9Ij" + }, + "source": [ + "See how frequent symbols are, as they can lead to an explosion in cardinality." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "znjnZIdMY9Ik", + "outputId": "cced72f2-2128-44cf-b594-16b625a6b26e" + }, + "outputs": [], + "source": [ + "frequency_symbols = data[\"ROOT\"].value_counts().reset_index(name=\"Count\")\n", + "frequency_symbols.rename(columns={\"index\": \"Symbol\"}, inplace=True)\n", + "frequency_symbols.sort_values(\"Count\", ascending=True)\n", + "sns.histplot(data=frequency_symbols, x=\"Count\", bins=200)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "5aRfobVAY9Il", + "outputId": "e19feb4f-4591-487a-dd33-a1af7b1666b6" + }, + "outputs": [], + "source": [ + "frequency_symbols[frequency_symbols[\"Count\"] <= 5].count()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "cLvzcvrQY9Im", + "outputId": "dcdddacf-a78f-43a7-9c3c-fdf89d4b14c1" + }, + "outputs": [], + "source": [ + "frequency_symbols\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 726 + }, + "id": "qLVCUu8WOqGG", + "outputId": "8058bfb0-031a-4d61-ebda-b84cb7e9d5a7" + }, + "outputs": [], + "source": [ + "most_frequent_symbols = data[\"ROOT\"].value_counts().head(N).reset_index(name=\"Count\")\n", + "most_frequent_symbols.rename(columns={\"index\": \"Symbol\"}, inplace=True)\n", + "\n", + "ax = sns.barplot(data=most_frequent_symbols, x=\"Symbol\", y=\"Count\")\n", + "ax.title.set_text(f\"{N} most frequently traded symbols\")\n", + "\n", + "most_frequent_symbols.head(N)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "balcupvypq5_" + }, + "outputs": [], + "source": [ + "list_freq_symbols = most_frequent_symbols.Symbol.tolist()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "vxI2kyFypzmb" + }, + "outputs": [], + "source": [ + "frequent_symbols_over_time = data[data[\"ROOT\"].isin(list_freq_symbols)]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Ui_bSf3JrdjE" + }, + "outputs": [], + "source": [ + "frequent_symbols_trades_per_day = (\n", + " frequent_symbols_over_time.groupby(\n", + " [frequent_symbols_over_time.QUOTE_DATETIME.dt.to_period(\"m\"), \"ROOT\"]\n", + " )[\"TRADE_SIZE\"]\n", + " .count()\n", + " .reset_index()\n", + " .rename(columns={\"TRADE_SIZE\": \"count\", \"QUOTE_DATETIME\": \"date\", \"ROOT\": \"Symbol\"})\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "r9NQn8JojaHq" + }, + "outputs": [], + "source": [ + "frequent_symbols_over_time = (\n", + " frequent_symbols_trades_per_day.groupby([\"date\", \"Symbol\"])[\"count\"]\n", + " .first()\n", + " .unstack()\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 397 + }, + "id": "xKynCukCly3K", + "outputId": "5f968ff8-407c-4c00-e44c-d909380719dd" + }, + "outputs": [], + "source": [ + "frequent_symbols_over_time.plot(\n", + " kind=\"line\", title=f\"{N} most frequently traded underlyings over time\"\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "SvzXOQXJY9Ir" + }, + "outputs": [], + "source": [ + "root_time_train = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/train_set_extended_60.parquet\",\n", + " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", + ")\n", + "root_time_val = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/val_set_extended_20.parquet\",\n", + " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", + ")\n", + "root_time_test = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/preprocessed/test_set_extended_20.parquet\",\n", + " columns=[\"QUOTE_DATETIME\", \"ROOT\"],\n", + ")\n", + "\n", + "roots_over_time = pd.concat([root_time_train, root_time_val, root_time_test])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "f1GkQvJQY9Is" + }, + "outputs": [], + "source": [ + "# randomly sample N symbols and check when they appear for the first and last time\n", + "roots_sample = (\n", + " roots_over_time.groupby(\"ROOT\")[\"QUOTE_DATETIME\"]\n", + " .agg([\"min\", \"max\"])\n", + " .reset_index()\n", + " .sample(N)\n", + " .T\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "9Myp0ocfY9It" + }, + "outputs": [], + "source": [ + "# see 2.0-mb-data_preprocessing_loading_splitting.ipynb\n", + "dti = pd.date_range(\"2005-05-02\", \"2017-05-31\", freq=\"d\")\n", + "plot_df = pd.DataFrame(index=dti)\n", + "\n", + "for i, col in enumerate(roots_sample.columns):\n", + " plot_df[roots_sample.iloc[0, i]] = np.where(\n", + " np.logical_and(\n", + " plot_df.index >= roots_sample.iloc[1, i],\n", + " plot_df.index <= roots_sample.iloc[2, i],\n", + " ),\n", + " i / N,\n", + " np.nan,\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 383 + }, + "id": "gz4UzN30Y9Iu", + "outputId": "fa727147-f8b8-444f-e29e-082165c6bb77" + }, + "outputs": [], + "source": [ + "ax = plot_df.plot(legend=False, style=\".\")\n", + "ax.set_yticks(np.linspace(0, (N - 1) / N, N))\n", + "ax.set_yticklabels(plot_df.columns)\n", + "# beginning of validation and test set\n", + "ax.axvline(\"2013-10-25\", color=\"gray\")\n", + "ax.axvline(\"2015-11-06\", color=\"gray\")\n", + "ax.set_title(\"roots over time (min / max appearance)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 431 + }, + "id": "S-Kd5_JSOO6R", + "outputId": "6dad31cd-2920-4226-e668-6910c0ce98b3" + }, + "outputs": [], + "source": [ + "# TODO: investigate why there is no True group\n", + "ax = sns.countplot(data=data, x=\"symbol_is_index\", hue=\"buy_sell\")\n", + "ax.title.set_text(\n", + " \"Distribution of Buy / Sell indicator with regard to whether underlying is an index\"\n", + ")\n", + "sns.move_legend(ax, \"lower center\", bbox_to_anchor=(0.5, -0.3))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "9ZPOB0DDPlaA", + "outputId": "dd796dd9-5e4e-4500-df78-39f3e06ae8aa" + }, + "outputs": [], + "source": [ + "ratios_is_index = (\n", + " data.groupby([\"symbol_is_index\", \"buy_sell\"])[\"buy_sell\"].count()\n", + " / data.groupby([\"symbol_is_index\"])[\"buy_sell\"].count()\n", + ")\n", + "ratios_is_index.head()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "cvLHx_iNOtgo" + }, + "source": [ + "**Observation:**\n", + "- Feature can be important, as it's much more likely for trade to be sell, rather than buy, if and only if the underlying is no index option.\n", + "- Difference isn't too pronounced and could be due to sampling effects." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "7cm4CSLELZLy", + "outputId": "3d3531b2-a7d0-4610-e5c1-b7eb1d764d3a" + }, + "outputs": [], + "source": [ + "data[\"issue_type\"].value_counts(dropna=False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "hI-NvLxx_p1P", + "outputId": "237340be-a1bb-4b4a-8159-b7720477c445" + }, + "outputs": [], + "source": [ + "ax = sns.countplot(data=data, x=\"issue_type\")\n", + "ax.title.set_text(\"No. of transactions by issue type\")\n", + "ax.xaxis.label.set_text(\"issue type\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "puN3bdGmUPLh" + }, + "source": [ + "### Ask and bidπŸ‘¨β€βš–οΈ" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 380 + }, + "id": "ObXgSwSxq2E_", + "outputId": "30df67d5-2601-4921-cf1b-a0c21db8f55a" + }, + "outputs": [], + "source": [ + "bid_ask_over_time = plot_time_series(\n", + " [\"bid_ex\", \"ask_ex\", \"BEST_ASK\", \"BEST_BID\"], \"mean\"\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "bS2PiyAl8XYP" + }, + "source": [ + "#### Ask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "KwtMkQfIUPLi", + "outputId": "88b78791-b8fd-40ce-ccc7-8410ddf4a763" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"ask_ex\", bins=50) \n", + "ax.title.set_text(\"Histogram of ask (exchange)\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "MrinpS5KwhHX" + }, + "source": [ + "**Observation:**\n", + "* Distribution is highly skewed, try correction with $\\log$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "t9Od_ss68Uf7", + "outputId": "0dbb2688-1e93-4e5d-82bc-51889dd8011e" + }, + "outputs": [], + "source": [ + "data[\"log_ask_ex\"] = np.log1p(data[\"ask_ex\"])\n", + "ax = sns.histplot(data, x=\"log_ask_ex\", bins=50) \n", + "ax.title.set_text(f\"Histogram of ask exchange (log1p)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "JHc4tuDw8UHG", + "outputId": "1d102fa7-b1b9-4871-e7d8-f726bb262b33" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_ask_ex\", clip=[0, 5])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hneiYOS1whHY" + }, + "source": [ + "**Observation:**\n", + "* Applying a $\\log$ transform leads to a easily distinguishable distribution" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "7jVN_izn8a43" + }, + "source": [ + "#### Bid" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "qap6DPAb8if7", + "outputId": "d0f16e78-d0d2-46f1-aef1-2f8979f9f989" + }, + "outputs": [], + "source": [ + "ax = sns.histplot(data, x=\"bid_ex\", bins=50) \n", + "ax.title.set_text(\"Histogram of bid (exchange)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "3w88oBOpUPLj", + "outputId": "cf90db94-d616-4191-836e-56c0d784cd43" + }, + "outputs": [], + "source": [ + "data[\"log_bid_ex\"] = np.log1p(data[\"bid_ex\"])\n", + "ax = sns.histplot(data, x=\"log_bid_ex\", bins=50) \n", + "ax.title.set_text(f\"Histogram of bid exchange (log1p)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "hlsQokLcUPLj", + "outputId": "5b8d9db8-5d10-4b9c-a907-cf5f666defcb" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_bid_ex\", clip=[0, 5])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 381 + }, + "id": "_JBE-ymdUPLk", + "outputId": "cd61daed-cfeb-45da-9fa4-a31278e884a6" + }, + "outputs": [], + "source": [ + "data[\"log_bid_ex\"] = np.log1p(data[\"bid_ex\"])\n", + "ax = sns.histplot(data, x=\"log_bid_ex\", bins=50) \n", + "ax.title.set_text(\"Histogram of bid exchange (log1p)\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "biafaSUqUPLk", + "outputId": "8d4404c6-79e4-4e6e-eed7-11d14e58d4d7" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_bid_ex\", clip=[-5, 6])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vesyvNMPUPLk" + }, + "source": [ + "**Observation:**\n", + "- One can choose different constants, but small constants, e. g., `const=1e-2` gives fuzzy, yet distributions that are easier to distinguish. Also note the higher correlation with the target. \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "fnrbwIFTYHr_" + }, + "source": [ + "**Observation:**\n", + "- log on size seems to worsen results.\n", + "- `TODO:` investigate further, what the reason is. e. g., how many outliers..." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "UUbWmbEtS2Ve" + }, + "source": [ + "# NaNs πŸͺ²" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "lYGJpMvzEhyc" + }, + "outputs": [], + "source": [ + "def visualize_nan():\n", + " \"\"\"\n", + " Visualize NaN values in a heatmap to learn about patterns.\n", + " \"\"\"\n", + " plt.subplots()\n", + " sns.heatmap(data.head(50).isnull(), cbar=False)\n", + " plt.xlabel(\"feature\")\n", + " plt.ylabel(\"row\")\n", + " plt.title(\"Missing values (colored in bright beige)\")\n", + " plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 470 + }, + "id": "glhx2wHHEtkU", + "outputId": "a26fefb3-fff4-4910-c8bb-01972d6d81a7" + }, + "outputs": [], + "source": [ + "visualize_nan()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 668 + }, + "id": "2JOoXJtHIKXE", + "outputId": "32053749-fa94-4608-c354-6dfa65e7a326" + }, + "outputs": [], + "source": [ + "isna_vals = data.isna().sum().sort_values(ascending=False)\n", + "isna_vals = isna_vals.loc[lambda x: x > 0]\n", + "\n", + "ax = isna_vals.T.plot(\n", + " kind=\"bar\",\n", + " figsize=ratio,\n", + " legend=False,\n", + " xlabel=\"No. of missing values\",\n", + " ylabel=\"feature\",\n", + " title=\"Missing values\",\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 588 + }, + "id": "swu5wGjNLZbF", + "outputId": "b04cb287-4483-48bb-f41f-77cca1c34bb8" + }, + "outputs": [], + "source": [ + "isna_vals_over_time = (\n", + " data[isna_vals.index.tolist()]\n", + " .groupby(data[\"QUOTE_DATETIME\"].dt.date)\n", + " .agg(lambda x: x.isnull().sum())\n", + ")\n", + "isna_vals_over_time.plot(\n", + " kind=\"line\",\n", + " figsize=ratio,\n", + " title=\"Missing values over time\",\n", + " xlabel=\"Timestamp\",\n", + " ylabel=\"No. of missing values\",\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 654 + }, + "id": "Bk7kdwU0Nh9X", + "outputId": "761bca49-09cf-4dac-c9be-09f9604a693b" + }, + "outputs": [], + "source": [ + "# adapted from: https://github.com/ResidentMario/missingno/blob/master/missingno/missingno.py\n", + "\n", + "isna_data = data.iloc[\n", + " :, [i for i, n in enumerate(np.var(data.isnull(), axis=\"rows\")) if n > 0]\n", + "]\n", + "\n", + "corr_mat = isna_data.isnull().corr()\n", + "mask = np.zeros_like(corr_mat)\n", + "mask[np.triu_indices_from(mask)] = True\n", + "\n", + "fig, ax = plt.subplots(figsize=(9, 9))\n", + "ax = sns.heatmap(corr_mat, mask=mask, annot=False, annot_kws={\"size\": 10}, ax=ax)\n", + "ax.title.set_text(\"Correlation between missing features\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 446 + }, + "id": "Dokt9B3BEvor", + "outputId": "bc9ccd5a-4d1f-488b-c4bf-b2978744a414" + }, + "outputs": [], + "source": [ + "# adapted from: https://github.com/ResidentMario/missingno/blob/master/missingno/missingno.py\n", + "\n", + "# sample down for performance reasons\n", + "isna_data = data.sample(frac=0.05)\n", + "\n", + "plt.figure()\n", + "ax0 = plt.gca()\n", + "\n", + "# Link the hierarchical output matrix, figure out orientation, construct base dendrogram.\n", + "x = np.transpose(isna_data.isnull().astype(int).values)\n", + "z = hierarchy.linkage(x, \"average\")\n", + "\n", + "hierarchy.dendrogram(\n", + " z,\n", + " labels=isna_data.columns.tolist(),\n", + " distance_sort=False,\n", + " link_color_func=lambda c: \"black\",\n", + " ax=ax0,\n", + ")\n", + "\n", + "# Remove extraneous default visual elements.\n", + "ax0.set_aspect(\"auto\")\n", + "ax0.set_title(\"Dendrogram of missing values\")\n", + "\n", + "ax0\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "dXduwXBWwhHl" + }, + "source": [ + "**Observation:**\n", + "- Note that also important features like `price_all_lead` or `price_ex_lag` are missing. This has an impact, whether it is possible to calculate the classical rules like the trade rule. Consider this when reporting results.\n", + "- Missing values become more of a problem towards the end of the data set. At the same time the number of trades also increases." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "hB5ZELdNm8fG" + }, + "source": [ + "# Correlations of engineered features 🎲" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Wq61_ag29Sxe" + }, + "source": [ + "### Correlations 🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 482 + }, + "id": "WwYnaW2zwJ9e", + "outputId": "2c430d9f-a63d-470b-e658-e5aaadc2cb3c" + }, + "outputs": [], + "source": [ + "corr = data.corr()\n", + "\n", + "sns.heatmap(corr, xticklabels=corr.columns.values, yticklabels=corr.columns.values) \n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8KUisq6b5TeN" + }, + "source": [ + "### Correlation with target 🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + }, + "id": "TeyU4_ev4gzx", + "outputId": "2b1d054d-f525-401d-8c18-2dcd560e33f1" + }, + "outputs": [], + "source": [ + "sort_criteria = corr[\"buy_sell\"].abs().sort_values(ascending=False)\n", + "corr_target = corr.sort_values(\"buy_sell\", ascending=False)[\"buy_sell\"]\n", + "corr_target.loc[sort_criteria.index].to_frame()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "KP4WCZV54j_0", + "outputId": "fe13968d-59a7-47f6-b377-7aedbdad4fd5" + }, + "outputs": [], + "source": [ + "# adapted from here: https://www.kaggle.com/code/willkoehrsen/featuretools-for-good\n", + "\n", + "# Select upper triangle of correlation matrix\n", + "upper = corr.where(np.triu(np.ones(corr.shape), k=1).astype(bool))\n", + "\n", + "# Find index of feature columns with correlation greater than 0.95\n", + "to_drop = [column for column in upper.columns if any(abs(upper[column]) > 0.975)]\n", + "\n", + "print(to_drop)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0DFHkf2rwhHn" + }, + "source": [ + "**Observation:**\n", + "- Newly engineered features have a high correlation with the target, which is positive. Investigate if the correlation is due to randomness or whether a pattern is observable.\n", + "- `_ex` and `BEST_` features seem to be rather redundant, even if a high threshold for correlation is chosen." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "1_T0SJq85dBz" + }, + "source": [ + "### Collinearity of features🎲" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "2AzhGW0P4qf0", + "outputId": "0e925abf-372e-453a-ec82-9a6f1e6d64c4" + }, + "outputs": [], + "source": [ + "# Set the threshold\n", + "threshold = 0.975\n", + "\n", + "# Empty dictionary to hold correlated variables\n", + "above_threshold_vars = {}\n", + "\n", + "# For each column, record the variables that are above the threshold\n", + "for col in corr:\n", + " above_threshold_vars[col] = list(corr.index[corr[col] > threshold])\n", + "\n", + "pd.Series(above_threshold_vars)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Si_KbJ4L9vXX" + }, + "source": [ + "# Analyses of engineered features" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 110 + }, + "id": "Ia0PqSQ1-Ky1", + "outputId": "249d3820-8779-4b3d-b399-68cf926d8562" + }, + "outputs": [], + "source": [ + "corr_target.loc[sort_criteria.index].to_frame().T\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "8ZqYGILc-F35" + }, + "source": [ + "### What works βœ”οΈ" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "eqCs_1OnhisK" + }, + "source": [ + "#### Trade price vs distance from mid\n", + "\n", + "Similar to `EMO`, where the applied rule depends on whether the trade is at the ask or bid. Similarily `CLVN` uses percentage bounds e. g., $~20~\\%$ of spread." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "A1y0c6y0hqtB", + "outputId": "0fddf5eb-a51d-4082-84fe-619bb690532c" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"prox_ex\", clip=[-2, 2])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "eblbyBtLh32U", + "outputId": "3b7b6db7-db3e-4534-c778-fa2389f7aa02" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"prox_ex\", years=[2006, 2010, 2013], clip=[-2, 2])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Jc3nlqEai9aa" + }, + "source": [ + "#### Depth\n", + "\n", + "Implicitly used in depth rule. Depth rule would assign a buy if `bid_ask_size_ratio_ex` is above one and a sell if it is below zero. But only used for mid-spread trades." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "WugmHPe5jAXi", + "outputId": "1ef9dd30-5f93-4468-933b-cb9cb69db9d7" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"bid_ask_size_ratio_ex\", clip=[0, 100])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "EelrGS3ijA2d", + "outputId": "b23088da-5cea-4eb6-e642-6d966bb95741" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\n", + " \"bid_ask_size_ratio_ex\", years=[2006, 2010, 2013], clip=[0, 100]\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "La0E9-xeDznH" + }, + "source": [ + "#### $\\log$ bid ex" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "azwaPAaR-hMH", + "outputId": "da0d0833-13b6-45be-ee1f-c4d1de93a19e" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_bid_ex\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "bD0Vrrue-3bI", + "outputId": "6d5ecd65-97ff-47c5-e0c7-c978999d6ded" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"log_bid_ex\", years=[2006, 2010, 2013])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "nMDoG_7ZwhHu" + }, + "source": [ + "**Observation:**\n", + "- Application of the $\\log$ leads to highly differentiable distributions, that remain stable over time." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mAnyPoUuDvmW" + }, + "source": [ + "#### $\\log$ trade price" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "7UYh_BnU_MeW", + "outputId": "56e56a26-1e71-461a-81c0-8d2828c343cb" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_trade_price\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "83OwlI_H_X6e", + "outputId": "68ed276e-fdcf-411b-b50e-0cbe6e92905b" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"log_trade_price\", years=[2006, 2010, 2013])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KNqBQJWwwhHv" + }, + "source": [ + "**Observation:**\n", + "- Application of the $\\log$ leads to highly differentiable distributions, that remain stable over time." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gpdek3I2DsIS" + }, + "source": [ + "#### Ask size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "mhljYe2-_xlb", + "outputId": "8e6edcc4-4447-4e1e-ff44-a7a0b9cee687" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"ask_size_ex\", clip=[0, 2000])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "6WLZVYMTAISn", + "outputId": "ae4d16da-5c95-4985-e41f-1a0c7f6214e7" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"ask_size_ex\", years=[2006, 2010, 2013], clip=[0, 2000])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "NC-jnOsVDo4b" + }, + "source": [ + "#### Bid size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "7auGIaX5AtuF", + "outputId": "102c88e5-b9c8-441a-b467-6880fdc96409" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"bid_size_ex\", clip=[0, 1000])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "k4d6zmPJBbQe", + "outputId": "d7444269-ae64-42fd-faf1-2c399a697ba7" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"bid_size_ex\", years=[2006, 2010, 2013], clip=[0, 1000])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "VL6hJO_ADgrS" + }, + "source": [ + "#### Quote rule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "y8nKJs-xCHvF", + "outputId": "8123dcb6-26ea-42d9-aeba-97b37d033c7b" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"abs_mid_ex\", clip=[-0.5, 0.5])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "YkRp65M7CN7M", + "outputId": "e3c2b158-d139-4f2c-8951-6339dcd78100" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"abs_mid_ex\", years=[2006, 2010, 2013], clip=[-0.5, 0.5])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "xHh4GiFOwhHy" + }, + "source": [ + "**Observation:**\n", + "- Compared with tick rule or reverse tick rule, quote rule is the only classical rule, where distributions are somewhat distinguishable\n", + "- On can clearly see that the quote rule works better at the beginning of the data set and its performance worsens over time." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "JljvKUsVEL6H" + }, + "source": [ + "#### Day of the month" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "wvhCypnJD6_y", + "outputId": "0ac7f3c4-449b-4442-9369-56ee57ce0441" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"day\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "j2pP-JoWGT3a", + "outputId": "89da927d-9628-4f45-fc27-5755cb81f4d6" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"year\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "GU6-LKPrGftY" + }, + "source": [ + "**Observation:**\n", + "* Judging from the plot there seems to be a seasonal pattern e. g., more buys \n", + "at the beginning of the month and more sells towards the end of the month. \n", + "* Due to the distributions it could make sense to include date features in some feature sets. But do not include in the most basic data set." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "KDAoxtxJ-TkV" + }, + "source": [ + "## What doesn't ❌" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vm-KQmTLFAhR" + }, + "source": [ + "#### tick rule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "HgyVpqkhAn2A", + "outputId": "a9ad17e6-fb4a-428d-e75f-8e18b0e46f0f" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"chg_ex_lead\", clip=[-5, 5])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "QjY46fg-Fn4q", + "outputId": "d3a069e2-3f0c-41a1-e0b1-ed78b0178507" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"chg_ex_lead\", years=[2006, 2010, 2013], clip=[-5, 5])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "s_60zom2whH1" + }, + "source": [ + "**Observation:**\n", + "- Distributions are hardly distinguishable. \n", + "- Results seem to worsen over time, which is consistent to the observations of Grauer et. al." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Vc3gKTf7FHID" + }, + "source": [ + "#### reverse tick rule" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "V-XTdok0FKJw", + "outputId": "01b29cc6-f889-4b98-9718-eec0047b016e" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"chg_ex_lag\", years=[2006, 2010, 2013], clip=[-5, 5])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 312 + }, + "id": "1egDxKiVF3x_", + "outputId": "4460c8ce-13fb-4d30-b6ad-1dab281233cf" + }, + "outputs": [], + "source": [ + "plot_kde_target_comparsion(\"chg_ex_lag\", years=[2006, 2010, 2013], clip=[-5, 5])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "d7F0yjcxwhH2" + }, + "source": [ + "**Observation:**\n", + "- Distributions are hardly distinguishable. \n", + "- Results worsen over time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "mCid1bvHUPuu", + "outputId": "9f615b6f-4162-44e4-f699-9f2a910c0454" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_bid_ex\", clip=[-5, 8])\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "UY_U1fSnU9w-" + }, + "outputs": [], + "source": [ + "data.replace([np.inf, -np.inf], np.nan, inplace=True)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "7DuDX2elUTE7" + }, + "outputs": [], + "source": [ + "scaler = StandardScaler()\n", + "data[\"log_bid_ex_scaled\"] = scaler.fit_transform(\n", + " X=data[\"log_bid_ex\"].values.reshape(-1, 1)\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "zsdRVJVTWGUe", + "outputId": "83bbe197-c18e-4f44-b29c-5c250586b2da" + }, + "outputs": [], + "source": [ + "data[\"log_bid_ex_scaled\"].describe()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 483 + }, + "id": "cJVUGKqMUjWY", + "outputId": "88145966-8677-476b-ee33-a8bc0ef55999" + }, + "outputs": [], + "source": [ + "plot_kde_target(\"log_bid_ex_scaled\", clip=[-5, 5])\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "TDCrqcp8Y9Js" + }, + "source": [ + "Results as expected. Scaling using `StandardScaler` does not affect distribution of data." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "F781YhmiGY_u" + }, + "source": [ + "# Conclusion πŸ”—\n", + "\n", + "**Observation:**\n", + "* $log$ transform makes no difference for gbms as shown in `3.0b-mb-comparsion-transformations.ipynb`. This is consistent with literature, as trees don't consider distributions. $log$\n", + "* Imputation makes hardly any differnce for gbms as shown in `3.0b-mb-comparsion-transformations.ipynb`. Passing missing values to the model yields slightly better results. This is also expected.\n", + "* Incorporating highly correlated columns is no problem for gbms and neural nets from a theoretical standpoint.\n", + "- Features of Grauer et. al seem to work. \n", + "- Binning gives mixed results e. g., for trade size and ttm.\n", + "- Theoretically, highly correlated columns don't matter for gradient boosting and neural networks.\n" + ] + } + ], + "metadata": { + "colab": { + "machine_shape": "hm", + "name": "Untitled2.ipynb", + "provenance": [] + }, + "gpuClass": "premium", + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.4 (tags/v3.9.4:1f2e308, Apr 6 2021, 13:40:21) [MSC v.1928 64 bit (AMD64)]" + }, + "vscode": { + "interpreter": { + "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/3.0c-feature-engineering.ipynb b/notebooks/3.0c-feature-engineering.ipynb index 6e94856b..842e4f5b 100644 --- a/notebooks/3.0c-feature-engineering.ipynb +++ b/notebooks/3.0c-feature-engineering.ipynb @@ -1,1029 +1,1029 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "7WXF7w4VyVgG", - "tags": [] - }, - "outputs": [], - "source": [ - "import gc\n", - "import os\n", - "import pickle\n", - "from pathlib import Path\n", - "from typing import Literal\n", - "\n", - "import gcsfs\n", - "import google.auth\n", - "import numpy as np\n", - "import numpy.typing as npt\n", - "import pandas as pd\n", - "import wandb\n", - "from catboost import CatBoostClassifier, Pool\n", - "from sklearn.exceptions import NotFittedError\n", - "from sklearn.metrics import matthews_corrcoef\n", - "from sklearn.model_selection import train_test_split\n", - "from sklearn.preprocessing import (OrdinalEncoder, PowerTransformer,\n", - " RobustScaler, StandardScaler)\n", - "from tqdm.auto import tqdm" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "credentials, _ = google.auth.default()\n", - "fs = gcsfs.GCSFileSystem(project=\"thesis\", token=credentials)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 191 - }, - "id": "KftC_bFhgwZt", - "outputId": "933d7b6d-400b-4f98-fa1f-a9cae72bb733", - "tags": [] - }, - "outputs": [], - "source": [ - "# connect to weights and biases\n", - "run = wandb.init(project=\"thesis\", job_type=\"dataset-creation\", entity=\"fbv\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# set here globally\n", - "seed = 42\n", - "\n", - "exchange = \"ise\" # \"ise\" # \"cboe\"\n", - "strategy = \"supervised\" # \"supervised\" #\"unsupervised\" # \"supervised\" # \"transfer\" # \"unsupervised\"\n", - "mode = \"none\" # \"none\" # \"log_standardized\"\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "Xk8VWtSQces7", - "tags": [] - }, - "outputs": [], - "source": [ - "dataset = f\"fbv/thesis/{exchange}_{strategy}_raw:latest\"\n", - "\n", - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "# load unscaled data\n", - "artifact = run.use_artifact(dataset)\n", - "data_dir = artifact.download()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "yJViJH1yl_S7", - "tags": [] - }, - "outputs": [], - "source": [ - "# reduce number of imported cols due to memory issues\n", - "columns = [\n", - " \"QUOTE_DATETIME\",\n", - " \"ROOT\",\n", - " \"EXPIRATION\",\n", - " \"STRK_PRC\",\n", - " \"OPTION_TYPE\",\n", - " \"issue_type\",\n", - " \"TRADE_SIZE\",\n", - " \"TRADE_PRICE\",\n", - " \"BEST_BID\",\n", - " \"BEST_ASK\",\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"price_all_lead\",\n", - " \"price_all_lag\",\n", - " \"price_ex_lead\",\n", - " \"price_ex_lag\",\n", - " \"buy_sell\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "WmXtH-PEqyQE", - "outputId": "8c68b54f-0331-444a-d3d8-83a6e2a9e7c3", - "tags": [] - }, - "outputs": [], - "source": [ - "if strategy == \"supervised\":\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - " val = pd.read_parquet(\n", - " Path(data_dir, \"val_set\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - "\n", - "elif strategy == \"unsupervised\":\n", - " # load unlabelled training set\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - "\n", - "elif strategy == \"transfer\":\n", - " # load test set\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=columns\n", - " )\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "CZoGJyq_ivfG", - "tags": [] - }, - "outputs": [], - "source": [ - "num_features = [\n", - " \"STRK_PRC\",\n", - " \"TRADE_SIZE\",\n", - " \"TRADE_PRICE\",\n", - " \"BEST_BID\",\n", - " \"BEST_ASK\",\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"price_all_lead\",\n", - " \"price_all_lag\",\n", - " \"price_ex_lead\",\n", - " \"price_ex_lag\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - "]\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "e3_ot886ivfK" - }, - "source": [ - "## Box Cox Test" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "v0MseONFivfL", - "outputId": "3a3cf373-d246-4c42-cb9d-13c41570f7d1", - "tags": [] - }, - "outputs": [], - "source": [ - "%%script false --no-raise-error\n", - "\n", - "train[num_features].min()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "owNjZgepivfN", - "outputId": "2535b4d5-88ec-47ac-e0c6-310d12a0a6b7", - "tags": [] - }, - "outputs": [], - "source": [ - "%%script false --no-raise-error\n", - "\n", - "box_cox = PowerTransformer(method=\"box-cox\")\n", - "# add constant as box cox works only on positive data\n", - "box_cox.fit(train[num_features] + 0.01)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "rfV5iVfuivfN", - "outputId": "60a15dc2-6eac-45ef-e520-74208d0182a4", - "tags": [] - }, - "outputs": [], - "source": [ - "%%script false --no-raise-error\n", - "\n", - "lambdas = pd.Series(data=box_cox.lambdas_, index=num_features)\n", - "lambdas\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "E7gne62JXAMc" - }, - "source": [ - "Use smallest possible constant for Box-Cox test. All $\\lambda \\approx 0 \\implies \\log(\\cdot)$ for price, size, and quotes." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "-f1NBeZNcXpY", - "tags": [] - }, - "outputs": [], - "source": [ - "if strategy == \"supervised\":\n", - " scaler = StandardScaler()\n", - " oe_option_type = OrdinalEncoder(\n", - " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", - " )\n", - " oe_root = OrdinalEncoder(\n", - " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", - " )\n", - " oe_issue_type = OrdinalEncoder(\n", - " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", - " )\n", - "else:\n", - " # if mode transfer or mode unsupervised -> use scaler from ise supervised dataset\n", - " # if mode supervised -> fit scaler on ise / cboe training set and apply on validation and test set\n", - "\n", - " # TODO: Fix if I get unlabelled CBOE dataset\n", - " artifact = run.use_artifact(f\"fbv/thesis/ise_supervised_{mode}_scaler:latest\")\n", - " scaler_dir = artifact.download()\n", - " scalers = pickle.load(open(Path(scaler_dir, \"scalers.sklearn\"), \"rb\"))\n", - "\n", - " # set fitted scalers\n", - " scaler = scalers[\"scaler\"]\n", - " oe_option_type = scalers[\"oe_option_type\"]\n", - " oe_root = scalers[\"oe_root\"]\n", - " oe_issue_type = scalers[\"oe_issue_type\"]\n", - "\n", - "\n", - "def transform(\n", - " data: pd.DataFrame,\n", - " mode: Literal[\"log_standarized\", \"none\"] = \"log_standardized\",\n", - ") -> pd.DataFrame:\n", - " \"\"\"\n", - " Create features, impute, and scale.\n", - "\n", - " Args:\n", - " data (pd.DataFrame): input data frame.\n", - " Returns:\n", - " pd.DataFrame: updated data frame.\n", - " \"\"\"\n", - "\n", - " # set up df, overwrite later\n", - " x = pd.DataFrame(data={\"TRADE_PRICE\": data[\"TRADE_PRICE\"]}, index=data.index)\n", - "\n", - " # size features\n", - " x[\"bid_ask_size_ratio_ex\"] = data[\"bid_size_ex\"] / data[\"ask_size_ex\"]\n", - " x[\"rel_bid_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"bid_size_ex\"]\n", - " x[\"rel_ask_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"ask_size_ex\"]\n", - " x[\"depth_ex\"] = data[\"bid_size_ex\"] - data[\"ask_size_ex\"]\n", - "\n", - " # classical\n", - " cond_ex = data[\"ask_ex\"] >= data[\"bid_ex\"]\n", - " cond_best = data[\"BEST_ASK\"] >= data[\"BEST_BID\"]\n", - "\n", - " # assume positive spread\n", - " mid_ex = np.where(cond_ex, 0.5 * (data[\"ask_ex\"] + data[\"bid_ex\"]), np.nan)\n", - " mid_best = np.where(cond_best, 0.5 * (data[\"BEST_ASK\"] + data[\"BEST_BID\"]), np.nan)\n", - "\n", - " spread_ex = np.where(cond_ex, data[\"ask_ex\"] - data[\"bid_ex\"], np.nan)\n", - " spread_best = np.where(cond_best, data[\"BEST_ASK\"] - data[\"BEST_BID\"], np.nan)\n", - "\n", - " x[\"prox_ex\"] = (data[\"TRADE_PRICE\"] - mid_ex) / (0.5 * spread_ex)\n", - " x[\"prox_best\"] = (data[\"TRADE_PRICE\"] - mid_best) / (0.5 * spread_best)\n", - "\n", - " # custom features\n", - " x[\"spread_ex\"] = spread_ex\n", - " x[\"spread_best\"] = spread_best\n", - " x[\"bid_ask_ratio_ex\"] = data[\"bid_ex\"] / data[\"ask_ex\"]\n", - "\n", - " # calculate change\n", - " x[\"chg_ex_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lead\"]\n", - " x[\"chg_ex_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lag\"]\n", - " x[\"chg_all_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lead\"]\n", - " x[\"chg_all_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lag\"]\n", - "\n", - " if \"clip\" in mode:\n", - " print(\"clipping...\")\n", - " # apply clipping, avoids exploding / vanishing gradients\n", - " to_clip = [\n", - " \"chg_ex_lead\",\n", - " \"chg_ex_lag\",\n", - " \"chg_all_lead\",\n", - " \"chg_all_lag\",\n", - " \"prox_ex\",\n", - " \"prox_best\",\n", - " \"bid_ask_size_ratio_ex\",\n", - " \"rel_bid_size_ex\",\n", - " \"rel_ask_size_ex\",\n", - " \"depth_ex\",\n", - " ]\n", - " x[to_clip] = x[to_clip].clip(-3, 3)\n", - "\n", - " if \"log\" in mode:\n", - " print(\"log transform...\")\n", - " # log transformed features\n", - " x[\n", - " [\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"BEST_ASK\",\n", - " \"BEST_BID\",\n", - " \"TRADE_PRICE\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"price_ex_lag\",\n", - " \"price_ex_lead\",\n", - " \"TRADE_SIZE\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - " \"STRK_PRC\",\n", - " ]\n", - " ] = np.log1p(\n", - " data[\n", - " [\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"BEST_ASK\",\n", - " \"BEST_BID\",\n", - " \"TRADE_PRICE\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"price_ex_lag\",\n", - " \"price_ex_lead\",\n", - " \"TRADE_SIZE\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - " \"STRK_PRC\",\n", - " ]\n", - " ]\n", - " )\n", - "\n", - " x[\"mid_ex\"] = np.log1p(mid_ex)\n", - " x[\"mid_best\"] = np.log1p(mid_best)\n", - "\n", - " x[\"ttm\"] = (\n", - " data[\"EXPIRATION\"].dt.to_period(\"M\")\n", - " - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", - " ).apply(lambda x: x.n)\n", - "\n", - " # save num columns for scaler\n", - " num_cols = x.columns.tolist()\n", - "\n", - " # impute with zeros\n", - " x.replace([np.inf, -np.inf], np.nan, inplace=True)\n", - " x.fillna(0, inplace=True)\n", - "\n", - " # standardize continous columns (w/o date features)\n", - " # bin encode categorical features\n", - " try:\n", - " x[num_cols] = scaler.transform(x[num_cols])\n", - " x[\"option_type\"] = oe_option_type.transform(\n", - " data[\"OPTION_TYPE\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " x[\"issue_type\"] = oe_issue_type.transform(\n", - " data[\"issue_type\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " x[\"root\"] = oe_root.transform(\n", - " data[\"ROOT\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " print(\"transform (val + test)\")\n", - " except NotFittedError as e:\n", - " x[num_cols] = scaler.fit_transform(x[num_cols])\n", - " x[\"option_type\"] = oe_option_type.fit_transform(\n", - " data[\"OPTION_TYPE\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " x[\"issue_type\"] = oe_issue_type.fit_transform(\n", - " data[\"issue_type\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " x[\"root\"] = oe_root.fit_transform(\n", - " data[\"ROOT\"].astype(str).values.reshape(-1, 1)\n", - " )\n", - " print(\"fit_transform (train)\")\n", - " if mode == \"none\":\n", - " x[\n", - " [\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"BEST_ASK\",\n", - " \"BEST_BID\",\n", - " \"TRADE_PRICE\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"price_ex_lag\",\n", - " \"price_ex_lead\",\n", - " \"TRADE_SIZE\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - " \"STRK_PRC\",\n", - " ]\n", - " ] = data[\n", - " [\n", - " \"ask_ex\",\n", - " \"bid_ex\",\n", - " \"BEST_ASK\",\n", - " \"BEST_BID\",\n", - " \"TRADE_PRICE\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"price_ex_lag\",\n", - " \"price_ex_lead\",\n", - " \"TRADE_SIZE\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"day_vol\",\n", - " \"myn\",\n", - " \"STRK_PRC\",\n", - " ]\n", - " ]\n", - "\n", - " x[\"mid_ex\"] = mid_ex\n", - " x[\"mid_best\"] = mid_best\n", - "\n", - " x[\"ttm\"] = (\n", - " data[\"EXPIRATION\"].dt.to_period(\"M\")\n", - " - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", - " ).apply(lambda x: x.n)\n", - "\n", - " # save num columns for scaler\n", - " num_cols = x.columns.tolist()\n", - "\n", - " # impute with zeros\n", - " x.replace([np.inf, -np.inf], np.nan, inplace=True)\n", - " # x.fillna(0, inplace=True)\n", - "\n", - " # just copy\n", - " x[\"option_type\"] = data[\"OPTION_TYPE\"]\n", - " x[\"issue_type\"] = data[\"issue_type\"]\n", - " x[\"root\"] = data[\"ROOT\"]\n", - "\n", - " x[\"buy_sell\"] = data[\"buy_sell\"].astype(\"int8\")\n", - " return x\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "3gKBgTbBivfS" - }, - "source": [ - "## Write to file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "0b-3AOjcivfT", - "outputId": "241094f0-0cda-44a8-e377-d5809d6ca1bd", - "tags": [] - }, - "outputs": [], - "source": [ - "name = f\"{exchange}_{strategy}_{mode}\"\n", - "\n", - "dataset = wandb.Artifact(name=name, type=\"preprocessed_data\")\n", - "\n", - "if strategy == \"supervised\" or strategy == \"unsupervised\":\n", - " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/train_set.parquet\"\n", - " train = transform(train, mode)\n", - " train.to_parquet(output_path)\n", - " del train\n", - " gc.collect()\n", - "\n", - " dataset.add_reference(output_path)\n", - "\n", - "if strategy == \"supervised\":\n", - " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/val_set.parquet\"\n", - " val = transform(val, mode)\n", - " val.to_parquet(output_path)\n", - " del val\n", - " gc.collect()\n", - " dataset.add_reference(output_path)\n", - "\n", - "if strategy == \"supervised\" or strategy == \"transfer\":\n", - " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/test_set.parquet\"\n", - "\n", - " test = transform(test, mode)\n", - " test.to_parquet(output_path)\n", - " del test\n", - " gc.collect()\n", - " dataset.add_reference(output_path)\n", - "\n", - "run.log_artifact(dataset)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# save scaler to pickle\n", - "\n", - "if strategy == \"supervised\":\n", - "\n", - " scalers = {\n", - " \"scaler\": scaler,\n", - " \"oe_option_type\": oe_option_type,\n", - " \"oe_root\": oe_root,\n", - " \"oe_issue_type\": oe_issue_type,\n", - " }\n", - " uri_scalers = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/scalers.sklearn\"\n", - " with fs.open(uri_scalers, \"wb\") as f:\n", - " pickle.dump(scalers, f, protocol=4) \n", - "\n", - " # log scaler to wandb\n", - " scaler = wandb.Artifact(name=f\"{name}_scaler\", type=\"scaler\")\n", - " scaler.add_reference(uri_scalers)\n", - " run.log_artifact(scaler)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "run.finish()\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "H8u4au_6XAMx" - }, - "source": [ - "## Adversarial Validation\n", - "> Adversarial Validation is a technique allowing you to easily estimate the degree of difference between your training and test data. This technique was long rumored among Kaggle participants and transmitted from team to team until it emerged publicly thanks to a post by Zygmunt ZajΔ…c (https://www.kaggle.com/zygmunt) on his FastML blog. (adapted from Banchawicz et. al)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "features_classical = [\n", - " \"TRADE_PRICE\",\n", - " \"bid_ex\",\n", - " \"ask_ex\",\n", - " \"BEST_ASK\",\n", - " \"BEST_BID\",\n", - " \"price_ex_lag\",\n", - " \"price_ex_lead\",\n", - " \"price_all_lag\",\n", - " \"price_all_lead\",\n", - " \"chg_ex_lead\",\n", - " \"chg_ex_lag\",\n", - " \"chg_all_lead\",\n", - " \"chg_all_lag\",\n", - " \"prox_ex\",\n", - " \"prox_best\",\n", - "]\n", - "\n", - "features_size = [\n", - " \"bid_ask_size_ratio_ex\",\n", - " \"rel_bid_size_ex\",\n", - " \"rel_ask_size_ex\",\n", - " \"TRADE_SIZE\",\n", - " \"bid_size_ex\",\n", - " \"ask_size_ex\",\n", - " \"depth_ex\",\n", - "]\n", - "\n", - "features_classical_size = [\n", - " *features_classical,\n", - " *features_size,\n", - " \"buy_sell\", # add here and remove later\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/ise_log_standardized/train_set_60.parquet\",\n", - " engine=\"fastparquet\",\n", - " columns=features_classical_size,\n", - ")\n", - "val = pd.read_parquet(\n", - " \"gs://thesis-bucket-option-trade-classification/data/ise_log_standardized/val_set_20.parquet\",\n", - " engine=\"fastparquet\",\n", - " columns=features_classical_size,\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "GKpvTE4EXAM0", - "outputId": "222f6a61-548f-4f1c-8064-caffcdfe637e" - }, - "outputs": [], - "source": [ - "X = pd.concat([train, val])\n", - "X.drop(columns=[\"buy_sell\"], inplace=True)\n", - "# assign zeros to train set and ones to test set\n", - "y = [0] * len(train) + [1] * len(val)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X.columns\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "tperioc56aCt" - }, - "outputs": [], - "source": [ - "# perform cv with catboost classifier\n", - "clf = CatBoostClassifier(\n", - " task_type=\"GPU\",\n", - " logging_level=\"Silent\",\n", - " random_seed=42,\n", - " eval_metric=\"Accuracy\",\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "X_train, X_test, y_train, y_test = train_test_split(\n", - " X, y, test_size=0.2, random_state=42, shuffle=True\n", - ")\n", - "clf.fit(X_train, y_train, eval_set=(X_test, y_test))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "y_pred = clf.predict(X_test)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# use mcc as data is imbalanced 3/4 train set, 1/4 val set\n", - "print(matthews_corrcoef(y_test, y_pred))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feature_importance = clf.get_feature_importance(\n", - " prettified=True, type=\"FeatureImportance\"\n", - ")\n", - "feature_importance\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "feature_importance.to_csv(\"feature_importance_gbm_classical_size.csv\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Kolmogorov Smirnov" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from scipy.stats import ks_2samp\n", - "\n", - "cols = train.columns.tolist()\n", - "# cols.remove(\"buy_sell\")\n", - "results = []\n", - "\n", - "for col in cols:\n", - " res = ks_2samp(train[col], val[col])\n", - "\n", - " results.append({\"col\": col, \"static\": res.statistic, \"pvalue\": res.pvalue})\n", - "\n", - "results = pd.DataFrame(results)\n", - "results.to_csv(\"kolmogorov_smirnov.csv\")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Auto-Correlation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "train = transform(train, mode=\"none\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "from otc.features.build_features import features_classical_size\n", - "import matplotlib as mpl\n", - "import matplotlib.pyplot as plt\n", - "from matplotlib import rc" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X = train[features_classical_size].head(200000)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "cols = X.columns.tolist()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "cols" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "cols_clearname = [\"trade price\", \"bid (ex)\", \"ask (ex)\", \"ask (best)\",\n", - " \"bid (best)\", \"price lag (ex)\", \"price lead (ex)\",\n", - " \"price lag (all)\", \"price lead (all)\",\n", - " \"price chg. lead (ex)\", \"price chg. lag (ex)\",\n", - " \"price chg. lead (all)\", \"price chg. lag (all)\",\n", - " \"prox (ex)\", \"prox (best)\", \"bid ask size ratio (ex)\",\n", - " \"rel. bid size (ex)\", \"rel. ask size (ex)\", \"trade size\",\n", - " \"bid size (ex)\", \"ask size (ex)\", \"depth (ex)\"\n", - " ]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "len(cols_clearname)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "list(zip(cols, cols_clearname))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "params = {\n", - " \"pgf.texsystem\": \"xelatex\",\n", - " \"pgf.rcfonts\": False,\n", - " \"font.serif\": [],\n", - " \"font.family\": \"serif\",\n", - " \"font.sans-serif\": [],\n", - " \"axes.labelsize\": 11,\n", - "}\n", - "\n", - "plt.rcParams.update(params)\n", - "rc(\"text\", usetex=True)\n", - "\n", - "plt.rc('text.latex', preamble=r'\\usepackage{amsmath}\\usepackage[utf8]{inputenc}')\n", - "\n", - "cmap = mpl.colormaps.get_cmap(\"plasma\")\n", - "\n", - "\n", - "\n", - "# https://ranocha.de/blog/colors/\n", - "# Standard SciencePlots color cycle\n", - "mpl.rcParams[\"axes.prop_cycle\"] = mpl.cycler(\n", - " \"color\", [\"0C5DA5\", \"00B945\", \"FF9500\", \"FF2C00\", \"845B97\", \"474747\", \"9e9e9e\"]\n", - ")\n", - "\n", - "# line cyclers adapted to colourblind people\n", - "from cycler import cycler\n", - "line_cycler = (cycler(color=[\"#E69F00\", \"#56B4E9\", \"#009E73\", \"#0072B2\", \"#D55E00\", \"#CC79A7\", \"#F0E442\"]) # + cycler(linestyle=[\"-\", \"--\", \"-.\", \":\", \"-\", \"--\", \"-.\"])\n", - " )\n", - "marker_cycler = (cycler(color=[\"#E69F00\", \"#56B4E9\", \"#009E73\", \"#0072B2\", \"#D55E00\", \"#CC79A7\", \"#F0E442\"]) +\n", - " cycler(linestyle=[\"none\", \"none\", \"none\", \"none\", \"none\", \"none\", \"none\"]) +\n", - " cycler(marker=[\"4\", \"2\", \"3\", \"1\", \"+\", \"x\", \".\"]))\n", - "\n", - "plt.rc(\"axes\", prop_cycle=line_cycler)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# cols.remove(\"buy_sell\")\n", - "print(cols)\n", - "\n", - "CM = 1 / 2.54\n", - "\n", - "(fig, ax) = plt.subplots(\n", - " nrows=(len(cols) // 4) + 1,\n", - " ncols=4,\n", - " sharey=True,\n", - " constrained_layout=True,\n", - " figsize=(14 * CM, 14 * CM),\n", - ")\n", - "\n", - "index = 0\n", - "\n", - "for i, col in tqdm(enumerate(cols)):\n", - "\n", - " \n", - " r = i // 4\n", - " c = i % 4\n", - "\n", - " \n", - " ax[r][c].acorr(X[col].astype(float), usevlines=True, normed=True, maxlags=20, lw=1)\n", - " ax[r][c].set_title(cols_clearname[index])\n", - "\n", - " index +=1\n", - "\n", - "# remove empty plots\n", - "fig.delaxes(ax[5][2])\n", - "fig.delaxes(ax[5][3])\n", - "\n", - "plt.savefig(\n", - " f\"../reports/Graphs/auto_corr_features.pdf\",\n", - " bbox_inches=\"tight\",\n", - ")\n" - ] - } - ], - "metadata": { - "accelerator": "GPU", - "colab": { - "machine_shape": "hm", - "name": "Untitled2.ipynb", - "provenance": [] - }, - "gpuClass": "premium", - "kernelspec": { - "display_name": "myenv", - "language": "python", - "name": "myenv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - }, - "vscode": { - "interpreter": { - "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "7WXF7w4VyVgG", + "tags": [] + }, + "outputs": [], + "source": [ + "import gc\n", + "import os\n", + "import pickle\n", + "from pathlib import Path\n", + "from typing import Literal\n", + "\n", + "import gcsfs\n", + "import google.auth\n", + "import numpy as np\n", + "import numpy.typing as npt\n", + "import pandas as pd\n", + "import wandb\n", + "from catboost import CatBoostClassifier, Pool\n", + "from sklearn.exceptions import NotFittedError\n", + "from sklearn.metrics import matthews_corrcoef\n", + "from sklearn.model_selection import train_test_split\n", + "from sklearn.preprocessing import (OrdinalEncoder, PowerTransformer,\n", + " RobustScaler, StandardScaler)\n", + "from tqdm.auto import tqdm" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "credentials, _ = google.auth.default()\n", + "fs = gcsfs.GCSFileSystem(project=\"thesis\", token=credentials)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 191 + }, + "id": "KftC_bFhgwZt", + "outputId": "933d7b6d-400b-4f98-fa1f-a9cae72bb733", + "tags": [] + }, + "outputs": [], + "source": [ + "# connect to weights and biases\n", + "run = wandb.init(project=\"thesis\", job_type=\"dataset-creation\", entity=\"fbv\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# set here globally\n", + "seed = 42\n", + "\n", + "exchange = \"ise\" # \"ise\" # \"cboe\"\n", + "strategy = \"supervised\" # \"supervised\" #\"unsupervised\" # \"supervised\" # \"transfer\" # \"unsupervised\"\n", + "mode = \"none\" # \"none\" # \"log_standardized\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Xk8VWtSQces7", + "tags": [] + }, + "outputs": [], + "source": [ + "dataset = f\"fbv/thesis/{exchange}_{strategy}_raw:latest\"\n", + "\n", + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "# load unscaled data\n", + "artifact = run.use_artifact(dataset)\n", + "data_dir = artifact.download()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "yJViJH1yl_S7", + "tags": [] + }, + "outputs": [], + "source": [ + "# reduce number of imported cols due to memory issues\n", + "columns = [\n", + " \"QUOTE_DATETIME\",\n", + " \"ROOT\",\n", + " \"EXPIRATION\",\n", + " \"STRK_PRC\",\n", + " \"OPTION_TYPE\",\n", + " \"issue_type\",\n", + " \"TRADE_SIZE\",\n", + " \"TRADE_PRICE\",\n", + " \"BEST_BID\",\n", + " \"BEST_ASK\",\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"price_all_lead\",\n", + " \"price_all_lag\",\n", + " \"price_ex_lead\",\n", + " \"price_ex_lag\",\n", + " \"buy_sell\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "WmXtH-PEqyQE", + "outputId": "8c68b54f-0331-444a-d3d8-83a6e2a9e7c3", + "tags": [] + }, + "outputs": [], + "source": [ + "if strategy == \"supervised\":\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + " val = pd.read_parquet(\n", + " Path(data_dir, \"val_set\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + "\n", + "elif strategy == \"unsupervised\":\n", + " # load unlabelled training set\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + "\n", + "elif strategy == \"transfer\":\n", + " # load test set\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=columns\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "CZoGJyq_ivfG", + "tags": [] + }, + "outputs": [], + "source": [ + "num_features = [\n", + " \"STRK_PRC\",\n", + " \"TRADE_SIZE\",\n", + " \"TRADE_PRICE\",\n", + " \"BEST_BID\",\n", + " \"BEST_ASK\",\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"price_all_lead\",\n", + " \"price_all_lag\",\n", + " \"price_ex_lead\",\n", + " \"price_ex_lag\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + "]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "e3_ot886ivfK" + }, + "source": [ + "## Box Cox Test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "v0MseONFivfL", + "outputId": "3a3cf373-d246-4c42-cb9d-13c41570f7d1", + "tags": [] + }, + "outputs": [], + "source": [ + "%%script false --no-raise-error\n", + "\n", + "train[num_features].min()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "owNjZgepivfN", + "outputId": "2535b4d5-88ec-47ac-e0c6-310d12a0a6b7", + "tags": [] + }, + "outputs": [], + "source": [ + "%%script false --no-raise-error\n", + "\n", + "box_cox = PowerTransformer(method=\"box-cox\")\n", + "# add constant as box cox works only on positive data\n", + "box_cox.fit(train[num_features] + 0.01)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "rfV5iVfuivfN", + "outputId": "60a15dc2-6eac-45ef-e520-74208d0182a4", + "tags": [] + }, + "outputs": [], + "source": [ + "%%script false --no-raise-error\n", + "\n", + "lambdas = pd.Series(data=box_cox.lambdas_, index=num_features)\n", + "lambdas\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "E7gne62JXAMc" + }, + "source": [ + "Use smallest possible constant for Box-Cox test. All $\\lambda \\approx 0 \\implies \\log(\\cdot)$ for price, size, and quotes." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "-f1NBeZNcXpY", + "tags": [] + }, + "outputs": [], + "source": [ + "if strategy == \"supervised\":\n", + " scaler = StandardScaler()\n", + " oe_option_type = OrdinalEncoder(\n", + " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", + " )\n", + " oe_root = OrdinalEncoder(\n", + " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", + " )\n", + " oe_issue_type = OrdinalEncoder(\n", + " unknown_value=-1, dtype=int, handle_unknown=\"use_encoded_value\"\n", + " )\n", + "else:\n", + " # if mode transfer or mode unsupervised -> use scaler from ise supervised dataset\n", + " # if mode supervised -> fit scaler on ise / cboe training set and apply on validation and test set\n", + "\n", + " # TODO: Fix if I get unlabelled CBOE dataset\n", + " artifact = run.use_artifact(f\"fbv/thesis/ise_supervised_{mode}_scaler:latest\")\n", + " scaler_dir = artifact.download()\n", + " scalers = pickle.load(open(Path(scaler_dir, \"scalers.sklearn\"), \"rb\"))\n", + "\n", + " # set fitted scalers\n", + " scaler = scalers[\"scaler\"]\n", + " oe_option_type = scalers[\"oe_option_type\"]\n", + " oe_root = scalers[\"oe_root\"]\n", + " oe_issue_type = scalers[\"oe_issue_type\"]\n", + "\n", + "\n", + "def transform(\n", + " data: pd.DataFrame,\n", + " mode: Literal[\"log_standarized\", \"none\"] = \"log_standardized\",\n", + ") -> pd.DataFrame:\n", + " \"\"\"\n", + " Create features, impute, and scale.\n", + "\n", + " Args:\n", + " data (pd.DataFrame): input data frame.\n", + " Returns:\n", + " pd.DataFrame: updated data frame.\n", + " \"\"\"\n", + "\n", + " # set up df, overwrite later\n", + " x = pd.DataFrame(data={\"TRADE_PRICE\": data[\"TRADE_PRICE\"]}, index=data.index)\n", + "\n", + " # size features\n", + " x[\"bid_ask_size_ratio_ex\"] = data[\"bid_size_ex\"] / data[\"ask_size_ex\"]\n", + " x[\"rel_bid_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"bid_size_ex\"]\n", + " x[\"rel_ask_size_ex\"] = data[\"TRADE_SIZE\"] / data[\"ask_size_ex\"]\n", + " x[\"depth_ex\"] = data[\"bid_size_ex\"] - data[\"ask_size_ex\"]\n", + "\n", + " # classical\n", + " cond_ex = data[\"ask_ex\"] >= data[\"bid_ex\"]\n", + " cond_best = data[\"BEST_ASK\"] >= data[\"BEST_BID\"]\n", + "\n", + " # assume positive spread\n", + " mid_ex = np.where(cond_ex, 0.5 * (data[\"ask_ex\"] + data[\"bid_ex\"]), np.nan)\n", + " mid_best = np.where(cond_best, 0.5 * (data[\"BEST_ASK\"] + data[\"BEST_BID\"]), np.nan)\n", + "\n", + " spread_ex = np.where(cond_ex, data[\"ask_ex\"] - data[\"bid_ex\"], np.nan)\n", + " spread_best = np.where(cond_best, data[\"BEST_ASK\"] - data[\"BEST_BID\"], np.nan)\n", + "\n", + " x[\"prox_ex\"] = (data[\"TRADE_PRICE\"] - mid_ex) / (0.5 * spread_ex)\n", + " x[\"prox_best\"] = (data[\"TRADE_PRICE\"] - mid_best) / (0.5 * spread_best)\n", + "\n", + " # custom features\n", + " x[\"spread_ex\"] = spread_ex\n", + " x[\"spread_best\"] = spread_best\n", + " x[\"bid_ask_ratio_ex\"] = data[\"bid_ex\"] / data[\"ask_ex\"]\n", + "\n", + " # calculate change\n", + " x[\"chg_ex_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lead\"]\n", + " x[\"chg_ex_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_ex_lag\"]\n", + " x[\"chg_all_lead\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lead\"]\n", + " x[\"chg_all_lag\"] = data[\"TRADE_PRICE\"] - data[\"price_all_lag\"]\n", + "\n", + " if \"clip\" in mode:\n", + " print(\"clipping...\")\n", + " # apply clipping, avoids exploding / vanishing gradients\n", + " to_clip = [\n", + " \"chg_ex_lead\",\n", + " \"chg_ex_lag\",\n", + " \"chg_all_lead\",\n", + " \"chg_all_lag\",\n", + " \"prox_ex\",\n", + " \"prox_best\",\n", + " \"bid_ask_size_ratio_ex\",\n", + " \"rel_bid_size_ex\",\n", + " \"rel_ask_size_ex\",\n", + " \"depth_ex\",\n", + " ]\n", + " x[to_clip] = x[to_clip].clip(-3, 3)\n", + "\n", + " if \"log\" in mode:\n", + " print(\"log transform...\")\n", + " # log transformed features\n", + " x[\n", + " [\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"BEST_ASK\",\n", + " \"BEST_BID\",\n", + " \"TRADE_PRICE\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"price_ex_lag\",\n", + " \"price_ex_lead\",\n", + " \"TRADE_SIZE\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + " \"STRK_PRC\",\n", + " ]\n", + " ] = np.log1p(\n", + " data[\n", + " [\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"BEST_ASK\",\n", + " \"BEST_BID\",\n", + " \"TRADE_PRICE\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"price_ex_lag\",\n", + " \"price_ex_lead\",\n", + " \"TRADE_SIZE\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + " \"STRK_PRC\",\n", + " ]\n", + " ]\n", + " )\n", + "\n", + " x[\"mid_ex\"] = np.log1p(mid_ex)\n", + " x[\"mid_best\"] = np.log1p(mid_best)\n", + "\n", + " x[\"ttm\"] = (\n", + " data[\"EXPIRATION\"].dt.to_period(\"M\")\n", + " - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", + " ).apply(lambda x: x.n)\n", + "\n", + " # save num columns for scaler\n", + " num_cols = x.columns.tolist()\n", + "\n", + " # impute with zeros\n", + " x.replace([np.inf, -np.inf], np.nan, inplace=True)\n", + " x.fillna(0, inplace=True)\n", + "\n", + " # standardize continous columns (w/o date features)\n", + " # bin encode categorical features\n", + " try:\n", + " x[num_cols] = scaler.transform(x[num_cols])\n", + " x[\"option_type\"] = oe_option_type.transform(\n", + " data[\"OPTION_TYPE\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " x[\"issue_type\"] = oe_issue_type.transform(\n", + " data[\"issue_type\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " x[\"root\"] = oe_root.transform(\n", + " data[\"ROOT\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " print(\"transform (val + test)\")\n", + " except NotFittedError as e:\n", + " x[num_cols] = scaler.fit_transform(x[num_cols])\n", + " x[\"option_type\"] = oe_option_type.fit_transform(\n", + " data[\"OPTION_TYPE\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " x[\"issue_type\"] = oe_issue_type.fit_transform(\n", + " data[\"issue_type\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " x[\"root\"] = oe_root.fit_transform(\n", + " data[\"ROOT\"].astype(str).values.reshape(-1, 1)\n", + " )\n", + " print(\"fit_transform (train)\")\n", + " if mode == \"none\":\n", + " x[\n", + " [\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"BEST_ASK\",\n", + " \"BEST_BID\",\n", + " \"TRADE_PRICE\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"price_ex_lag\",\n", + " \"price_ex_lead\",\n", + " \"TRADE_SIZE\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + " \"STRK_PRC\",\n", + " ]\n", + " ] = data[\n", + " [\n", + " \"ask_ex\",\n", + " \"bid_ex\",\n", + " \"BEST_ASK\",\n", + " \"BEST_BID\",\n", + " \"TRADE_PRICE\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"price_ex_lag\",\n", + " \"price_ex_lead\",\n", + " \"TRADE_SIZE\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"day_vol\",\n", + " \"myn\",\n", + " \"STRK_PRC\",\n", + " ]\n", + " ]\n", + "\n", + " x[\"mid_ex\"] = mid_ex\n", + " x[\"mid_best\"] = mid_best\n", + "\n", + " x[\"ttm\"] = (\n", + " data[\"EXPIRATION\"].dt.to_period(\"M\")\n", + " - data[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", + " ).apply(lambda x: x.n)\n", + "\n", + " # save num columns for scaler\n", + " num_cols = x.columns.tolist()\n", + "\n", + " # impute with zeros\n", + " x.replace([np.inf, -np.inf], np.nan, inplace=True)\n", + " # x.fillna(0, inplace=True)\n", + "\n", + " # just copy\n", + " x[\"option_type\"] = data[\"OPTION_TYPE\"]\n", + " x[\"issue_type\"] = data[\"issue_type\"]\n", + " x[\"root\"] = data[\"ROOT\"]\n", + "\n", + " x[\"buy_sell\"] = data[\"buy_sell\"].astype(\"int8\")\n", + " return x\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "3gKBgTbBivfS" + }, + "source": [ + "## Write to file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "0b-3AOjcivfT", + "outputId": "241094f0-0cda-44a8-e377-d5809d6ca1bd", + "tags": [] + }, + "outputs": [], + "source": [ + "name = f\"{exchange}_{strategy}_{mode}\"\n", + "\n", + "dataset = wandb.Artifact(name=name, type=\"preprocessed_data\")\n", + "\n", + "if strategy == \"supervised\" or strategy == \"unsupervised\":\n", + " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/train_set.parquet\"\n", + " train = transform(train, mode)\n", + " train.to_parquet(output_path)\n", + " del train\n", + " gc.collect()\n", + "\n", + " dataset.add_reference(output_path)\n", + "\n", + "if strategy == \"supervised\":\n", + " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/val_set.parquet\"\n", + " val = transform(val, mode)\n", + " val.to_parquet(output_path)\n", + " del val\n", + " gc.collect()\n", + " dataset.add_reference(output_path)\n", + "\n", + "if strategy == \"supervised\" or strategy == \"transfer\":\n", + " output_path = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/test_set.parquet\"\n", + "\n", + " test = transform(test, mode)\n", + " test.to_parquet(output_path)\n", + " del test\n", + " gc.collect()\n", + " dataset.add_reference(output_path)\n", + "\n", + "run.log_artifact(dataset)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# save scaler to pickle\n", + "\n", + "if strategy == \"supervised\":\n", + "\n", + " scalers = {\n", + " \"scaler\": scaler,\n", + " \"oe_option_type\": oe_option_type,\n", + " \"oe_root\": oe_root,\n", + " \"oe_issue_type\": oe_issue_type,\n", + " }\n", + " uri_scalers = f\"gs://thesis-bucket-option-trade-classification/data/preprocessed/{name}/scalers.sklearn\"\n", + " with fs.open(uri_scalers, \"wb\") as f:\n", + " pickle.dump(scalers, f, protocol=4) \n", + "\n", + " # log scaler to wandb\n", + " scaler = wandb.Artifact(name=f\"{name}_scaler\", type=\"scaler\")\n", + " scaler.add_reference(uri_scalers)\n", + " run.log_artifact(scaler)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "run.finish()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "H8u4au_6XAMx" + }, + "source": [ + "## Adversarial Validation\n", + "> Adversarial Validation is a technique allowing you to easily estimate the degree of difference between your training and test data. This technique was long rumored among Kaggle participants and transmitted from team to team until it emerged publicly thanks to a post by Zygmunt ZajΔ…c (https://www.kaggle.com/zygmunt) on his FastML blog. (adapted from Banchawicz et. al)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "features_classical = [\n", + " \"TRADE_PRICE\",\n", + " \"bid_ex\",\n", + " \"ask_ex\",\n", + " \"BEST_ASK\",\n", + " \"BEST_BID\",\n", + " \"price_ex_lag\",\n", + " \"price_ex_lead\",\n", + " \"price_all_lag\",\n", + " \"price_all_lead\",\n", + " \"chg_ex_lead\",\n", + " \"chg_ex_lag\",\n", + " \"chg_all_lead\",\n", + " \"chg_all_lag\",\n", + " \"prox_ex\",\n", + " \"prox_best\",\n", + "]\n", + "\n", + "features_size = [\n", + " \"bid_ask_size_ratio_ex\",\n", + " \"rel_bid_size_ex\",\n", + " \"rel_ask_size_ex\",\n", + " \"TRADE_SIZE\",\n", + " \"bid_size_ex\",\n", + " \"ask_size_ex\",\n", + " \"depth_ex\",\n", + "]\n", + "\n", + "features_classical_size = [\n", + " *features_classical,\n", + " *features_size,\n", + " \"buy_sell\", # add here and remove later\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/ise_log_standardized/train_set_60.parquet\",\n", + " engine=\"fastparquet\",\n", + " columns=features_classical_size,\n", + ")\n", + "val = pd.read_parquet(\n", + " \"gs://thesis-bucket-option-trade-classification/data/ise_log_standardized/val_set_20.parquet\",\n", + " engine=\"fastparquet\",\n", + " columns=features_classical_size,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "GKpvTE4EXAM0", + "outputId": "222f6a61-548f-4f1c-8064-caffcdfe637e" + }, + "outputs": [], + "source": [ + "X = pd.concat([train, val])\n", + "X.drop(columns=[\"buy_sell\"], inplace=True)\n", + "# assign zeros to train set and ones to test set\n", + "y = [0] * len(train) + [1] * len(val)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X.columns\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tperioc56aCt" + }, + "outputs": [], + "source": [ + "# perform cv with catboost classifier\n", + "clf = CatBoostClassifier(\n", + " task_type=\"GPU\",\n", + " logging_level=\"Silent\",\n", + " random_seed=42,\n", + " eval_metric=\"Accuracy\",\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "X_train, X_test, y_train, y_test = train_test_split(\n", + " X, y, test_size=0.2, random_state=42, shuffle=True\n", + ")\n", + "clf.fit(X_train, y_train, eval_set=(X_test, y_test))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "y_pred = clf.predict(X_test)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# use mcc as data is imbalanced 3/4 train set, 1/4 val set\n", + "print(matthews_corrcoef(y_test, y_pred))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feature_importance = clf.get_feature_importance(\n", + " prettified=True, type=\"FeatureImportance\"\n", + ")\n", + "feature_importance\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "feature_importance.to_csv(\"feature_importance_gbm_classical_size.csv\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Kolmogorov Smirnov" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.stats import ks_2samp\n", + "\n", + "cols = train.columns.tolist()\n", + "# cols.remove(\"buy_sell\")\n", + "results = []\n", + "\n", + "for col in cols:\n", + " res = ks_2samp(train[col], val[col])\n", + "\n", + " results.append({\"col\": col, \"static\": res.statistic, \"pvalue\": res.pvalue})\n", + "\n", + "results = pd.DataFrame(results)\n", + "results.to_csv(\"kolmogorov_smirnov.csv\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Auto-Correlation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "train = transform(train, mode=\"none\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "from otc.features.build_features import features_classical_size\n", + "import matplotlib as mpl\n", + "import matplotlib.pyplot as plt\n", + "from matplotlib import rc" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X = train[features_classical_size].head(200000)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cols = X.columns.tolist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cols" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cols_clearname = [\"trade price\", \"bid (ex)\", \"ask (ex)\", \"ask (best)\",\n", + " \"bid (best)\", \"price lag (ex)\", \"price lead (ex)\",\n", + " \"price lag (all)\", \"price lead (all)\",\n", + " \"price chg. lead (ex)\", \"price chg. lag (ex)\",\n", + " \"price chg. lead (all)\", \"price chg. lag (all)\",\n", + " \"prox (ex)\", \"prox (best)\", \"bid ask size ratio (ex)\",\n", + " \"rel. bid size (ex)\", \"rel. ask size (ex)\", \"trade size\",\n", + " \"bid size (ex)\", \"ask size (ex)\", \"depth (ex)\"\n", + " ]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "len(cols_clearname)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "list(zip(cols, cols_clearname))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "params = {\n", + " \"pgf.texsystem\": \"xelatex\",\n", + " \"pgf.rcfonts\": False,\n", + " \"font.serif\": [],\n", + " \"font.family\": \"serif\",\n", + " \"font.sans-serif\": [],\n", + " \"axes.labelsize\": 11,\n", + "}\n", + "\n", + "plt.rcParams.update(params)\n", + "rc(\"text\", usetex=True)\n", + "\n", + "plt.rc('text.latex', preamble=r'\\usepackage{amsmath}\\usepackage[utf8]{inputenc}')\n", + "\n", + "cmap = mpl.colormaps.get_cmap(\"plasma\")\n", + "\n", + "\n", + "\n", + "# https://ranocha.de/blog/colors/\n", + "# Standard SciencePlots color cycle\n", + "mpl.rcParams[\"axes.prop_cycle\"] = mpl.cycler(\n", + " \"color\", [\"0C5DA5\", \"00B945\", \"FF9500\", \"FF2C00\", \"845B97\", \"474747\", \"9e9e9e\"]\n", + ")\n", + "\n", + "# line cyclers adapted to colourblind people\n", + "from cycler import cycler\n", + "line_cycler = (cycler(color=[\"#E69F00\", \"#56B4E9\", \"#009E73\", \"#0072B2\", \"#D55E00\", \"#CC79A7\", \"#F0E442\"]) # + cycler(linestyle=[\"-\", \"--\", \"-.\", \":\", \"-\", \"--\", \"-.\"])\n", + " )\n", + "marker_cycler = (cycler(color=[\"#E69F00\", \"#56B4E9\", \"#009E73\", \"#0072B2\", \"#D55E00\", \"#CC79A7\", \"#F0E442\"]) +\n", + " cycler(linestyle=[\"none\", \"none\", \"none\", \"none\", \"none\", \"none\", \"none\"]) +\n", + " cycler(marker=[\"4\", \"2\", \"3\", \"1\", \"+\", \"x\", \".\"]))\n", + "\n", + "plt.rc(\"axes\", prop_cycle=line_cycler)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# cols.remove(\"buy_sell\")\n", + "print(cols)\n", + "\n", + "CM = 1 / 2.54\n", + "\n", + "(fig, ax) = plt.subplots(\n", + " nrows=(len(cols) // 4) + 1,\n", + " ncols=4,\n", + " sharey=True,\n", + " constrained_layout=True,\n", + " figsize=(14 * CM, 14 * CM),\n", + ")\n", + "\n", + "index = 0\n", + "\n", + "for i, col in tqdm(enumerate(cols)):\n", + "\n", + " \n", + " r = i // 4\n", + " c = i % 4\n", + "\n", + " \n", + " ax[r][c].acorr(X[col].astype(float), usevlines=True, normed=True, maxlags=20, lw=1)\n", + " ax[r][c].set_title(cols_clearname[index])\n", + "\n", + " index +=1\n", + "\n", + "# remove empty plots\n", + "fig.delaxes(ax[5][2])\n", + "fig.delaxes(ax[5][3])\n", + "\n", + "plt.savefig(\n", + " f\"../reports/Graphs/auto_corr_features.pdf\",\n", + " bbox_inches=\"tight\",\n", + ")\n" + ] + } + ], + "metadata": { + "accelerator": "GPU", + "colab": { + "machine_shape": "hm", + "name": "Untitled2.ipynb", + "provenance": [] + }, + "gpuClass": "premium", + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "myenv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/4.0a-mb-logistic-regression.ipynb b/notebooks/4.0a-mb-logistic-regression.ipynb index 982b81a2..4e9ce745 100644 --- a/notebooks/4.0a-mb-logistic-regression.ipynb +++ b/notebooks/4.0a-mb-logistic-regression.ipynb @@ -1,309 +1,309 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "98b853e9-a97e-4a0b-b1af-1bd0ede09c77", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import os\n", - "import sys\n", - "\n", - "import math\n", - "from pathlib import Path\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "import torch\n", - "import wandb\n", - "from torch import nn\n", - "from torch import nn, optim\n", - "from tqdm.auto import tqdm\n", - "\n", - "sys.path.append(\"..\")\n", - "from otc.data.dataset import TabDataset\n", - "from otc.data.dataloader import TabDataLoader\n", - "from otc.features.build_features import features_classical_size\n", - "from otc.optim.early_stopping import EarlyStopping" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9361c4b-0819-45a0-b9a4-5089914cd280", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19a63a56-6aff-4459-9765-1242403443b5", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "dataset = \"fbv/thesis/ise_supervised_log_standardized_clipped:latest\"\n", - "artifact = run.use_artifact(dataset)\n", - "data_dir = artifact.download()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13bf75ce-b0b4-4198-9be7-f0da4e699f60", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# preserve relative ordering, sample for testing ace\n", - "frac = 1\n", - "\n", - "# sample\n", - "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\").sample(frac=frac)\n", - "y_train = X_train[\"buy_sell\"]\n", - "X_train = X_train[features_classical_size]\n", - "\n", - "X_val = pd.read_parquet(Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\").sample(frac=frac)\n", - "y_val = X_val[\"buy_sell\"]\n", - "X_val = X_val[features_classical_size]\n", - "\n", - "X_test = pd.read_parquet(Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\")\n", - "y_test = X_test[\"buy_sell\"]\n", - "X_test = X_test[features_classical_size]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "56360209-b30d-47a1-bb88-c34112178ecb", - "metadata": {}, - "outputs": [], - "source": [ - "class LogisticRegression(nn.Module):\n", - " def __init__(self, input_size, num_classes):\n", - " super(LogisticRegression, self).__init__()\n", - " self.linear = nn.Linear(input_size, num_classes)\n", - "\n", - " def forward(self, x_cat, x_cont):\n", - " if x_cat:\n", - " x = torch.cat((x_cat, x_cont), 1)\n", - " else:\n", - " x = x_cont\n", - " return self.linear(x)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c271935-f54d-4b6d-a51c-423c5d5d2818", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "training_data = TabDataset(X_train, y_train)\n", - "val_data = TabDataset(X_val, y_val)\n", - "test_data = TabDataset(X_test, y_test)\n", - "\n", - "dl_params = {\n", - " \"batch_size\": 32768, \n", - " \"device\": \"cuda\",\n", - " \"shuffle\": True,\n", - "}\n", - "\n", - "\n", - "train_loader = TabDataLoader(\n", - " training_data.x_cat,\n", - " training_data.x_cont,\n", - " training_data.weight,\n", - " training_data.y,\n", - " **dl_params\n", - ")\n", - "val_loader = TabDataLoader(\n", - " val_data.x_cat, val_data.x_cont, val_data.weight, val_data.y, **dl_params\n", - ")\n", - "\n", - "test_loader = TabDataLoader(\n", - " test_data.x_cat, test_data.x_cont, test_data.weight, test_data.y, **dl_params\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "359c2ccf-8984-4ce1-ae41-f1dcb0ae3d2d", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", - "\n", - "clf = LogisticRegression(input_size=X_train.shape[1],num_classes=1).to(\"cuda\")\n", - "\n", - "criterion = nn.BCEWithLogitsLoss()\n", - "\n", - "optimizer = optim.AdamW(clf.parameters(),\n", - " lr=optim_params[\"lr\"],\n", - " weight_decay=optim_params[\"weight_decay\"],\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a57c959b-29fa-4329-a1d5-c05bea812dcc", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# half precision, see https://pytorch.org/docs/stable/amp.html\n", - "scaler = torch.cuda.amp.GradScaler()\n", - "early_stopping = EarlyStopping(patience=15)\n", - "epochs = 100\n", - "\n", - "step = 0\n", - "best_accuracy = -1\n", - "best_step = -1\n", - "\n", - "\n", - "for epoch in tqdm(range(epochs)):\n", - "\n", - " # perform training\n", - " loss_in_epoch_train = 0\n", - "\n", - " batch = 0\n", - " \n", - " for x_cat, x_cont, weights, targets in train_loader:\n", - " \n", - " clf.train()\n", - " optimizer.zero_grad()\n", - "\n", - " with torch.autocast(device_type='cuda', dtype=torch.float16):\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " train_loss = criterion(logits, targets)\n", - "\n", - " scaler.scale(train_loss).backward()\n", - " scaler.step(optimizer)\n", - " scaler.update()\n", - " \n", - " # add the mini-batch training loss to epoch loss\n", - " loss_in_epoch_train += train_loss # .item()\n", - " wandb.log({\"train_loss_step\": train_loss, \"epoch\": epoch, \"batch\": batch})\n", - " \n", - " batch += 1\n", - " step +=1\n", - "\n", - " clf.eval()\n", - " loss_in_epoch_val = 0.0\n", - " correct = 0\n", - " \n", - " with torch.no_grad():\n", - " for x_cat, x_cont, weights, targets in val_loader:\n", - " \n", - " # for my implementation\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " logits = logits.flatten()\n", - "\n", - " val_loss = criterion(logits, targets)\n", - " \n", - " # get probabilities and round to nearest integer\n", - " preds = torch.sigmoid(logits).round()\n", - " correct += (preds == targets).sum().item()\n", - "\n", - " loss_in_epoch_val += val_loss # val_loss #.item()\n", - " wandb.log({\"val_loss_step\": val_loss, \"epoch\": epoch, \"batch\": batch})\n", - " \n", - " batch +=1 \n", - "\n", - " # loss average over all batches\n", - " train_loss = loss_in_epoch_train / len(train_loader)\n", - " val_loss = loss_in_epoch_val / len(val_loader)\n", - " \n", - " # correct samples / no samples\n", - " val_accuracy = correct / len(X_val)\n", - " if best_accuracy < val_accuracy:\n", - " best_accuracy = val_accuracy\n", - " best_step = step\n", - " \n", - " \n", - " wandb.log({\"train_loss\": train_loss, 'epoch': epoch})\n", - " wandb.log({\"val_loss\": val_loss, 'epoch': epoch})\n", - " # wandb.log({\"val_accuracy\": val_accuracy, 'epoch': epoch}) \n", - " \n", - " print(f\"train:{train_loss} val:{val_loss}\")\n", - " print(f\"val accuracy:{val_accuracy}\")\n", - "\n", - " # return early if val accuracy doesn't improve. Minus to minimize.\n", - " early_stopping(-val_accuracy)\n", - " if early_stopping.early_stop or math.isnan(train_loss) or math.isnan(val_loss):\n", - " print(\"early stopping now.\")\n", - " break\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b73fd9d-9260-4866-9cb5-0928dcece535", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "y_pred, y_true = [], []\n", - "\n", - "for x_cat, x_cont, weights, targets in test_loader:\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " logits = logits.flatten()\n", - "\n", - " # map between zero and one, sigmoid is otherwise included in loss already\n", - " # https://stackoverflow.com/a/66910866/5755604\n", - " preds = torch.sigmoid(logits.squeeze())\n", - " y_pred.append(preds.detach().cpu().numpy())\n", - " y_true.append(targets.detach().cpu().numpy()) \n", - "\n", - "# round prediction to nearest int\n", - "y_pred = np.rint(np.concatenate(y_pred))\n", - "y_true = np.concatenate(y_true)\n", - "\n", - "# calculate accuracy on validation set\n", - "acc = (y_pred == y_true).sum() / len(y_true)\n", - "print(acc)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "thesis", - "language": "python", - "name": "thesis" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "98b853e9-a97e-4a0b-b1af-1bd0ede09c77", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "\n", + "import math\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import torch\n", + "import wandb\n", + "from torch import nn\n", + "from torch import nn, optim\n", + "from tqdm.auto import tqdm\n", + "\n", + "sys.path.append(\"..\")\n", + "from otc.data.dataset import TabDataset\n", + "from otc.data.dataloader import TabDataLoader\n", + "from otc.features.build_features import features_classical_size\n", + "from otc.optim.early_stopping import EarlyStopping" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9361c4b-0819-45a0-b9a4-5089914cd280", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19a63a56-6aff-4459-9765-1242403443b5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "dataset = \"fbv/thesis/ise_supervised_log_standardized_clipped:latest\"\n", + "artifact = run.use_artifact(dataset)\n", + "data_dir = artifact.download()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13bf75ce-b0b4-4198-9be7-f0da4e699f60", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# preserve relative ordering, sample for testing ace\n", + "frac = 1\n", + "\n", + "# sample\n", + "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\").sample(frac=frac)\n", + "y_train = X_train[\"buy_sell\"]\n", + "X_train = X_train[features_classical_size]\n", + "\n", + "X_val = pd.read_parquet(Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\").sample(frac=frac)\n", + "y_val = X_val[\"buy_sell\"]\n", + "X_val = X_val[features_classical_size]\n", + "\n", + "X_test = pd.read_parquet(Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\")\n", + "y_test = X_test[\"buy_sell\"]\n", + "X_test = X_test[features_classical_size]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "56360209-b30d-47a1-bb88-c34112178ecb", + "metadata": {}, + "outputs": [], + "source": [ + "class LogisticRegression(nn.Module):\n", + " def __init__(self, input_size, num_classes):\n", + " super(LogisticRegression, self).__init__()\n", + " self.linear = nn.Linear(input_size, num_classes)\n", + "\n", + " def forward(self, x_cat, x_cont):\n", + " if x_cat:\n", + " x = torch.cat((x_cat, x_cont), 1)\n", + " else:\n", + " x = x_cont\n", + " return self.linear(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c271935-f54d-4b6d-a51c-423c5d5d2818", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "training_data = TabDataset(X_train, y_train)\n", + "val_data = TabDataset(X_val, y_val)\n", + "test_data = TabDataset(X_test, y_test)\n", + "\n", + "dl_params = {\n", + " \"batch_size\": 32768, \n", + " \"device\": \"cuda\",\n", + " \"shuffle\": True,\n", + "}\n", + "\n", + "\n", + "train_loader = TabDataLoader(\n", + " training_data.x_cat,\n", + " training_data.x_cont,\n", + " training_data.weight,\n", + " training_data.y,\n", + " **dl_params\n", + ")\n", + "val_loader = TabDataLoader(\n", + " val_data.x_cat, val_data.x_cont, val_data.weight, val_data.y, **dl_params\n", + ")\n", + "\n", + "test_loader = TabDataLoader(\n", + " test_data.x_cat, test_data.x_cont, test_data.weight, test_data.y, **dl_params\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "359c2ccf-8984-4ce1-ae41-f1dcb0ae3d2d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", + "\n", + "clf = LogisticRegression(input_size=X_train.shape[1],num_classes=1).to(\"cuda\")\n", + "\n", + "criterion = nn.BCEWithLogitsLoss()\n", + "\n", + "optimizer = optim.AdamW(clf.parameters(),\n", + " lr=optim_params[\"lr\"],\n", + " weight_decay=optim_params[\"weight_decay\"],\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a57c959b-29fa-4329-a1d5-c05bea812dcc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# half precision, see https://pytorch.org/docs/stable/amp.html\n", + "scaler = torch.cuda.amp.GradScaler()\n", + "early_stopping = EarlyStopping(patience=15)\n", + "epochs = 100\n", + "\n", + "step = 0\n", + "best_accuracy = -1\n", + "best_step = -1\n", + "\n", + "\n", + "for epoch in tqdm(range(epochs)):\n", + "\n", + " # perform training\n", + " loss_in_epoch_train = 0\n", + "\n", + " batch = 0\n", + " \n", + " for x_cat, x_cont, weights, targets in train_loader:\n", + " \n", + " clf.train()\n", + " optimizer.zero_grad()\n", + "\n", + " with torch.autocast(device_type='cuda', dtype=torch.float16):\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " train_loss = criterion(logits, targets)\n", + "\n", + " scaler.scale(train_loss).backward()\n", + " scaler.step(optimizer)\n", + " scaler.update()\n", + " \n", + " # add the mini-batch training loss to epoch loss\n", + " loss_in_epoch_train += train_loss # .item()\n", + " wandb.log({\"train_loss_step\": train_loss, \"epoch\": epoch, \"batch\": batch})\n", + " \n", + " batch += 1\n", + " step +=1\n", + "\n", + " clf.eval()\n", + " loss_in_epoch_val = 0.0\n", + " correct = 0\n", + " \n", + " with torch.no_grad():\n", + " for x_cat, x_cont, weights, targets in val_loader:\n", + " \n", + " # for my implementation\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " logits = logits.flatten()\n", + "\n", + " val_loss = criterion(logits, targets)\n", + " \n", + " # get probabilities and round to nearest integer\n", + " preds = torch.sigmoid(logits).round()\n", + " correct += (preds == targets).sum().item()\n", + "\n", + " loss_in_epoch_val += val_loss # val_loss #.item()\n", + " wandb.log({\"val_loss_step\": val_loss, \"epoch\": epoch, \"batch\": batch})\n", + " \n", + " batch +=1 \n", + "\n", + " # loss average over all batches\n", + " train_loss = loss_in_epoch_train / len(train_loader)\n", + " val_loss = loss_in_epoch_val / len(val_loader)\n", + " \n", + " # correct samples / no samples\n", + " val_accuracy = correct / len(X_val)\n", + " if best_accuracy < val_accuracy:\n", + " best_accuracy = val_accuracy\n", + " best_step = step\n", + " \n", + " \n", + " wandb.log({\"train_loss\": train_loss, 'epoch': epoch})\n", + " wandb.log({\"val_loss\": val_loss, 'epoch': epoch})\n", + " # wandb.log({\"val_accuracy\": val_accuracy, 'epoch': epoch}) \n", + " \n", + " print(f\"train:{train_loss} val:{val_loss}\")\n", + " print(f\"val accuracy:{val_accuracy}\")\n", + "\n", + " # return early if val accuracy doesn't improve. Minus to minimize.\n", + " early_stopping(-val_accuracy)\n", + " if early_stopping.early_stop or math.isnan(train_loss) or math.isnan(val_loss):\n", + " print(\"early stopping now.\")\n", + " break\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b73fd9d-9260-4866-9cb5-0928dcece535", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "y_pred, y_true = [], []\n", + "\n", + "for x_cat, x_cont, weights, targets in test_loader:\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " logits = logits.flatten()\n", + "\n", + " # map between zero and one, sigmoid is otherwise included in loss already\n", + " # https://stackoverflow.com/a/66910866/5755604\n", + " preds = torch.sigmoid(logits.squeeze())\n", + " y_pred.append(preds.detach().cpu().numpy())\n", + " y_true.append(targets.detach().cpu().numpy()) \n", + "\n", + "# round prediction to nearest int\n", + "y_pred = np.rint(np.concatenate(y_pred))\n", + "y_true = np.concatenate(y_true)\n", + "\n", + "# calculate accuracy on validation set\n", + "acc = (y_pred == y_true).sum() / len(y_true)\n", + "print(acc)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "thesis", + "language": "python", + "name": "thesis" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/4.0b-mb-fttransformer.ipynb b/notebooks/4.0b-mb-fttransformer.ipynb index 2fdf6f26..f641fffe 100644 --- a/notebooks/4.0b-mb-fttransformer.ipynb +++ b/notebooks/4.0b-mb-fttransformer.ipynb @@ -1,455 +1,455 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "id": "98b853e9-a97e-4a0b-b1af-1bd0ede09c77", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "import glob\n", - "import os\n", - "import math\n", - "import sys\n", - "from pathlib import Path\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "import wandb\n", - "import torch\n", - "from torch import optim, nn\n", - "from tqdm.auto import tqdm\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6e34dde1", - "metadata": {}, - "outputs": [], - "source": [ - "sys.path.append(\"..\")\n", - "from otc.models.fttransformer import FeatureTokenizer, FTTransformer, Transformer\n", - "from otc.models.activation import ReGLU\n", - "from otc.data.dataset import TabDataset\n", - "from otc.data.dataloader import TabDataLoader\n", - "from otc.features.build_features import features_classical_size\n", - "from otc.optim.early_stopping import EarlyStopping\n", - "from otc.optim.scheduler import CosineWarmupScheduler" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e9361c4b-0819-45a0-b9a4-5089914cd280", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "19a63a56-6aff-4459-9765-1242403443b5", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "dataset = \"fbv/thesis/ise_supervised_log_standardized_clipped:latest\"\n", - "artifact = run.use_artifact(dataset)\n", - "data_dir = artifact.download()\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "13bf75ce-b0b4-4198-9be7-f0da4e699f60", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# preserve relative ordering, sample for testing ache\n", - "frac = 0.05\n", - "\n", - "# sample\n", - "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\")\n", - "X_train = X_train.sample(frac=frac, random_state=42)\n", - "y_train = X_train[\"buy_sell\"]\n", - "X_train = X_train[features_classical_size]\n", - "\n", - "X_val = pd.read_parquet(Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\").sample(\n", - " frac=frac, random_state=42\n", - ")\n", - "y_val = X_val[\"buy_sell\"]\n", - "X_val = X_val[features_classical_size]\n", - "\n", - "X_test = pd.read_parquet(Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\")\n", - "y_test = X_test[\"buy_sell\"]\n", - "X_test = X_test[features_classical_size]\n", - "\n", - "# eps = 0.1\n", - "# y_train[np.where(y_train == 0)] = eps\n", - "# y_train[np.where(y_train == 1)] = 1.0 - eps\n" - ] - }, - { - "cell_type": "markdown", - "id": "df1cabe5-50b4-42ca-997a-a685739ed097", - "metadata": {}, - "source": [ - "## Run Area" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cdf1535c-438d-4db7-aee6-b0f1bbf39d60", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "frac = 1\n", - "\n", - "device = \"cuda\"\n", - "batch_size = 16192\n", - "epochs = 100\n", - "\n", - "d_token = 192\n", - "n_blocks = 3\n", - "attention_dropout = 0.2\n", - "ffn_dropout = 0.1\n", - "residual_dropout = 0.0\n", - "attention_heads = 8\n", - "\n", - "\n", - "# clipping_value = 5\n", - "reduction = \"mean\"\n", - "\n", - "feature_tokenizer_kwargs = {\n", - " \"num_continous\": len(X_train.columns.tolist()),\n", - " \"cat_cardinalities\": (),\n", - " \"d_token\": d_token,\n", - "}\n", - "\n", - "dl_params = {\n", - " \"batch_size\": batch_size, # dataprallel splits batches across devices\n", - " \"shuffle\": False,\n", - " \"device\": device,\n", - "}\n", - "\n", - "transformer_kwargs = {\n", - " \"d_token\": d_token,\n", - " \"n_blocks\": n_blocks,\n", - " \"attention_n_heads\": attention_heads,\n", - " \"attention_initialization\": \"kaiming\",\n", - " \"ffn_activation\": ReGLU,\n", - " \"attention_normalization\": nn.LayerNorm,\n", - " \"ffn_normalization\": nn.LayerNorm,\n", - " \"ffn_dropout\": ffn_dropout,\n", - " # fix at 4/3, as activation (see search space B in\n", - " # https://arxiv.org/pdf/2106.11959v2.pdf)\n", - " # is static with ReGLU / GeGLU\n", - " \"ffn_d_hidden\": int(d_token * (4 / 3)),\n", - " \"attention_dropout\": attention_dropout,\n", - " \"residual_dropout\": residual_dropout, # see search space (B)\n", - " \"prenormalization\": True,\n", - " \"first_prenormalization\": False,\n", - " \"last_layer_query_idx\": None,\n", - " \"n_tokens\": None,\n", - " \"kv_compression_ratio\": None,\n", - " \"kv_compression_sharing\": None,\n", - " \"head_activation\": nn.GELU, # nn.ReLU\n", - " \"head_normalization\": nn.LayerNorm,\n", - " \"d_out\": 1, # fix at 1, due to binary classification\n", - "}\n", - "\n", - "\n", - "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", - "\n", - "module_params = {\n", - " \"transformer\": Transformer(**transformer_kwargs), \n", - " \"feature_tokenizer\": FeatureTokenizer(**feature_tokenizer_kwargs), # noqa: E501\n", - " \"cat_features\": None,\n", - " \"cat_cardinalities\": [],\n", - "}\n", - "\n", - "clf = FTTransformer(**module_params)\n", - "# use multiple gpus, if available\n", - "clf = nn.DataParallel(clf).to(device)\n", - "\n", - "\n", - "criterion = nn.BCEWithLogitsLoss()\n", - "# wandb.log(other_kwargs)\n", - "# wandb.log(transformer_kwargs)\n", - "# wandb.log(optim_params)\n", - "# wandb.log(feature_tokenizer_kwargs)\n", - "# wandb.log(dl_params)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2c271935-f54d-4b6d-a51c-423c5d5d2818", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "training_data = TabDataset(X_train, y_train)\n", - "val_data = TabDataset(X_val, y_val)\n", - "test_data = TabDataset(X_test, y_test)\n", - "\n", - "train_loader = TabDataLoader(\n", - " training_data.x_cat,\n", - " training_data.x_cont,\n", - " training_data.weight,\n", - " training_data.y,\n", - " **dl_params\n", - ")\n", - "val_loader = TabDataLoader(\n", - " val_data.x_cat, val_data.x_cont, val_data.weight, val_data.y, **dl_params\n", - ")\n", - "\n", - "test_loader = TabDataLoader(\n", - " test_data.x_cat, test_data.x_cont, test_data.weight, test_data.y, **dl_params\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "359c2ccf-8984-4ce1-ae41-f1dcb0ae3d2d", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "optimizer = optim.AdamW(\n", - " clf.parameters(),\n", - " lr=optim_params[\"lr\"],\n", - " weight_decay=optim_params[\"weight_decay\"],\n", - ")\n", - "\n", - "max_iters = epochs * len(train_loader)\n", - "# saw recommendation of 5 - 10 % of total training budget or 100 to 500 steps\n", - "warmup = int(0.05 * max_iters)\n", - "print(f\"warmup steps: {warmup}\")\n", - "print(max_iters)\n", - "\n", - "\n", - "scheduler = CosineWarmupScheduler(\n", - " optimizer=optimizer, warmup=warmup, max_iters=max_iters\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "99743844-ba1e-4a9c-8650-8ce14ca48385", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "def checkpoint(model, filename):\n", - "\n", - " # remove old files\n", - " for filename in glob.glob(f\"checkpoints/{run.id}*\"):\n", - " os.remove(filename)\n", - "\n", - " # create_dir\n", - " dir_checkpoints = \"checkpoints/\"\n", - " os.makedirs(dir_checkpoints, exist_ok=True)\n", - "\n", - " # save new file\n", - " print(\"saving new checkpoints.\")\n", - " torch.save(model.state_dict(), os.path.join(dir_checkpoints, f\"{run.id}*\"))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a57c959b-29fa-4329-a1d5-c05bea812dcc", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# half precision, see https://pytorch.org/docs/stable/amp.html\n", - "scaler = torch.cuda.amp.GradScaler()\n", - "\n", - "\n", - "early_stopping = EarlyStopping(patience=15)\n", - "\n", - "# see https://stackoverflow.com/a/53628783/5755604\n", - "# no sigmoid required; numerically more stable\n", - "# do not reduce, calculate mean after multiplication with weight\n", - "\n", - "step = 0\n", - "best_accuracy = -1\n", - "best_step = -1\n", - "\n", - "for epoch in tqdm(range(epochs)):\n", - "\n", - " # perform training\n", - " loss_in_epoch_train = 0\n", - "\n", - " batch = 0\n", - "\n", - " for x_cat, x_cont, _, targets in train_loader:\n", - "\n", - " clf.train()\n", - " optimizer.zero_grad()\n", - "\n", - " # for my implementation\n", - " with torch.autocast(device_type=\"cuda\", dtype=torch.float16):\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " train_loss = criterion(logits, targets)\n", - "\n", - " scaler.scale(train_loss).backward()\n", - " scaler.step(optimizer)\n", - " scaler.update()\n", - "\n", - " scheduler.step()\n", - "\n", - " # add the mini-batch training loss to epoch loss\n", - " loss_in_epoch_train += train_loss.item()\n", - " wandb.log({\"train_loss_step\": train_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", - "\n", - " batch += 1\n", - " step += 1\n", - "\n", - " clf.eval()\n", - " loss_in_epoch_val = 0.0\n", - " correct = 0\n", - "\n", - " with torch.no_grad():\n", - " for x_cat, x_cont, _, targets in val_loader:\n", - "\n", - " # for my implementation\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " logits = logits.flatten()\n", - "\n", - " val_loss = criterion(logits, targets)\n", - "\n", - " # get probabilities and round to nearest integer\n", - " preds = torch.sigmoid(logits).round()\n", - " correct += (preds == targets).sum().item()\n", - "\n", - " loss_in_epoch_val += val_loss.item()\n", - " wandb.log({\"val_loss_step\": val_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", - "\n", - " batch += 1\n", - "\n", - " # loss average over all batches\n", - " train_loss = loss_in_epoch_train / len(train_loader)\n", - " val_loss = loss_in_epoch_val / len(val_loader)\n", - "\n", - " # correct samples / no samples\n", - " val_accuracy = correct / len(X_val)\n", - " if best_accuracy < val_accuracy:\n", - " checkpoint(clf, f\"checkpoints/{run.id}-{step}.ptx\")\n", - " best_accuracy = val_accuracy\n", - " best_step = step\n", - "\n", - " wandb.log({\"train_loss\": train_loss, \"epoch\": epoch})\n", - " wandb.log({\"val_loss\": val_loss, \"epoch\": epoch})\n", - "\n", - " print(f\"train:{train_loss} val:{val_loss}\")\n", - " print(f\"val accuracy:{val_accuracy}\")\n", - "\n", - " # return early if val accuracy doesn't improve. Minus to minimize.\n", - " early_stopping(-val_accuracy)\n", - " if early_stopping.early_stop or math.isnan(train_loss) or math.isnan(val_loss):\n", - " print(\"meh... early stopping\")\n", - " break\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "51ca46d5-7448-4e63-8d93-ff3773fe5753", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "cp = glob.glob(f\"checkpoints/{run.id}*\")\n", - "print(cp)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4ca09c3b-6598-4a6f-be55-ce0cf7de61d1", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "clf.load_state_dict(torch.load(cp[0]))\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6b73fd9d-9260-4866-9cb5-0928dcece535", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "y_pred, y_true = [], []\n", - "\n", - "for x_cat, x_cont, _, targets in test_loader:\n", - "\n", - " logits = clf(x_cat, x_cont).flatten()\n", - " logits = logits.flatten()\n", - "\n", - " # map between zero and one, sigmoid is otherwise included in loss already\n", - " # https://stackoverflow.com/a/66910866/5755604\n", - " preds = torch.sigmoid(logits.squeeze())\n", - " y_pred.append(preds.detach().cpu().numpy())\n", - " y_true.append(targets.detach().cpu().numpy()) \n", - "\n", - "# round prediction to nearest int\n", - "y_pred = np.rint(np.concatenate(y_pred))\n", - "y_true = np.concatenate(y_true)\n", - "\n", - "acc = (y_pred == y_true).sum() / len(y_true) \n", - "print(acc)\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "thesis2", - "language": "python", - "name": "thesis2" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "98b853e9-a97e-4a0b-b1af-1bd0ede09c77", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import glob\n", + "import os\n", + "import math\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "import wandb\n", + "import torch\n", + "from torch import optim, nn\n", + "from tqdm.auto import tqdm\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e34dde1", + "metadata": {}, + "outputs": [], + "source": [ + "sys.path.append(\"..\")\n", + "from otc.models.fttransformer import FeatureTokenizer, FTTransformer, Transformer\n", + "from otc.models.activation import ReGLU\n", + "from otc.data.dataset import TabDataset\n", + "from otc.data.dataloader import TabDataLoader\n", + "from otc.features.build_features import features_classical_size\n", + "from otc.optim.early_stopping import EarlyStopping\n", + "from otc.optim.scheduler import CosineWarmupScheduler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9361c4b-0819-45a0-b9a4-5089914cd280", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19a63a56-6aff-4459-9765-1242403443b5", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "dataset = \"fbv/thesis/ise_supervised_log_standardized_clipped:latest\"\n", + "artifact = run.use_artifact(dataset)\n", + "data_dir = artifact.download()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "13bf75ce-b0b4-4198-9be7-f0da4e699f60", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# preserve relative ordering, sample for testing ache\n", + "frac = 0.05\n", + "\n", + "# sample\n", + "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\")\n", + "X_train = X_train.sample(frac=frac, random_state=42)\n", + "y_train = X_train[\"buy_sell\"]\n", + "X_train = X_train[features_classical_size]\n", + "\n", + "X_val = pd.read_parquet(Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\").sample(\n", + " frac=frac, random_state=42\n", + ")\n", + "y_val = X_val[\"buy_sell\"]\n", + "X_val = X_val[features_classical_size]\n", + "\n", + "X_test = pd.read_parquet(Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\")\n", + "y_test = X_test[\"buy_sell\"]\n", + "X_test = X_test[features_classical_size]\n", + "\n", + "# eps = 0.1\n", + "# y_train[np.where(y_train == 0)] = eps\n", + "# y_train[np.where(y_train == 1)] = 1.0 - eps\n" + ] + }, + { + "cell_type": "markdown", + "id": "df1cabe5-50b4-42ca-997a-a685739ed097", + "metadata": {}, + "source": [ + "## Run Area" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cdf1535c-438d-4db7-aee6-b0f1bbf39d60", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "frac = 1\n", + "\n", + "device = \"cuda\"\n", + "batch_size = 16192\n", + "epochs = 100\n", + "\n", + "d_token = 192\n", + "n_blocks = 3\n", + "attention_dropout = 0.2\n", + "ffn_dropout = 0.1\n", + "residual_dropout = 0.0\n", + "attention_heads = 8\n", + "\n", + "\n", + "# clipping_value = 5\n", + "reduction = \"mean\"\n", + "\n", + "feature_tokenizer_kwargs = {\n", + " \"num_continous\": len(X_train.columns.tolist()),\n", + " \"cat_cardinalities\": (),\n", + " \"d_token\": d_token,\n", + "}\n", + "\n", + "dl_params = {\n", + " \"batch_size\": batch_size, # dataprallel splits batches across devices\n", + " \"shuffle\": False,\n", + " \"device\": device,\n", + "}\n", + "\n", + "transformer_kwargs = {\n", + " \"d_token\": d_token,\n", + " \"n_blocks\": n_blocks,\n", + " \"attention_n_heads\": attention_heads,\n", + " \"attention_initialization\": \"kaiming\",\n", + " \"ffn_activation\": ReGLU,\n", + " \"attention_normalization\": nn.LayerNorm,\n", + " \"ffn_normalization\": nn.LayerNorm,\n", + " \"ffn_dropout\": ffn_dropout,\n", + " # fix at 4/3, as activation (see search space B in\n", + " # https://arxiv.org/pdf/2106.11959v2.pdf)\n", + " # is static with ReGLU / GeGLU\n", + " \"ffn_d_hidden\": int(d_token * (4 / 3)),\n", + " \"attention_dropout\": attention_dropout,\n", + " \"residual_dropout\": residual_dropout, # see search space (B)\n", + " \"prenormalization\": True,\n", + " \"first_prenormalization\": False,\n", + " \"last_layer_query_idx\": None,\n", + " \"n_tokens\": None,\n", + " \"kv_compression_ratio\": None,\n", + " \"kv_compression_sharing\": None,\n", + " \"head_activation\": nn.GELU, # nn.ReLU\n", + " \"head_normalization\": nn.LayerNorm,\n", + " \"d_out\": 1, # fix at 1, due to binary classification\n", + "}\n", + "\n", + "\n", + "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", + "\n", + "module_params = {\n", + " \"transformer\": Transformer(**transformer_kwargs), \n", + " \"feature_tokenizer\": FeatureTokenizer(**feature_tokenizer_kwargs), # noqa: E501\n", + " \"cat_features\": None,\n", + " \"cat_cardinalities\": [],\n", + "}\n", + "\n", + "clf = FTTransformer(**module_params)\n", + "# use multiple gpus, if available\n", + "clf = nn.DataParallel(clf).to(device)\n", + "\n", + "\n", + "criterion = nn.BCEWithLogitsLoss()\n", + "# wandb.log(other_kwargs)\n", + "# wandb.log(transformer_kwargs)\n", + "# wandb.log(optim_params)\n", + "# wandb.log(feature_tokenizer_kwargs)\n", + "# wandb.log(dl_params)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c271935-f54d-4b6d-a51c-423c5d5d2818", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "training_data = TabDataset(X_train, y_train)\n", + "val_data = TabDataset(X_val, y_val)\n", + "test_data = TabDataset(X_test, y_test)\n", + "\n", + "train_loader = TabDataLoader(\n", + " training_data.x_cat,\n", + " training_data.x_cont,\n", + " training_data.weight,\n", + " training_data.y,\n", + " **dl_params\n", + ")\n", + "val_loader = TabDataLoader(\n", + " val_data.x_cat, val_data.x_cont, val_data.weight, val_data.y, **dl_params\n", + ")\n", + "\n", + "test_loader = TabDataLoader(\n", + " test_data.x_cat, test_data.x_cont, test_data.weight, test_data.y, **dl_params\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "359c2ccf-8984-4ce1-ae41-f1dcb0ae3d2d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "optimizer = optim.AdamW(\n", + " clf.parameters(),\n", + " lr=optim_params[\"lr\"],\n", + " weight_decay=optim_params[\"weight_decay\"],\n", + ")\n", + "\n", + "max_iters = epochs * len(train_loader)\n", + "# saw recommendation of 5 - 10 % of total training budget or 100 to 500 steps\n", + "warmup = int(0.05 * max_iters)\n", + "print(f\"warmup steps: {warmup}\")\n", + "print(max_iters)\n", + "\n", + "\n", + "scheduler = CosineWarmupScheduler(\n", + " optimizer=optimizer, warmup=warmup, max_iters=max_iters\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "99743844-ba1e-4a9c-8650-8ce14ca48385", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def checkpoint(model, filename):\n", + "\n", + " # remove old files\n", + " for filename in glob.glob(f\"checkpoints/{run.id}*\"):\n", + " os.remove(filename)\n", + "\n", + " # create_dir\n", + " dir_checkpoints = \"checkpoints/\"\n", + " os.makedirs(dir_checkpoints, exist_ok=True)\n", + "\n", + " # save new file\n", + " print(\"saving new checkpoints.\")\n", + " torch.save(model.state_dict(), os.path.join(dir_checkpoints, f\"{run.id}*\"))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a57c959b-29fa-4329-a1d5-c05bea812dcc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# half precision, see https://pytorch.org/docs/stable/amp.html\n", + "scaler = torch.cuda.amp.GradScaler()\n", + "\n", + "\n", + "early_stopping = EarlyStopping(patience=15)\n", + "\n", + "# see https://stackoverflow.com/a/53628783/5755604\n", + "# no sigmoid required; numerically more stable\n", + "# do not reduce, calculate mean after multiplication with weight\n", + "\n", + "step = 0\n", + "best_accuracy = -1\n", + "best_step = -1\n", + "\n", + "for epoch in tqdm(range(epochs)):\n", + "\n", + " # perform training\n", + " loss_in_epoch_train = 0\n", + "\n", + " batch = 0\n", + "\n", + " for x_cat, x_cont, _, targets in train_loader:\n", + "\n", + " clf.train()\n", + " optimizer.zero_grad()\n", + "\n", + " # for my implementation\n", + " with torch.autocast(device_type=\"cuda\", dtype=torch.float16):\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " train_loss = criterion(logits, targets)\n", + "\n", + " scaler.scale(train_loss).backward()\n", + " scaler.step(optimizer)\n", + " scaler.update()\n", + "\n", + " scheduler.step()\n", + "\n", + " # add the mini-batch training loss to epoch loss\n", + " loss_in_epoch_train += train_loss.item()\n", + " wandb.log({\"train_loss_step\": train_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", + "\n", + " batch += 1\n", + " step += 1\n", + "\n", + " clf.eval()\n", + " loss_in_epoch_val = 0.0\n", + " correct = 0\n", + "\n", + " with torch.no_grad():\n", + " for x_cat, x_cont, _, targets in val_loader:\n", + "\n", + " # for my implementation\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " logits = logits.flatten()\n", + "\n", + " val_loss = criterion(logits, targets)\n", + "\n", + " # get probabilities and round to nearest integer\n", + " preds = torch.sigmoid(logits).round()\n", + " correct += (preds == targets).sum().item()\n", + "\n", + " loss_in_epoch_val += val_loss.item()\n", + " wandb.log({\"val_loss_step\": val_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", + "\n", + " batch += 1\n", + "\n", + " # loss average over all batches\n", + " train_loss = loss_in_epoch_train / len(train_loader)\n", + " val_loss = loss_in_epoch_val / len(val_loader)\n", + "\n", + " # correct samples / no samples\n", + " val_accuracy = correct / len(X_val)\n", + " if best_accuracy < val_accuracy:\n", + " checkpoint(clf, f\"checkpoints/{run.id}-{step}.ptx\")\n", + " best_accuracy = val_accuracy\n", + " best_step = step\n", + "\n", + " wandb.log({\"train_loss\": train_loss, \"epoch\": epoch})\n", + " wandb.log({\"val_loss\": val_loss, \"epoch\": epoch})\n", + "\n", + " print(f\"train:{train_loss} val:{val_loss}\")\n", + " print(f\"val accuracy:{val_accuracy}\")\n", + "\n", + " # return early if val accuracy doesn't improve. Minus to minimize.\n", + " early_stopping(-val_accuracy)\n", + " if early_stopping.early_stop or math.isnan(train_loss) or math.isnan(val_loss):\n", + " print(\"meh... early stopping\")\n", + " break\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51ca46d5-7448-4e63-8d93-ff3773fe5753", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "cp = glob.glob(f\"checkpoints/{run.id}*\")\n", + "print(cp)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4ca09c3b-6598-4a6f-be55-ce0cf7de61d1", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "clf.load_state_dict(torch.load(cp[0]))\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6b73fd9d-9260-4866-9cb5-0928dcece535", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "y_pred, y_true = [], []\n", + "\n", + "for x_cat, x_cont, _, targets in test_loader:\n", + "\n", + " logits = clf(x_cat, x_cont).flatten()\n", + " logits = logits.flatten()\n", + "\n", + " # map between zero and one, sigmoid is otherwise included in loss already\n", + " # https://stackoverflow.com/a/66910866/5755604\n", + " preds = torch.sigmoid(logits.squeeze())\n", + " y_pred.append(preds.detach().cpu().numpy())\n", + " y_true.append(targets.detach().cpu().numpy()) \n", + "\n", + "# round prediction to nearest int\n", + "y_pred = np.rint(np.concatenate(y_pred))\n", + "y_true = np.concatenate(y_true)\n", + "\n", + "acc = (y_pred == y_true).sum() / len(y_true) \n", + "print(acc)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "thesis2", + "language": "python", + "name": "thesis2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/4.0e-mb-fttransformer-pretraining.ipynb b/notebooks/4.0e-mb-fttransformer-pretraining.ipynb index 92c4eaa5..9f3c32ef 100644 --- a/notebooks/4.0e-mb-fttransformer-pretraining.ipynb +++ b/notebooks/4.0e-mb-fttransformer-pretraining.ipynb @@ -1,467 +1,467 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import glob\n", - "import os\n", - "from pathlib import Path\n", - "\n", - "import pandas as pd\n", - "\n", - "from tqdm.auto import tqdm\n", - "\n", - "import torch\n", - "import torch.nn as nn\n", - "import torch.optim as optim\n", - "\n", - "import wandb\n", - "\n", - "from otc.models.activation import ReGLU\n", - "from otc.models.fttransformer import (\n", - " FeatureTokenizer,\n", - " FTTransformer,\n", - " Transformer,\n", - " CLSHead,\n", - ")\n", - "\n", - "from otc.data.dataset import TabDataset\n", - "from otc.data.dataloader import TabDataLoader\n", - "from otc.features.build_features import features_classical_size\n", - "from otc.optim.early_stopping import EarlyStopping\n", - "from otc.optim.scheduler import CosineWarmupScheduler" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "dataset = \"fbv/thesis/ise_unsupervised_log_standardized_clipped:latest\"\n", - "artifact = run.use_artifact(dataset)\n", - "data_dir = artifact.download()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# preserve relative ordering, sample for testing ache\n", - "frac = 1 #0.05\n", - "\n", - "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\")\n", - "X_train = X_train.sample(frac=frac, random_state=42)\n", - "\n", - "y_train = X_train[\"buy_sell\"] # here: y = 0\n", - "X_train = X_train[features_classical_size]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "training_data = TabDataset(X_train, y_train)\n", - "x_cont = training_data.x_cont\n", - "x_cat = training_data.x_cat" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def gen_perm(X):\n", - " \"\"\"\n", - " Generate index permutation.\n", - " \"\"\"\n", - " if X is None:\n", - " return None\n", - " return torch.randint_like(X, X.shape[0], dtype=torch.long)\n", - "\n", - "x_cont_perm = gen_perm(x_cont)\n", - "x_cat_perm = gen_perm(x_cat)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def gen_masks(X, perm, corrupt_probability = 0.15):\n", - " \"\"\"\n", - " Generate binary mask for detection.\n", - " \"\"\"\n", - " masks = torch.empty_like(X).bernoulli(p=corrupt_probability).bool()\n", - " new_masks = masks & (X != X[perm, torch.arange(X.shape[1], device=X.device)])\n", - " return new_masks\n", - "\n", - "# generate masks for numeric and for categorical features (optional)\n", - "x_cont_mask = gen_masks(training_data.x_cont, x_cont_perm)\n", - "\n", - "if training_data.x_cat is not None:\n", - " x_cat_mask = gen_masks(training_data.x_cat, x_cat_perm)\n", - "else:\n", - " x_cat_mask = None" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# replace at permutation\n", - "x_cont_permuted = torch.gather(x_cont, 0, x_cont_perm)\n", - "\n", - "# replace at mask = True\n", - "x_cont[x_cont_mask] = x_cont_permuted[x_cont_mask]\n", - "\n", - "if x_cat is not None:\n", - "\n", - " # along the 0 axis get elements based on perm_cat\n", - " x_cat_permuted = torch.gather(x_cat, 0, x_cat_perm)\n", - " \n", - " # replace at mask\n", - " x_cat[x_cat_mask] = x_cat_permuted[x_cat_mask]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# merge masks [mask_num, mask_cat]\n", - "if x_cat != None:\n", - " masks = torch.cat([x_cont_mask, x_cat_mask], dim=1)\n", - "else:\n", - " masks = x_cont_mask" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# split up into train (first 80 %) and val (last 20 %)\n", - "idx = int (len(x_cont) * 0.8)\n", - "\n", - "x_cont_train, x_cont_val = torch.split(x_cont, idx, dim=0)\n", - "masks_train, masks_val = torch.split(masks, idx, dim=0)\n", - "\n", - "if x_cat is not None:\n", - " x_cat_train, x_cat_val = torch.split(x_cat, idx, dim=0)\n", - "else:\n", - " x_cat_train, x_cat_val = None, None\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Runfield πŸ›«" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "device = \"cuda\"\n", - "batch_size = 16192\n", - "epochs = 100\n", - "\n", - "d_token = 192\n", - "n_blocks = 3\n", - "attention_dropout = 0.2\n", - "ffn_dropout = 0.1\n", - "residual_dropout = 0.0\n", - "attention_heads = 8\n", - "\n", - "\n", - "reduction = \"mean\"\n", - "\n", - "dl_params = {\n", - " \"batch_size\": batch_size,\n", - " \"shuffle\": False,\n", - " \"device\": \"cuda\",\n", - "}\n", - "\n", - "feature_tokenizer_kwargs = {\n", - " \"num_continous\": len(X_train.columns.tolist()),\n", - " \"cat_cardinalities\": (),\n", - " \"d_token\": d_token,\n", - "}\n", - "\n", - "dl_params = {\n", - " \"batch_size\": batch_size, # dataprallel splits batches across devices\n", - " \"shuffle\": False,\n", - " \"device\": device,\n", - "}\n", - "\n", - "transformer_kwargs = {\n", - " \"d_token\": d_token,\n", - " \"n_blocks\": n_blocks,\n", - " \"attention_n_heads\": attention_heads,\n", - " \"attention_initialization\": \"kaiming\",\n", - " \"ffn_activation\": ReGLU,\n", - " \"attention_normalization\": nn.LayerNorm,\n", - " \"ffn_normalization\": nn.LayerNorm,\n", - " \"ffn_dropout\": ffn_dropout,\n", - " # fix at 4/3, as activation (see search space B in\n", - " # https://arxiv.org/pdf/2106.11959v2.pdf)\n", - " # is static with ReGLU / GeGLU\n", - " \"ffn_d_hidden\": int(d_token * (4 / 3)),\n", - " \"attention_dropout\": attention_dropout,\n", - " \"residual_dropout\": residual_dropout, # see search space (B)\n", - " \"prenormalization\": True,\n", - " \"first_prenormalization\": False,\n", - " \"last_layer_query_idx\": None,\n", - " \"n_tokens\": None,\n", - " \"kv_compression_ratio\": None,\n", - " \"kv_compression_sharing\": None,\n", - " \"head_activation\": nn.GELU, # nn.ReLU\n", - " \"head_normalization\": nn.LayerNorm,\n", - " \"d_out\": 1, # fix at 1, due to binary classification\n", - "}\n", - "\n", - "head_kwargs = {\"d_in\": d_token, \"d_hidden\": 32}\n", - "\n", - "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", - "\n", - "module_params = {\n", - " \"transformer\": Transformer(**transformer_kwargs), \n", - " \"feature_tokenizer\": FeatureTokenizer(**feature_tokenizer_kwargs), # noqa: E501\n", - " \"cat_features\": None,\n", - " \"cat_cardinalities\": [],\n", - "}\n", - "\n", - "clf = FTTransformer(**module_params)\n", - "criterion = nn.BCEWithLogitsLoss()\n", - "\n", - "# swap target head with classification head, and restore later\n", - "target_head = clf.transformer.head\n", - "clf_head = CLSHead(**head_kwargs)\n", - "clf.transformer.head = clf_head\n", - "\n", - "clf.to(device)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "train_loader = TabDataLoader(\n", - " x_cat_train,\n", - " x_cont_train,\n", - " masks_train, \n", - " **dl_params\n", - ")\n", - "\n", - "val_loader = TabDataLoader(\n", - " x_cat_val,\n", - " x_cont_val,\n", - " masks_val, \n", - " **dl_params\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "optimizer = optim.AdamW(clf.parameters(),\n", - " lr=optim_params[\"lr\"],\n", - " weight_decay=optim_params[\"weight_decay\"],\n", - ")\n", - "\n", - "max_iters = epochs * len(train_loader)\n", - "# saw recommendation of 5 - 10 % of total training budget or 100 to 500 steps\n", - "warmup = int(0.05 * max_iters)\n", - "print(f\"warmup steps: {warmup}\")\n", - "print(max_iters)\n", - "\n", - "scheduler = CosineWarmupScheduler(optimizer=optimizer, warmup=warmup, max_iters=max_iters)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def checkpoint(model):\n", - " \n", - " # remove old files\n", - " for fn in glob.glob(f\"checkpoints/{run.id}*\"):\n", - " os.remove(fn) \n", - " \n", - " # create_dir\n", - " dir_checkpoints = \"checkpoints/\"\n", - " os.makedirs(dir_checkpoints, exist_ok = True) \n", - " \n", - " # save new file\n", - " print(\"saving new checkpoints.\")\n", - " torch.save(model.state_dict(), os.path.join(dir_checkpoints,f\"{run.id}*\"))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# half precision, see https://pytorch.org/docs/stable/amp.html\n", - "scaler = torch.cuda.amp.GradScaler()\n", - "\n", - "early_stopping = EarlyStopping(patience=15)\n", - "\n", - "step = 0\n", - "best_accuracy = -1\n", - "best_step = -1\n", - "\n", - "for epoch in tqdm(range(epochs)):\n", - "\n", - " # perform training\n", - " loss_in_epoch_train = 0\n", - "\n", - " batch = 0\n", - " \n", - " for x_cat, x_cont, masks in train_loader:\n", - " \n", - " clf.train()\n", - " optimizer.zero_grad()\n", - " \n", - " with torch.autocast(device_type='cuda', dtype=torch.float16):\n", - " logits = clf(x_cat, x_cont)\n", - " train_loss = criterion(logits, masks.float())\n", - "\n", - " scaler.scale(train_loss).backward()\n", - " scaler.step(optimizer)\n", - " scaler.update()\n", - " \n", - " scheduler.step()\n", - " \n", - " # add the mini-batch training loss to epoch loss\n", - " loss_in_epoch_train += train_loss.item()\n", - " \n", - " wandb.log({\"train_loss_step\": train_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", - "\n", - " batch += 1\n", - " step +=1\n", - "\n", - " clf.eval()\n", - " loss_in_epoch_val = 0.0\n", - " correct = 0\n", - " \n", - " with torch.no_grad():\n", - " for x_cat, x_cont, masks in val_loader:\n", - "\n", - " # for my implementation\n", - " logits = clf(x_cat, x_cont)\n", - " val_loss = criterion(logits, masks.float())\n", - " \n", - "\n", - " # hard_predictions = torch.zeros_like(logits, dtype=torch.long)\n", - " # hard_predictions[logits > 0] = 1\n", - " # correct += (hard_predictions.bool() == masks).sum() / hard_predictions.shape[0]\n", - "\n", - " loss_in_epoch_val += val_loss.item()\n", - " wandb.log({\"val_loss_step\": val_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", - " \n", - " batch +=1 \n", - "\n", - " # correct / (rows * columns)\n", - " # val_accuracy = correct / (X_train.shape[0] * X_train.shape[1]) \n", - " \n", - " # loss average over all batches\n", - " train_loss = loss_in_epoch_train / len(train_loader)\n", - " val_loss = loss_in_epoch_val / len(val_loader)\n", - " \n", - " print(f\"train loss: {train_loss}\")\n", - " print(f\"val loss: {val_loss}\")\n", - " \n", - " # correct samples / no samples\n", - " # val_accuracy = correct / len(X_val)\n", - " # if best_accuracy < val_accuracy:\n", - " # checkpoint(clf, f\"checkpoints/{run.id}-{step}.ptx\")\n", - " # best_accuracy = val_accuracy\n", - " # best_step = step\n", - " \n", - " \n", - " wandb.log({\"train_loss\": train_loss, 'epoch': epoch})" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Prepare for FinetuningπŸ•°οΈ" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# swap heads and save model\n", - "clf.transformer.head = target_head\n", - "checkpoint(clf)\n", - "\n", - "# FIXME: Think about which weights to freeze and which to update\n", - "# https://ai.stackexchange.com/questions/23884/why-arent-the-bert-layers-frozen-during-fine-tuning-tasks" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "import os\n", + "from pathlib import Path\n", + "\n", + "import pandas as pd\n", + "\n", + "from tqdm.auto import tqdm\n", + "\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.optim as optim\n", + "\n", + "import wandb\n", + "\n", + "from otc.models.activation import ReGLU\n", + "from otc.models.fttransformer import (\n", + " FeatureTokenizer,\n", + " FTTransformer,\n", + " Transformer,\n", + " CLSHead,\n", + ")\n", + "\n", + "from otc.data.dataset import TabDataset\n", + "from otc.data.dataloader import TabDataLoader\n", + "from otc.features.build_features import features_classical_size\n", + "from otc.optim.early_stopping import EarlyStopping\n", + "from otc.optim.scheduler import CosineWarmupScheduler" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "dataset = \"fbv/thesis/ise_unsupervised_log_standardized_clipped:latest\"\n", + "artifact = run.use_artifact(dataset)\n", + "data_dir = artifact.download()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# preserve relative ordering, sample for testing ache\n", + "frac = 1 #0.05\n", + "\n", + "X_train = pd.read_parquet(Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\")\n", + "X_train = X_train.sample(frac=frac, random_state=42)\n", + "\n", + "y_train = X_train[\"buy_sell\"] # here: y = 0\n", + "X_train = X_train[features_classical_size]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "training_data = TabDataset(X_train, y_train)\n", + "x_cont = training_data.x_cont\n", + "x_cat = training_data.x_cat" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_perm(X):\n", + " \"\"\"\n", + " Generate index permutation.\n", + " \"\"\"\n", + " if X is None:\n", + " return None\n", + " return torch.randint_like(X, X.shape[0], dtype=torch.long)\n", + "\n", + "x_cont_perm = gen_perm(x_cont)\n", + "x_cat_perm = gen_perm(x_cat)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def gen_masks(X, perm, corrupt_probability = 0.15):\n", + " \"\"\"\n", + " Generate binary mask for detection.\n", + " \"\"\"\n", + " masks = torch.empty_like(X).bernoulli(p=corrupt_probability).bool()\n", + " new_masks = masks & (X != X[perm, torch.arange(X.shape[1], device=X.device)])\n", + " return new_masks\n", + "\n", + "# generate masks for numeric and for categorical features (optional)\n", + "x_cont_mask = gen_masks(training_data.x_cont, x_cont_perm)\n", + "\n", + "if training_data.x_cat is not None:\n", + " x_cat_mask = gen_masks(training_data.x_cat, x_cat_perm)\n", + "else:\n", + " x_cat_mask = None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# replace at permutation\n", + "x_cont_permuted = torch.gather(x_cont, 0, x_cont_perm)\n", + "\n", + "# replace at mask = True\n", + "x_cont[x_cont_mask] = x_cont_permuted[x_cont_mask]\n", + "\n", + "if x_cat is not None:\n", + "\n", + " # along the 0 axis get elements based on perm_cat\n", + " x_cat_permuted = torch.gather(x_cat, 0, x_cat_perm)\n", + " \n", + " # replace at mask\n", + " x_cat[x_cat_mask] = x_cat_permuted[x_cat_mask]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# merge masks [mask_num, mask_cat]\n", + "if x_cat != None:\n", + " masks = torch.cat([x_cont_mask, x_cat_mask], dim=1)\n", + "else:\n", + " masks = x_cont_mask" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# split up into train (first 80 %) and val (last 20 %)\n", + "idx = int (len(x_cont) * 0.8)\n", + "\n", + "x_cont_train, x_cont_val = torch.split(x_cont, idx, dim=0)\n", + "masks_train, masks_val = torch.split(masks, idx, dim=0)\n", + "\n", + "if x_cat is not None:\n", + " x_cat_train, x_cat_val = torch.split(x_cat, idx, dim=0)\n", + "else:\n", + " x_cat_train, x_cat_val = None, None\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Runfield πŸ›«" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "device = \"cuda\"\n", + "batch_size = 16192\n", + "epochs = 100\n", + "\n", + "d_token = 192\n", + "n_blocks = 3\n", + "attention_dropout = 0.2\n", + "ffn_dropout = 0.1\n", + "residual_dropout = 0.0\n", + "attention_heads = 8\n", + "\n", + "\n", + "reduction = \"mean\"\n", + "\n", + "dl_params = {\n", + " \"batch_size\": batch_size,\n", + " \"shuffle\": False,\n", + " \"device\": \"cuda\",\n", + "}\n", + "\n", + "feature_tokenizer_kwargs = {\n", + " \"num_continous\": len(X_train.columns.tolist()),\n", + " \"cat_cardinalities\": (),\n", + " \"d_token\": d_token,\n", + "}\n", + "\n", + "dl_params = {\n", + " \"batch_size\": batch_size, # dataprallel splits batches across devices\n", + " \"shuffle\": False,\n", + " \"device\": device,\n", + "}\n", + "\n", + "transformer_kwargs = {\n", + " \"d_token\": d_token,\n", + " \"n_blocks\": n_blocks,\n", + " \"attention_n_heads\": attention_heads,\n", + " \"attention_initialization\": \"kaiming\",\n", + " \"ffn_activation\": ReGLU,\n", + " \"attention_normalization\": nn.LayerNorm,\n", + " \"ffn_normalization\": nn.LayerNorm,\n", + " \"ffn_dropout\": ffn_dropout,\n", + " # fix at 4/3, as activation (see search space B in\n", + " # https://arxiv.org/pdf/2106.11959v2.pdf)\n", + " # is static with ReGLU / GeGLU\n", + " \"ffn_d_hidden\": int(d_token * (4 / 3)),\n", + " \"attention_dropout\": attention_dropout,\n", + " \"residual_dropout\": residual_dropout, # see search space (B)\n", + " \"prenormalization\": True,\n", + " \"first_prenormalization\": False,\n", + " \"last_layer_query_idx\": None,\n", + " \"n_tokens\": None,\n", + " \"kv_compression_ratio\": None,\n", + " \"kv_compression_sharing\": None,\n", + " \"head_activation\": nn.GELU, # nn.ReLU\n", + " \"head_normalization\": nn.LayerNorm,\n", + " \"d_out\": 1, # fix at 1, due to binary classification\n", + "}\n", + "\n", + "head_kwargs = {\"d_in\": d_token, \"d_hidden\": 32}\n", + "\n", + "optim_params = {\"lr\": 1e-4, \"weight_decay\": 0.00001}\n", + "\n", + "module_params = {\n", + " \"transformer\": Transformer(**transformer_kwargs), \n", + " \"feature_tokenizer\": FeatureTokenizer(**feature_tokenizer_kwargs), # noqa: E501\n", + " \"cat_features\": None,\n", + " \"cat_cardinalities\": [],\n", + "}\n", + "\n", + "clf = FTTransformer(**module_params)\n", + "criterion = nn.BCEWithLogitsLoss()\n", + "\n", + "# swap target head with classification head, and restore later\n", + "target_head = clf.transformer.head\n", + "clf_head = CLSHead(**head_kwargs)\n", + "clf.transformer.head = clf_head\n", + "\n", + "clf.to(device)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "train_loader = TabDataLoader(\n", + " x_cat_train,\n", + " x_cont_train,\n", + " masks_train, \n", + " **dl_params\n", + ")\n", + "\n", + "val_loader = TabDataLoader(\n", + " x_cat_val,\n", + " x_cont_val,\n", + " masks_val, \n", + " **dl_params\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "optimizer = optim.AdamW(clf.parameters(),\n", + " lr=optim_params[\"lr\"],\n", + " weight_decay=optim_params[\"weight_decay\"],\n", + ")\n", + "\n", + "max_iters = epochs * len(train_loader)\n", + "# saw recommendation of 5 - 10 % of total training budget or 100 to 500 steps\n", + "warmup = int(0.05 * max_iters)\n", + "print(f\"warmup steps: {warmup}\")\n", + "print(max_iters)\n", + "\n", + "scheduler = CosineWarmupScheduler(optimizer=optimizer, warmup=warmup, max_iters=max_iters)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def checkpoint(model):\n", + " \n", + " # remove old files\n", + " for fn in glob.glob(f\"checkpoints/{run.id}*\"):\n", + " os.remove(fn) \n", + " \n", + " # create_dir\n", + " dir_checkpoints = \"checkpoints/\"\n", + " os.makedirs(dir_checkpoints, exist_ok = True) \n", + " \n", + " # save new file\n", + " print(\"saving new checkpoints.\")\n", + " torch.save(model.state_dict(), os.path.join(dir_checkpoints,f\"{run.id}*\"))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# half precision, see https://pytorch.org/docs/stable/amp.html\n", + "scaler = torch.cuda.amp.GradScaler()\n", + "\n", + "early_stopping = EarlyStopping(patience=15)\n", + "\n", + "step = 0\n", + "best_accuracy = -1\n", + "best_step = -1\n", + "\n", + "for epoch in tqdm(range(epochs)):\n", + "\n", + " # perform training\n", + " loss_in_epoch_train = 0\n", + "\n", + " batch = 0\n", + " \n", + " for x_cat, x_cont, masks in train_loader:\n", + " \n", + " clf.train()\n", + " optimizer.zero_grad()\n", + " \n", + " with torch.autocast(device_type='cuda', dtype=torch.float16):\n", + " logits = clf(x_cat, x_cont)\n", + " train_loss = criterion(logits, masks.float())\n", + "\n", + " scaler.scale(train_loss).backward()\n", + " scaler.step(optimizer)\n", + " scaler.update()\n", + " \n", + " scheduler.step()\n", + " \n", + " # add the mini-batch training loss to epoch loss\n", + " loss_in_epoch_train += train_loss.item()\n", + " \n", + " wandb.log({\"train_loss_step\": train_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", + "\n", + " batch += 1\n", + " step +=1\n", + "\n", + " clf.eval()\n", + " loss_in_epoch_val = 0.0\n", + " correct = 0\n", + " \n", + " with torch.no_grad():\n", + " for x_cat, x_cont, masks in val_loader:\n", + "\n", + " # for my implementation\n", + " logits = clf(x_cat, x_cont)\n", + " val_loss = criterion(logits, masks.float())\n", + " \n", + "\n", + " # hard_predictions = torch.zeros_like(logits, dtype=torch.long)\n", + " # hard_predictions[logits > 0] = 1\n", + " # correct += (hard_predictions.bool() == masks).sum() / hard_predictions.shape[0]\n", + "\n", + " loss_in_epoch_val += val_loss.item()\n", + " wandb.log({\"val_loss_step\": val_loss.item(), \"epoch\": epoch, \"batch\": batch})\n", + " \n", + " batch +=1 \n", + "\n", + " # correct / (rows * columns)\n", + " # val_accuracy = correct / (X_train.shape[0] * X_train.shape[1]) \n", + " \n", + " # loss average over all batches\n", + " train_loss = loss_in_epoch_train / len(train_loader)\n", + " val_loss = loss_in_epoch_val / len(val_loader)\n", + " \n", + " print(f\"train loss: {train_loss}\")\n", + " print(f\"val loss: {val_loss}\")\n", + " \n", + " # correct samples / no samples\n", + " # val_accuracy = correct / len(X_val)\n", + " # if best_accuracy < val_accuracy:\n", + " # checkpoint(clf, f\"checkpoints/{run.id}-{step}.ptx\")\n", + " # best_accuracy = val_accuracy\n", + " # best_step = step\n", + " \n", + " \n", + " wandb.log({\"train_loss\": train_loss, 'epoch': epoch})" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Prepare for FinetuningπŸ•°οΈ" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# swap heads and save model\n", + "clf.transformer.head = target_head\n", + "checkpoint(clf)\n", + "\n", + "# FIXME: Think about which weights to freeze and which to update\n", + "# https://ai.stackexchange.com/questions/23884/why-arent-the-bert-layers-frozen-during-fine-tuning-tasks" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/6.0c-mb-results-universal.ipynb b/notebooks/6.0c-mb-results-universal.ipynb index 869a7644..f007e6d7 100644 --- a/notebooks/6.0c-mb-results-universal.ipynb +++ b/notebooks/6.0c-mb-results-universal.ipynb @@ -1,948 +1,948 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "7WXF7w4VyVgG", - "tags": [] - }, - "outputs": [], - "source": [ - "import os\n", - "import random\n", - "import sys\n", - "from pathlib import Path\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "from sklearn.metrics import accuracy_score\n", - "\n", - "sys.path.append(\"..\")\n", - "import warnings\n", - "\n", - "import wandb\n", - "from otc.metrics.metrics import effective_spread\n", - "from scipy.stats import wilcoxon\n", - "from tqdm.auto import tqdm\n", - "\n", - "from statsmodels.stats.contingency_tables import mcnemar" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# set here globally\n", - "EXCHANGE = \"cboe\" # \"ise\"\n", - "MODELS = [\"gbm\",\"fttransformer\"] # \"classical\", \"fttransformer\", \"gbm\"\n", - "SUBSET = \"test\" # \"all\"\n", - "STRATEGY = \"transfer\" # \"supervised\" \n", - "\n", - "RETRAIN = False" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "KEY = f\"{EXCHANGE}_{STRATEGY}_{SUBSET}\"\n", - "DATASET = f\"fbv/thesis/{EXCHANGE}_{STRATEGY}_raw:latest\"\n", - "\n", - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", - "\n", - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "# load unscaled data\n", - "artifact = run.use_artifact(DATASET) \n", - "data_dir = artifact.download()\n", - "\n", - "# load results\n", - "result_dirs = []\n", - "for model in MODELS:\n", - " # retraining is only possible for gbm\n", - " if model == \"gbm\" and RETRAIN:\n", - " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}_retrain:latest\"\n", - " else:\n", - " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}:latest\"\n", - " artifact = run.use_artifact(results) \n", - " result_dir = artifact.download()\n", - " result_dirs.append(result_dir)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "WmXtH-PEqyQE", - "tags": [] - }, - "outputs": [], - "source": [ - "# p. 35-38\n", - "COLUMNS = [\n", - " \"buy_sell\",\n", - " \"EXPIRATION\",\n", - " \"QUOTE_DATETIME\",\n", - " \"TRADE_SIZE\",\n", - " \"TRADE_PRICE\",\n", - " \"ask_ex\",\n", - " \"ask_size_ex\",\n", - " \"bid_ex\",\n", - " \"bid_size_ex\",\n", - " \"myn\",\n", - " \"OPTION_TYPE\",\n", - " \"issue_type\",\n", - "]\n", - "\n", - "\n", - "if SUBSET == \"all\":\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " val = pd.read_parquet(\n", - " Path(data_dir, \"val_set\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " eval_data = pd.concat([train, val, test])\n", - " del train, val, test\n", - "\n", - "elif SUBSET == \"test\":\n", - " eval_data = pd.read_parquet(\n", - " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - "\n", - "\n", - "results = []\n", - "for i, model in tqdm(enumerate(MODELS)):\n", - " result = pd.read_parquet(Path(result_dirs[i], \"results\"), engine=\"fastparquet\")\n", - " result.columns = pd.MultiIndex.from_product([[model], result.columns])\n", - " results.append(result)\n", - "\n", - "results_data = pd.concat(results, axis=1, names=MODELS)\n", - "\n", - "assert len(eval_data) == len(results_data)\n", - "\n", - "X_print = eval_data\n", - "\n", - "del results\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# FIXME: select a subset of results for testing.\n", - "results_data = results_data[\n", - " [\n", - " # (\"fttransformer\", \"fttransformer(classical)\"),\n", - " # (\"fttransformer\", \"fttransformer(classical-size)\"),\n", - " # (\"fttransformer\", \"fttransformer(ml)\"), \n", - " (\"fttransformer\", \"fttransformer(semi-classical)\"),\n", - " (\"fttransformer\", \"fttransformer(semi-classical-size)\"),\n", - " (\"fttransformer\", \"fttransformer(semi-ml)\"), \n", - " # (\"gbm\", \"gbm(classical)\"),\n", - " # (\"gbm\", \"gbm(classical-size)\"),\n", - " # (\"gbm\", \"gbm(ml)\"),\n", - " # # (\"gbm\", \"gbm(classical-retraining)\"),\n", - " # # (\"gbm\", \"gbm(classical-size-retraining)\"),\n", - " # # (\"gbm\", \"gbm(ml-retraining)\"),\n", - " (\"gbm\", \"gbm(semi-classical)\"),\n", - " (\"gbm\",'gbm(semi-classical-size)'),\n", - " (\"gbm\",'gbm(semi-ml)'),\n", - "\n", - "# # viz\n", - " # (\"classical\", \"tick(all)\"),\n", - " # (\"classical\", \"quote(best)\"),\n", - " # (\"classical\", \"quote(ex)\"),\n", - " # (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", - " # (\n", - " # \"classical\",\n", - " # \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", - " # ),\n", - " # (\"classical\", \"depth(ex)\"),\n", - " # (\"classical\", \"depth(best)\"),\n", - " # (\"classical\", \"trade_size(ex)\"),\n", - "\n", - "# # batch 1 / detailled analysis\n", - "# (\"classical\", \"tick(ex)\"),\n", - "# (\"classical\", \"rev_tick(ex)\"),\n", - "# (\"classical\", \"quote(ex)\"),\n", - "# (\"classical\", \"lr(ex)\"),\n", - "# (\"classical\", \"rev_lr(ex)\"),\n", - "# (\"classical\", \"emo(ex)\"),\n", - "# (\"classical\", \"rev_emo(ex)\"),\n", - " \n", - "# # batch 2\n", - "# (\"classical\", \"clnv(ex)\"),\n", - "# (\"classical\", \"rev_clnv(ex)\"),\n", - "# (\"classical\", \"tick(all)\"),\n", - "# (\"classical\", \"rev_tick(all)\"),\n", - "# (\"classical\", \"quote(best)\"),\n", - "# (\"classical\", \"lr(best)\"),\n", - "# (\"classical\", \"rev_lr(best)\"),\n", - " \n", - "# # batch 3\n", - "# (\"classical\", \"emo(best)\"),\n", - "# (\"classical\", \"rev_emo(best)\"),\n", - "# (\"classical\", \"clnv(best)\"),\n", - "# (\"classical\", \"rev_clnv(best)\"), \n", - " # (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", - " # (\n", - " # \"classical\",\n", - " # \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", - " # ),\n", - " \n", - " # detailed analysis\n", - " \n", - " ]\n", - "]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "LUT = {\n", - " \"Trade_Size(ex)->Quote(Best)->Depth(Best)->Quote(Ex)->Depth(Ex)->Rev_Tick(All)\": \"\\gls{GBM}\",\n", - " \"(Ex)\": \" (Ex)\",\n", - " \"(Best)\": \" (Best)\",\n", - " \"(Classical)\": \" (Classical)\",\n", - " \"(Classical-Size)\": \" (Classical, Size)\",\n", - " \"Rev_\": \"Rev. \",\n", - " \"Trade_Size\": \"Trade Size\",\n", - " \"Depth\": \"Depth\",\n", - " \"->\": \" $\\\\to$ \",\n", - " \"Lr\": \"\\gls{LR}\",\n", - " \"Emo\": \"\\gls{EMO}\",\n", - " \"Clnv\": \"\\gls{CLNV}\",\n", - " \"OPTION_TYPE\": \"Option Type\",\n", - " \"_\": \"$\\_\",\n", - " \"Gbm\": \"\\gls{GBM}\",\n", - "}\n", - "\n", - "LUT_INDEX = {\n", - " \"OPTION_TYPE\": \"Option Type\",\n", - " \"issue_type\": \"Security Type\",\n", - " \"TRADE_SIZE_binned\": \"Trade Size\",\n", - " \"year_binned\": \"Year\",\n", - " \"ttm_binned\": \"Time to Maturity\",\n", - " \"myn_binned\": \"Moneyness\",\n", - " \"prox_q_binned\": \"Location to Quote\",\n", - " \"all\": \"All trades\",\n", - "}\n", - "\n", - "\n", - "def cell_str(x):\n", - " x = x.title()\n", - " for orig, sub in LUT.items():\n", - " x = x.replace(orig, sub)\n", - " # title-case everything\n", - " return x\n", - "\n", - "\n", - "def highlight_max(s, props=\"\"):\n", - " return np.where(s == np.nanmax(s.values), props, \"\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "def set_tex_style(styler, caption, label, bold_axis=1):\n", - " res = styler.set_caption(caption)\n", - "\n", - " res = (\n", - " res.apply(highlight_max, props=\"font-weight:bold;\", axis=bold_axis)\n", - " .format(precision=4, decimal=\".\", thousands=\",\", escape=False, hyperlinks=None)\n", - " .format_index(cell_str, axis=0)\n", - " .format_index(cell_str, axis=1)\n", - " .to_latex(\n", - " f\"{label}.tex\",\n", - " siunitx=True,\n", - " position_float=\"centering\",\n", - " hrules=True,\n", - " clines=\"skip-last;data\",\n", - " label=\"tab:\" + label,\n", - " caption=caption,\n", - " convert_css=True,\n", - " )\n", - " )\n", - " return res\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "classifiers = results_data.columns.tolist()\n", - "criterions = list(LUT_INDEX)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "classifiers" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Unclassified by method" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "unclassified = (\n", - " (results_data[results_data == 0.0].count(axis=0) / len(results_data.index))\n", - " # .sort_values(ascending=False)\n", - " .to_frame(name=\"unclassified\")\n", - ")\n", - "\n", - "# coverage in %\n", - "unclassified = 100 - (unclassified * 100)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "unclassified.style.pipe(\n", - " set_tex_style,\n", - " caption=(f\"{KEY}-unclassified-long\", \"{key}-unclassified-short\"),\n", - " label=f\"{KEY.lower()}-unclassfied\",\n", - " bold_axis=0,\n", - ")\n", - "unclassified\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Fill in unclassified\n", - "\n", - "Unclassified are `0`." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "rng = np.random.default_rng(42)\n", - "\n", - "# replace 0 -> nan -> [-1,1]\n", - "results_data.replace(0, np.nan, inplace=True)\n", - "# assume same filler for every column\n", - "filler = pd.Series(\n", - " rng.choice(a=[-1, 1], size=results_data.shape[0]),\n", - " index=results_data.index,\n", - " # columns=results_data.columns,\n", - ")\n", - "\n", - "# do column-wise as we run out of memory otherwise\n", - "for classifier in tqdm(classifiers):\n", - " results_data[classifier].fillna(filler, inplace=True)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### McNemar's Test" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "X_print = pd.concat([X_print, results_data], axis=1)\n", - "Y = X_print[[*results_data.columns.tolist(), \"buy_sell\"]]\n", - "\n", - "import statsmodels\n", - "from statsmodels.stats.contingency_tables import mcnemar\n", - "\n", - "results = []\n", - "combinations = [(('gbm', 'gbm(semi-classical)'), ('fttransformer', 'fttransformer(semi-classical)')),\n", - " (('gbm', 'gbm(semi-classical-size)'), ('fttransformer', 'fttransformer(semi-classical-size)')),\n", - " (('gbm', 'gbm(semi-ml)'), ('fttransformer', 'fttransformer(semi-ml)'))]\n", - "significance = 0.05\n", - "\n", - "def get_contingency_table(Y, ground_truth, model_1, model_2):\n", - "\n", - " Y_ = Y[[ground_truth, model_1, model_2]].copy().astype(int)\n", - "\n", - " c_0_0 = np.where((Y_[model_1] == Y_[ground_truth]) & (Y_[model_2] == Y_[ground_truth]), 1, 0).sum()\n", - " c_0_1 = np.where((Y_[model_1] == Y_[ground_truth]) & (Y_[model_2] != Y_[ground_truth]), 1, 0).sum()\n", - " c_1_0 = np.where((Y_[model_1] != Y_[ground_truth]) & (Y_[model_2] == Y_[ground_truth]), 1, 0).sum()\n", - " c_1_1 = np.where((Y_[model_1] != Y_[ground_truth]) & (Y_[model_2] != Y_[ground_truth]), 1, 0).sum()\n", - " \n", - " # [both right, gbm right/transformer wrong, gbm wrong/transformer right, both wrong]\n", - " contingency_table = [[c_0_0, c_0_1],[c_1_0, c_1_1]]\n", - "\n", - " return np.array(contingency_table)\n", - "\n", - " \n", - "for combination in tqdm(combinations):\n", - " contingency_table = get_contingency_table(Y, 'buy_sell', combination[0], combination[1])\n", - " test = mcnemar(contingency_table, exact=False, correction=True)\n", - " \n", - " results.append({\"contingency_table\": contingency_table, \"model_1\": combination[0], \"model_2\": combination[1], \"statistic\": test.statistic, \"p-value\": test.pvalue, \"significant\": test.pvalue < significance})\n", - " \n", - "pd.DataFrame(results).to_csv(f\"../models/{EXCHANGE}-mcnemar.csv\")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "h3vzAVSc_DfD" - }, - "source": [ - "### Robustness Checks" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "3evMG-KVA2eX" - }, - "outputs": [], - "source": [ - "# %%script false --no-raise-error\n", - "# prepare columns for printing\n", - "X_print[\"ttm\"] = (\n", - " X_print[\"EXPIRATION\"].dt.to_period(\"M\")\n", - " - X_print[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", - ").apply(lambda x: x.n)\n", - "\n", - "X_print[\"year\"] = X_print[\"QUOTE_DATETIME\"].dt.year\n", - "\n", - "bins_tradesize = [-1, 1, 3, 5, 11, np.inf]\n", - "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", - "X_print[\"TRADE_SIZE_binned\"] = pd.cut(\n", - " X_print[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", - ")\n", - "\n", - "# p. 38\n", - "bins_years = [2004, 2007, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]\n", - "year_labels = [\n", - " \"2005-2007\",\n", - " \"2008-2010\",\n", - " \"2011\",\n", - " \"2012\",\n", - " \"2013\",\n", - " \"2014\",\n", - " \"2015\",\n", - " \"2016\",\n", - " \"2017\",\n", - "]\n", - "X_print[\"year_binned\"] = pd.cut(X_print[\"year\"], bins_years, labels=year_labels)\n", - "\n", - "# p. 37\n", - "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", - "ttm_labels = [\n", - " \"<= 1\",\n", - " \"(1-2]\",\n", - " \"(2-3]\",\n", - " \"(3-6]\",\n", - " \"(6-12]\",\n", - " \"> 12\",\n", - "]\n", - "X_print[\"ttm_binned\"] = pd.cut(X_print[\"ttm\"], bins_ttm, labels=ttm_labels)\n", - "\n", - "# Security type\n", - "# see 3.0a-mb-explanatory-data-analysis.ipynb\n", - "X_print[\"issue_type\"] = X_print[\"issue_type\"].map(\n", - " {\n", - " \"0\": \"Stock option\",\n", - " \"A\": \"Index option\",\n", - " \"7\": \"Others\",\n", - " \"F\": \"Others\",\n", - " \"%\": \"Others\",\n", - " \" \": \"Others\",\n", - " }\n", - ")\n", - "\n", - "# Moneyness p. 38\n", - "bins_myn = [-1, 0.7, 0.9, 1.1, 1.3, np.inf]\n", - "myn_labels = [\n", - " \"<= 0.7\",\n", - " \"(0.7-0.9]\",\n", - " \"(0.9-1.1]\",\n", - " \"(1.1-1.3]\",\n", - " \"> 1.3\",\n", - "]\n", - "X_print[\"myn_binned\"] = pd.cut(X_print[\"myn\"], bins_myn, labels=myn_labels)\n", - "\n", - "# mid p. 31 + extra category for unknowns\n", - "ask = X_print[\"ask_ex\"]\n", - "bid = X_print[\"bid_ex\"]\n", - "trade_price = X_print[\"TRADE_PRICE\"]\n", - "\n", - "# require ask >= bid\n", - "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", - "\n", - "prox_quotes = np.where(\n", - " trade_price == mid,\n", - " 0, # at mid\n", - " np.where(\n", - " (bid < trade_price) & (trade_price < ask),\n", - " 1, # inside\n", - " np.where(\n", - " (trade_price == bid) | (ask == trade_price),\n", - " 2, # at quotes\n", - " np.where((trade_price < bid) | (ask < trade_price), 3, 4),\n", - " ),\n", - " ),\n", - ") # outside + unclassifiable\n", - "\n", - "bins_prox = [-np.inf, 0, 1, 2, 3, 4]\n", - "prox_labels = [\n", - " \"at mid\",\n", - " \"inside\",\n", - " \"at quotes\",\n", - " \"outside\",\n", - " \"unknown\",\n", - "]\n", - "\n", - "X_print[\"prox_q_binned\"] = pd.cut(prox_quotes, bins_prox, labels=prox_labels)\n", - "X_print[\"mid\"] = mid\n", - "\n", - "# clean up empty buckets, as it causes empty grouping in result set generation\n", - "X_print[\"year_binned\"] = X_print[\"year_binned\"].cat.remove_unused_categories()\n", - "X_print[\"myn_binned\"] = X_print[\"myn_binned\"].cat.remove_unused_categories()\n", - "X_print[\"ttm_binned\"] = X_print[\"ttm_binned\"].cat.remove_unused_categories()\n", - "X_print[\"prox_q_binned\"] = X_print[\"prox_q_binned\"].cat.remove_unused_categories()\n", - "\n", - "X_print[\"all\"] = \"all\"\n", - "\n", - "X_print.drop(\n", - " columns=[\n", - " \"EXPIRATION\",\n", - " \"QUOTE_DATETIME\",\n", - " # \"TRADE_SIZE\",\n", - " \"ttm\",\n", - " \"myn\",\n", - " \"year\",\n", - " ],\n", - " inplace=True,\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X_print = pd.concat([X_print, results_data], axis=1)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X_print.head().T" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Accuracy Calculation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# FIXME: Find better approach\n", - "warnings.filterwarnings(\"ignore\", category=np.VisibleDeprecationWarning)\n", - "\n", - "result_dfs = []\n", - "\n", - "for criterion in tqdm(criterions):\n", - " results = []\n", - " for classifier in classifiers:\n", - " res = (\n", - " X_print.groupby([criterion])[[\"buy_sell\", classifier]]\n", - " .apply(\n", - " lambda x: accuracy_score(x[\"buy_sell\"].astype(\"int8\"), x[classifier])\n", - " )\n", - " .mul(100)\n", - " .rename(classifier)\n", - " )\n", - " # acc_tot = accuracy_score(\n", - " # X_print[\"buy_sell\"].astype(\"int8\"), X_print[classifier]\n", - " # )\n", - "\n", - " # res.loc[\"all\"] = acc_tot * 100\n", - "\n", - " res.index.name = LUT_INDEX.get(criterion)\n", - " results.append(res)\n", - "\n", - " # save aggregated results\n", - " result_df = pd.concat(results, axis=1).T\n", - " # result_df.style.pipe(\n", - " # set_tex_style,\n", - " # caption=(f\"long-tbd\", \"short-tbd\"),\n", - " # label=f\"{KEY.lower()}-{criterion.lower()}\",\n", - " # )\n", - "\n", - " # store all result sets for later use\n", - " result_dfs.append(result_df)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "%%script false --no-raise-error\n", - "keys = [\"set\", \"all\"]\n", - "master = pd.concat(result_dfs, axis=1, keys=keys).T" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "master = pd.concat(result_dfs, axis=1, keys=list(LUT_INDEX.values())).T" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "master.style.pipe(\n", - " set_tex_style,\n", - " caption=(\"master-long\", \"master-short\"),\n", - " label=f\"{KEY}-master\",\n", - " bold_axis=0,\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "master" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Effective Spread πŸ’΄" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# mid p. 31 + extra category for unknowns\n", - "ask = X_print[\"ask_ex\"]\n", - "bid = X_print[\"bid_ex\"]\n", - "trade_price = X_print[\"TRADE_PRICE\"]\n", - "\n", - "# require ask >= bid\n", - "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", - "\n", - "results = []\n", - "\n", - "# calculate true rel effective spread but not aggregated, convert to %\n", - "es_true = effective_spread(X_print[\"buy_sell\"], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", - "nom_true = np.nanmean(es_true)\n", - "\n", - "eps_true = np.empty(es_true.shape)\n", - "np.divide(es_true, mid, out=eps_true, where=mid != 0)\n", - "rel_true = np.nanmean(eps_true)\n", - "\n", - "\n", - "for classifier in tqdm(classifiers):\n", - "\n", - " # calculate pred rel effective spread but not aggregated convert to %\n", - " es_pred = effective_spread(X_print[classifier], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", - " \n", - " eps_pred = np.empty(es_pred.shape)\n", - " np.divide(es_pred, mid, out=eps_pred, where=mid != 0)\n", - "\n", - " wilcoxon_res = wilcoxon(eps_pred, eps_true, nan_policy=\"omit\", zero_method=\"zsplit\")\n", - "\n", - " res = pd.Series(\n", - " {\n", - " \"nom_pred\": np.nanmean(es_pred),\n", - " \"rel_pred\": np.nanmean(eps_pred),\n", - " \"statistic\":wilcoxon_res.statistic,\n", - " \"pvalue\":wilcoxon_res.pvalue,\n", - " }, name=classifier\n", - " )\n", - " results.append(res)\n", - "\n", - "true_eff = pd.Series({\"nom_pred\":nom_true, \"rel_pred\": rel_true, \"statistic\":np.NaN, \"pvalue\":np.NaN}, name=\"true_eff\")\n", - "\n", - "results.append(true_eff)\n", - "\n", - "results = pd.concat(results, axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "results.T.style.format(\"{:.3f}\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results.T.style.to_latex(\n", - " f\"../reports/Content/{KEY}-eff-spread.tex\",\n", - " siunitx=True,\n", - " position_float=\"centering\",\n", - " hrules=True,\n", - " clines=\"skip-last;data\",\n", - " label=f\"tab:eff-{KEY}\",\n", - " caption=(f\"long-eff-{KEY}\", f\"short-eff-{KEY}\"),\n", - " convert_css=True,\n", - ")\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Diffs πŸ”„οΈ" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "master.columns.tolist()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# classical baselines\n", - "view = [(\"fttransformer\", \"fttransformer(semi-classical)\"), (\"fttransformer\", \"fttransformer(semi-classical-size)\"), (\"fttransformer\", \"fttransformer(semi-ml)\")]\n", - "\n", - "base = master[\n", - " [\n", - " (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", - " (\n", - " \"classical\",\n", - " \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", - " ),\n", - " (\n", - " \"classical\",\n", - " \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", - " ),\n", - " ]\n", - "]\n", - "\n", - "# my ml models\n", - "revised = master[view]\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def combine_results(revised: pd.DataFrame, base: pd.DataFrame) -> pd.DataFrame:\n", - " \"\"\"\n", - " Generate print layout like in Grauer et al.\n", - "\n", - " https://tex.stackexchange.com/questions/430283/table-with-numbers-in-parentheses-in-siunitx/430290#430290\n", - "\n", - " # see p. https://texdoc.org/serve/siunitx/0\n", - " \"\"\"\n", - " # first, second layer of colum index\n", - " c_1 = revised.columns.get_level_values(1)\n", - " c_2 = [\"nom\"]\n", - " midx = pd.MultiIndex.from_product([c_1, c_2])\n", - "\n", - " # copy data from revised add as (column, \"nom\")\n", - " combo = pd.DataFrame(revised.values, index=revised.index, columns=midx)\n", - "\n", - " for i, mul_col in enumerate(combo.columns):\n", - "\n", - " combo[(mul_col[0], \"pm\")] = (combo[mul_col] - base.iloc[:, i]).round(2)\n", - " combo.sort_index(axis=1, inplace=True)\n", - "\n", - " return combo\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "diff = combine_results(revised, base)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "diff.style.to_latex(\n", - " f\"../reports/Content/diff-{KEY}.tex\",\n", - " siunitx=True,\n", - " position_float=\"centering\",\n", - " hrules=True,\n", - " clines=\"skip-last;data\",\n", - " label=f\"tab:diff-{KEY}\",\n", - " caption=(f\"long-diff-{KEY}\", f\"short-diff-{KEY}\"),\n", - " convert_css=True,\n", - ")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "diff\n" - ] - } - ], - "metadata": { - "colab": { - "include_colab_link": true, - "machine_shape": "hm", - "name": "Untitled2.ipynb", - "provenance": [] - }, - "gpuClass": "premium", - "kernelspec": { - "display_name": "myenv", - "language": "python", - "name": "myenv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - }, - "vscode": { - "interpreter": { - "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "7WXF7w4VyVgG", + "tags": [] + }, + "outputs": [], + "source": [ + "import os\n", + "import random\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "sys.path.append(\"..\")\n", + "import warnings\n", + "\n", + "import wandb\n", + "from otc.metrics.metrics import effective_spread\n", + "from scipy.stats import wilcoxon\n", + "from tqdm.auto import tqdm\n", + "\n", + "from statsmodels.stats.contingency_tables import mcnemar" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# set here globally\n", + "EXCHANGE = \"cboe\" # \"ise\"\n", + "MODELS = [\"gbm\",\"fttransformer\"] # \"classical\", \"fttransformer\", \"gbm\"\n", + "SUBSET = \"test\" # \"all\"\n", + "STRATEGY = \"transfer\" # \"supervised\" \n", + "\n", + "RETRAIN = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "KEY = f\"{EXCHANGE}_{STRATEGY}_{SUBSET}\"\n", + "DATASET = f\"fbv/thesis/{EXCHANGE}_{STRATEGY}_raw:latest\"\n", + "\n", + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", + "\n", + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "# load unscaled data\n", + "artifact = run.use_artifact(DATASET) \n", + "data_dir = artifact.download()\n", + "\n", + "# load results\n", + "result_dirs = []\n", + "for model in MODELS:\n", + " # retraining is only possible for gbm\n", + " if model == \"gbm\" and RETRAIN:\n", + " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}_retrain:latest\"\n", + " else:\n", + " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}:latest\"\n", + " artifact = run.use_artifact(results) \n", + " result_dir = artifact.download()\n", + " result_dirs.append(result_dir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "WmXtH-PEqyQE", + "tags": [] + }, + "outputs": [], + "source": [ + "# p. 35-38\n", + "COLUMNS = [\n", + " \"buy_sell\",\n", + " \"EXPIRATION\",\n", + " \"QUOTE_DATETIME\",\n", + " \"TRADE_SIZE\",\n", + " \"TRADE_PRICE\",\n", + " \"ask_ex\",\n", + " \"ask_size_ex\",\n", + " \"bid_ex\",\n", + " \"bid_size_ex\",\n", + " \"myn\",\n", + " \"OPTION_TYPE\",\n", + " \"issue_type\",\n", + "]\n", + "\n", + "\n", + "if SUBSET == \"all\":\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " val = pd.read_parquet(\n", + " Path(data_dir, \"val_set\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " eval_data = pd.concat([train, val, test])\n", + " del train, val, test\n", + "\n", + "elif SUBSET == \"test\":\n", + " eval_data = pd.read_parquet(\n", + " Path(data_dir, \"test_set\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + "\n", + "\n", + "results = []\n", + "for i, model in tqdm(enumerate(MODELS)):\n", + " result = pd.read_parquet(Path(result_dirs[i], \"results\"), engine=\"fastparquet\")\n", + " result.columns = pd.MultiIndex.from_product([[model], result.columns])\n", + " results.append(result)\n", + "\n", + "results_data = pd.concat(results, axis=1, names=MODELS)\n", + "\n", + "assert len(eval_data) == len(results_data)\n", + "\n", + "X_print = eval_data\n", + "\n", + "del results\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# FIXME: select a subset of results for testing.\n", + "results_data = results_data[\n", + " [\n", + " # (\"fttransformer\", \"fttransformer(classical)\"),\n", + " # (\"fttransformer\", \"fttransformer(classical-size)\"),\n", + " # (\"fttransformer\", \"fttransformer(ml)\"), \n", + " (\"fttransformer\", \"fttransformer(semi-classical)\"),\n", + " (\"fttransformer\", \"fttransformer(semi-classical-size)\"),\n", + " (\"fttransformer\", \"fttransformer(semi-ml)\"), \n", + " # (\"gbm\", \"gbm(classical)\"),\n", + " # (\"gbm\", \"gbm(classical-size)\"),\n", + " # (\"gbm\", \"gbm(ml)\"),\n", + " # # (\"gbm\", \"gbm(classical-retraining)\"),\n", + " # # (\"gbm\", \"gbm(classical-size-retraining)\"),\n", + " # # (\"gbm\", \"gbm(ml-retraining)\"),\n", + " (\"gbm\", \"gbm(semi-classical)\"),\n", + " (\"gbm\",'gbm(semi-classical-size)'),\n", + " (\"gbm\",'gbm(semi-ml)'),\n", + "\n", + "# # viz\n", + " # (\"classical\", \"tick(all)\"),\n", + " # (\"classical\", \"quote(best)\"),\n", + " # (\"classical\", \"quote(ex)\"),\n", + " # (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", + " # (\n", + " # \"classical\",\n", + " # \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", + " # ),\n", + " # (\"classical\", \"depth(ex)\"),\n", + " # (\"classical\", \"depth(best)\"),\n", + " # (\"classical\", \"trade_size(ex)\"),\n", + "\n", + "# # batch 1 / detailled analysis\n", + "# (\"classical\", \"tick(ex)\"),\n", + "# (\"classical\", \"rev_tick(ex)\"),\n", + "# (\"classical\", \"quote(ex)\"),\n", + "# (\"classical\", \"lr(ex)\"),\n", + "# (\"classical\", \"rev_lr(ex)\"),\n", + "# (\"classical\", \"emo(ex)\"),\n", + "# (\"classical\", \"rev_emo(ex)\"),\n", + " \n", + "# # batch 2\n", + "# (\"classical\", \"clnv(ex)\"),\n", + "# (\"classical\", \"rev_clnv(ex)\"),\n", + "# (\"classical\", \"tick(all)\"),\n", + "# (\"classical\", \"rev_tick(all)\"),\n", + "# (\"classical\", \"quote(best)\"),\n", + "# (\"classical\", \"lr(best)\"),\n", + "# (\"classical\", \"rev_lr(best)\"),\n", + " \n", + "# # batch 3\n", + "# (\"classical\", \"emo(best)\"),\n", + "# (\"classical\", \"rev_emo(best)\"),\n", + "# (\"classical\", \"clnv(best)\"),\n", + "# (\"classical\", \"rev_clnv(best)\"), \n", + " # (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", + " # (\n", + " # \"classical\",\n", + " # \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", + " # ),\n", + " \n", + " # detailed analysis\n", + " \n", + " ]\n", + "]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "LUT = {\n", + " \"Trade_Size(ex)->Quote(Best)->Depth(Best)->Quote(Ex)->Depth(Ex)->Rev_Tick(All)\": \"\\gls{GBM}\",\n", + " \"(Ex)\": \" (Ex)\",\n", + " \"(Best)\": \" (Best)\",\n", + " \"(Classical)\": \" (Classical)\",\n", + " \"(Classical-Size)\": \" (Classical, Size)\",\n", + " \"Rev_\": \"Rev. \",\n", + " \"Trade_Size\": \"Trade Size\",\n", + " \"Depth\": \"Depth\",\n", + " \"->\": \" $\\\\to$ \",\n", + " \"Lr\": \"\\gls{LR}\",\n", + " \"Emo\": \"\\gls{EMO}\",\n", + " \"Clnv\": \"\\gls{CLNV}\",\n", + " \"OPTION_TYPE\": \"Option Type\",\n", + " \"_\": \"$\\_\",\n", + " \"Gbm\": \"\\gls{GBM}\",\n", + "}\n", + "\n", + "LUT_INDEX = {\n", + " \"OPTION_TYPE\": \"Option Type\",\n", + " \"issue_type\": \"Security Type\",\n", + " \"TRADE_SIZE_binned\": \"Trade Size\",\n", + " \"year_binned\": \"Year\",\n", + " \"ttm_binned\": \"Time to Maturity\",\n", + " \"myn_binned\": \"Moneyness\",\n", + " \"prox_q_binned\": \"Location to Quote\",\n", + " \"all\": \"All trades\",\n", + "}\n", + "\n", + "\n", + "def cell_str(x):\n", + " x = x.title()\n", + " for orig, sub in LUT.items():\n", + " x = x.replace(orig, sub)\n", + " # title-case everything\n", + " return x\n", + "\n", + "\n", + "def highlight_max(s, props=\"\"):\n", + " return np.where(s == np.nanmax(s.values), props, \"\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def set_tex_style(styler, caption, label, bold_axis=1):\n", + " res = styler.set_caption(caption)\n", + "\n", + " res = (\n", + " res.apply(highlight_max, props=\"font-weight:bold;\", axis=bold_axis)\n", + " .format(precision=4, decimal=\".\", thousands=\",\", escape=False, hyperlinks=None)\n", + " .format_index(cell_str, axis=0)\n", + " .format_index(cell_str, axis=1)\n", + " .to_latex(\n", + " f\"{label}.tex\",\n", + " siunitx=True,\n", + " position_float=\"centering\",\n", + " hrules=True,\n", + " clines=\"skip-last;data\",\n", + " label=\"tab:\" + label,\n", + " caption=caption,\n", + " convert_css=True,\n", + " )\n", + " )\n", + " return res\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "classifiers = results_data.columns.tolist()\n", + "criterions = list(LUT_INDEX)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "classifiers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unclassified by method" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "unclassified = (\n", + " (results_data[results_data == 0.0].count(axis=0) / len(results_data.index))\n", + " # .sort_values(ascending=False)\n", + " .to_frame(name=\"unclassified\")\n", + ")\n", + "\n", + "# coverage in %\n", + "unclassified = 100 - (unclassified * 100)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "unclassified.style.pipe(\n", + " set_tex_style,\n", + " caption=(f\"{KEY}-unclassified-long\", \"{key}-unclassified-short\"),\n", + " label=f\"{KEY.lower()}-unclassfied\",\n", + " bold_axis=0,\n", + ")\n", + "unclassified\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fill in unclassified\n", + "\n", + "Unclassified are `0`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "rng = np.random.default_rng(42)\n", + "\n", + "# replace 0 -> nan -> [-1,1]\n", + "results_data.replace(0, np.nan, inplace=True)\n", + "# assume same filler for every column\n", + "filler = pd.Series(\n", + " rng.choice(a=[-1, 1], size=results_data.shape[0]),\n", + " index=results_data.index,\n", + " # columns=results_data.columns,\n", + ")\n", + "\n", + "# do column-wise as we run out of memory otherwise\n", + "for classifier in tqdm(classifiers):\n", + " results_data[classifier].fillna(filler, inplace=True)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### McNemar's Test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "X_print = pd.concat([X_print, results_data], axis=1)\n", + "Y = X_print[[*results_data.columns.tolist(), \"buy_sell\"]]\n", + "\n", + "import statsmodels\n", + "from statsmodels.stats.contingency_tables import mcnemar\n", + "\n", + "results = []\n", + "combinations = [(('gbm', 'gbm(semi-classical)'), ('fttransformer', 'fttransformer(semi-classical)')),\n", + " (('gbm', 'gbm(semi-classical-size)'), ('fttransformer', 'fttransformer(semi-classical-size)')),\n", + " (('gbm', 'gbm(semi-ml)'), ('fttransformer', 'fttransformer(semi-ml)'))]\n", + "significance = 0.05\n", + "\n", + "def get_contingency_table(Y, ground_truth, model_1, model_2):\n", + "\n", + " Y_ = Y[[ground_truth, model_1, model_2]].copy().astype(int)\n", + "\n", + " c_0_0 = np.where((Y_[model_1] == Y_[ground_truth]) & (Y_[model_2] == Y_[ground_truth]), 1, 0).sum()\n", + " c_0_1 = np.where((Y_[model_1] == Y_[ground_truth]) & (Y_[model_2] != Y_[ground_truth]), 1, 0).sum()\n", + " c_1_0 = np.where((Y_[model_1] != Y_[ground_truth]) & (Y_[model_2] == Y_[ground_truth]), 1, 0).sum()\n", + " c_1_1 = np.where((Y_[model_1] != Y_[ground_truth]) & (Y_[model_2] != Y_[ground_truth]), 1, 0).sum()\n", + " \n", + " # [both right, gbm right/transformer wrong, gbm wrong/transformer right, both wrong]\n", + " contingency_table = [[c_0_0, c_0_1],[c_1_0, c_1_1]]\n", + "\n", + " return np.array(contingency_table)\n", + "\n", + " \n", + "for combination in tqdm(combinations):\n", + " contingency_table = get_contingency_table(Y, 'buy_sell', combination[0], combination[1])\n", + " test = mcnemar(contingency_table, exact=False, correction=True)\n", + " \n", + " results.append({\"contingency_table\": contingency_table, \"model_1\": combination[0], \"model_2\": combination[1], \"statistic\": test.statistic, \"p-value\": test.pvalue, \"significant\": test.pvalue < significance})\n", + " \n", + "pd.DataFrame(results).to_csv(f\"../models/{EXCHANGE}-mcnemar.csv\")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "h3vzAVSc_DfD" + }, + "source": [ + "### Robustness Checks" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "3evMG-KVA2eX" + }, + "outputs": [], + "source": [ + "# %%script false --no-raise-error\n", + "# prepare columns for printing\n", + "X_print[\"ttm\"] = (\n", + " X_print[\"EXPIRATION\"].dt.to_period(\"M\")\n", + " - X_print[\"QUOTE_DATETIME\"].dt.to_period(\"M\")\n", + ").apply(lambda x: x.n)\n", + "\n", + "X_print[\"year\"] = X_print[\"QUOTE_DATETIME\"].dt.year\n", + "\n", + "bins_tradesize = [-1, 1, 3, 5, 11, np.inf]\n", + "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", + "X_print[\"TRADE_SIZE_binned\"] = pd.cut(\n", + " X_print[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", + ")\n", + "\n", + "# p. 38\n", + "bins_years = [2004, 2007, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]\n", + "year_labels = [\n", + " \"2005-2007\",\n", + " \"2008-2010\",\n", + " \"2011\",\n", + " \"2012\",\n", + " \"2013\",\n", + " \"2014\",\n", + " \"2015\",\n", + " \"2016\",\n", + " \"2017\",\n", + "]\n", + "X_print[\"year_binned\"] = pd.cut(X_print[\"year\"], bins_years, labels=year_labels)\n", + "\n", + "# p. 37\n", + "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", + "ttm_labels = [\n", + " \"<= 1\",\n", + " \"(1-2]\",\n", + " \"(2-3]\",\n", + " \"(3-6]\",\n", + " \"(6-12]\",\n", + " \"> 12\",\n", + "]\n", + "X_print[\"ttm_binned\"] = pd.cut(X_print[\"ttm\"], bins_ttm, labels=ttm_labels)\n", + "\n", + "# Security type\n", + "# see 3.0a-mb-explanatory-data-analysis.ipynb\n", + "X_print[\"issue_type\"] = X_print[\"issue_type\"].map(\n", + " {\n", + " \"0\": \"Stock option\",\n", + " \"A\": \"Index option\",\n", + " \"7\": \"Others\",\n", + " \"F\": \"Others\",\n", + " \"%\": \"Others\",\n", + " \" \": \"Others\",\n", + " }\n", + ")\n", + "\n", + "# Moneyness p. 38\n", + "bins_myn = [-1, 0.7, 0.9, 1.1, 1.3, np.inf]\n", + "myn_labels = [\n", + " \"<= 0.7\",\n", + " \"(0.7-0.9]\",\n", + " \"(0.9-1.1]\",\n", + " \"(1.1-1.3]\",\n", + " \"> 1.3\",\n", + "]\n", + "X_print[\"myn_binned\"] = pd.cut(X_print[\"myn\"], bins_myn, labels=myn_labels)\n", + "\n", + "# mid p. 31 + extra category for unknowns\n", + "ask = X_print[\"ask_ex\"]\n", + "bid = X_print[\"bid_ex\"]\n", + "trade_price = X_print[\"TRADE_PRICE\"]\n", + "\n", + "# require ask >= bid\n", + "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", + "\n", + "prox_quotes = np.where(\n", + " trade_price == mid,\n", + " 0, # at mid\n", + " np.where(\n", + " (bid < trade_price) & (trade_price < ask),\n", + " 1, # inside\n", + " np.where(\n", + " (trade_price == bid) | (ask == trade_price),\n", + " 2, # at quotes\n", + " np.where((trade_price < bid) | (ask < trade_price), 3, 4),\n", + " ),\n", + " ),\n", + ") # outside + unclassifiable\n", + "\n", + "bins_prox = [-np.inf, 0, 1, 2, 3, 4]\n", + "prox_labels = [\n", + " \"at mid\",\n", + " \"inside\",\n", + " \"at quotes\",\n", + " \"outside\",\n", + " \"unknown\",\n", + "]\n", + "\n", + "X_print[\"prox_q_binned\"] = pd.cut(prox_quotes, bins_prox, labels=prox_labels)\n", + "X_print[\"mid\"] = mid\n", + "\n", + "# clean up empty buckets, as it causes empty grouping in result set generation\n", + "X_print[\"year_binned\"] = X_print[\"year_binned\"].cat.remove_unused_categories()\n", + "X_print[\"myn_binned\"] = X_print[\"myn_binned\"].cat.remove_unused_categories()\n", + "X_print[\"ttm_binned\"] = X_print[\"ttm_binned\"].cat.remove_unused_categories()\n", + "X_print[\"prox_q_binned\"] = X_print[\"prox_q_binned\"].cat.remove_unused_categories()\n", + "\n", + "X_print[\"all\"] = \"all\"\n", + "\n", + "X_print.drop(\n", + " columns=[\n", + " \"EXPIRATION\",\n", + " \"QUOTE_DATETIME\",\n", + " # \"TRADE_SIZE\",\n", + " \"ttm\",\n", + " \"myn\",\n", + " \"year\",\n", + " ],\n", + " inplace=True,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X_print = pd.concat([X_print, results_data], axis=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X_print.head().T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Accuracy Calculation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# FIXME: Find better approach\n", + "warnings.filterwarnings(\"ignore\", category=np.VisibleDeprecationWarning)\n", + "\n", + "result_dfs = []\n", + "\n", + "for criterion in tqdm(criterions):\n", + " results = []\n", + " for classifier in classifiers:\n", + " res = (\n", + " X_print.groupby([criterion])[[\"buy_sell\", classifier]]\n", + " .apply(\n", + " lambda x: accuracy_score(x[\"buy_sell\"].astype(\"int8\"), x[classifier])\n", + " )\n", + " .mul(100)\n", + " .rename(classifier)\n", + " )\n", + " # acc_tot = accuracy_score(\n", + " # X_print[\"buy_sell\"].astype(\"int8\"), X_print[classifier]\n", + " # )\n", + "\n", + " # res.loc[\"all\"] = acc_tot * 100\n", + "\n", + " res.index.name = LUT_INDEX.get(criterion)\n", + " results.append(res)\n", + "\n", + " # save aggregated results\n", + " result_df = pd.concat(results, axis=1).T\n", + " # result_df.style.pipe(\n", + " # set_tex_style,\n", + " # caption=(f\"long-tbd\", \"short-tbd\"),\n", + " # label=f\"{KEY.lower()}-{criterion.lower()}\",\n", + " # )\n", + "\n", + " # store all result sets for later use\n", + " result_dfs.append(result_df)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "%%script false --no-raise-error\n", + "keys = [\"set\", \"all\"]\n", + "master = pd.concat(result_dfs, axis=1, keys=keys).T" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "master = pd.concat(result_dfs, axis=1, keys=list(LUT_INDEX.values())).T" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "master.style.pipe(\n", + " set_tex_style,\n", + " caption=(\"master-long\", \"master-short\"),\n", + " label=f\"{KEY}-master\",\n", + " bold_axis=0,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "master" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Effective Spread πŸ’΄" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# mid p. 31 + extra category for unknowns\n", + "ask = X_print[\"ask_ex\"]\n", + "bid = X_print[\"bid_ex\"]\n", + "trade_price = X_print[\"TRADE_PRICE\"]\n", + "\n", + "# require ask >= bid\n", + "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", + "\n", + "results = []\n", + "\n", + "# calculate true rel effective spread but not aggregated, convert to %\n", + "es_true = effective_spread(X_print[\"buy_sell\"], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", + "nom_true = np.nanmean(es_true)\n", + "\n", + "eps_true = np.empty(es_true.shape)\n", + "np.divide(es_true, mid, out=eps_true, where=mid != 0)\n", + "rel_true = np.nanmean(eps_true)\n", + "\n", + "\n", + "for classifier in tqdm(classifiers):\n", + "\n", + " # calculate pred rel effective spread but not aggregated convert to %\n", + " es_pred = effective_spread(X_print[classifier], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", + " \n", + " eps_pred = np.empty(es_pred.shape)\n", + " np.divide(es_pred, mid, out=eps_pred, where=mid != 0)\n", + "\n", + " wilcoxon_res = wilcoxon(eps_pred, eps_true, nan_policy=\"omit\", zero_method=\"zsplit\")\n", + "\n", + " res = pd.Series(\n", + " {\n", + " \"nom_pred\": np.nanmean(es_pred),\n", + " \"rel_pred\": np.nanmean(eps_pred),\n", + " \"statistic\":wilcoxon_res.statistic,\n", + " \"pvalue\":wilcoxon_res.pvalue,\n", + " }, name=classifier\n", + " )\n", + " results.append(res)\n", + "\n", + "true_eff = pd.Series({\"nom_pred\":nom_true, \"rel_pred\": rel_true, \"statistic\":np.NaN, \"pvalue\":np.NaN}, name=\"true_eff\")\n", + "\n", + "results.append(true_eff)\n", + "\n", + "results = pd.concat(results, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "results.T.style.format(\"{:.3f}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results.T.style.to_latex(\n", + " f\"../reports/Content/{KEY}-eff-spread.tex\",\n", + " siunitx=True,\n", + " position_float=\"centering\",\n", + " hrules=True,\n", + " clines=\"skip-last;data\",\n", + " label=f\"tab:eff-{KEY}\",\n", + " caption=(f\"long-eff-{KEY}\", f\"short-eff-{KEY}\"),\n", + " convert_css=True,\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Diffs πŸ”„οΈ" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "master.columns.tolist()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# classical baselines\n", + "view = [(\"fttransformer\", \"fttransformer(semi-classical)\"), (\"fttransformer\", \"fttransformer(semi-classical-size)\"), (\"fttransformer\", \"fttransformer(semi-ml)\")]\n", + "\n", + "base = master[\n", + " [\n", + " (\"classical\", \"quote(best)->quote(ex)->rev_tick(all)\"),\n", + " (\n", + " \"classical\",\n", + " \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", + " ),\n", + " (\n", + " \"classical\",\n", + " \"trade_size(ex)->quote(best)->quote(ex)->depth(best)->depth(ex)->rev_tick(all)\",\n", + " ),\n", + " ]\n", + "]\n", + "\n", + "# my ml models\n", + "revised = master[view]\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def combine_results(revised: pd.DataFrame, base: pd.DataFrame) -> pd.DataFrame:\n", + " \"\"\"\n", + " Generate print layout like in Grauer et al.\n", + "\n", + " https://tex.stackexchange.com/questions/430283/table-with-numbers-in-parentheses-in-siunitx/430290#430290\n", + "\n", + " # see p. https://texdoc.org/serve/siunitx/0\n", + " \"\"\"\n", + " # first, second layer of colum index\n", + " c_1 = revised.columns.get_level_values(1)\n", + " c_2 = [\"nom\"]\n", + " midx = pd.MultiIndex.from_product([c_1, c_2])\n", + "\n", + " # copy data from revised add as (column, \"nom\")\n", + " combo = pd.DataFrame(revised.values, index=revised.index, columns=midx)\n", + "\n", + " for i, mul_col in enumerate(combo.columns):\n", + "\n", + " combo[(mul_col[0], \"pm\")] = (combo[mul_col] - base.iloc[:, i]).round(2)\n", + " combo.sort_index(axis=1, inplace=True)\n", + "\n", + " return combo\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "diff = combine_results(revised, base)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "diff.style.to_latex(\n", + " f\"../reports/Content/diff-{KEY}.tex\",\n", + " siunitx=True,\n", + " position_float=\"centering\",\n", + " hrules=True,\n", + " clines=\"skip-last;data\",\n", + " label=f\"tab:diff-{KEY}\",\n", + " caption=(f\"long-diff-{KEY}\", f\"short-diff-{KEY}\"),\n", + " convert_css=True,\n", + ")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "diff\n" + ] + } + ], + "metadata": { + "colab": { + "include_colab_link": true, + "machine_shape": "hm", + "name": "Untitled2.ipynb", + "provenance": [] + }, + "gpuClass": "premium", + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "myenv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/notebooks/6.0i-mb-discussion.ipynb b/notebooks/6.0i-mb-discussion.ipynb index dbf1b68c..8576cd68 100644 --- a/notebooks/6.0i-mb-discussion.ipynb +++ b/notebooks/6.0i-mb-discussion.ipynb @@ -1,671 +1,671 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "7WXF7w4VyVgG", - "tags": [] - }, - "outputs": [], - "source": [ - "import os\n", - "import random\n", - "import sys\n", - "from pathlib import Path\n", - "\n", - "import numpy as np\n", - "import pandas as pd\n", - "from sklearn.metrics import accuracy_score\n", - "\n", - "sys.path.append(\"..\")\n", - "import warnings\n", - "\n", - "import wandb\n", - "from tqdm.auto import tqdm\n", - "\n", - "from otc.features.build_features import features_ml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Summary Statistics" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "run = wandb.init(project=\"thesis\", job_type=\"dataset-creation\", entity=\"fbv\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "exchange = \"cboe\"\n", - "strategy = \"transfer\"" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "dataset = f\"fbv/thesis/{exchange}_{strategy}_none:latest\"\n", - "\n", - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "# load unscaled data\n", - "artifact = run.use_artifact(dataset)\n", - "data_dir = artifact.download()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "train, val, test = None, None, None\n", - "columns = [*features_ml, \"buy_sell\"]\n", - "\n", - "if strategy == \"supervised\":\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - " val = pd.read_parquet(\n", - " Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - " \n", - "elif strategy == \"transfer\":\n", - " # load test set\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=columns\n", - " )\n", - "\n", - " \n", - "elif strategy == \"unsupervised\":\n", - " # load unlabelled training set\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=columns\n", - " )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "def summarize_stats(df):\n", - " summary_stats = pd.DataFrame(index=df.columns) # Create an empty DataFrame with column names as index\n", - "\n", - " # Calculate summary statistics\n", - " # summary_stats['Count'] = df.count()\n", - " # summary_stats['Nunique'] = df.nunique()\n", - "\n", - " summary_stats = df.describe(percentiles=[0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99])\n", - " summary_stats = summary_stats.transpose() # Transpose the table to have columns as variables\n", - "\n", - " # Rename the columns\n", - " summary_stats.rename(columns={'mean': 'Mean', 'std': 'SD', '50%': 'Median'},\n", - " inplace=True)\n", - " return summary_stats[[\"Mean\", \"SD\", \"1%\", \"5%\", \"25%\", \"Median\", \"75%\",\"95%\", \"99%\"]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# all_sets = pd.concat([train, val, test])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "summary = summarize_stats(test)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "KEY = f\"{exchange}-{strategy}-test\"\n", - "FNAME = \"../reports/Content/\" + KEY + \"-summary-stats.tex\"\n", - "\n", - "summary.style.to_latex(\n", - " FNAME,\n", - " siunitx=True,\n", - " position_float=\"centering\",\n", - " hrules=True,\n", - " clines=\"skip-last;data\",\n", - " label=f\"tab:{KEY}\",\n", - " caption=(f\"long{KEY}\", f\"short{KEY}\"),\n", - " convert_css=True,\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Insights into distribution" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# set here globally\n", - "EXCHANGE = \"ise\" # \"ise\"\n", - "MODELS = [\"classical\"] # \"classical\", \"fttransformer\", \"gbm\"\n", - "SUBSET = \"all\" # \"all\"\n", - "STRATEGY = \"supervised\" # \"supervised\" \n", - "\n", - "RETRAIN = False" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "KEY = f\"{EXCHANGE}_{STRATEGY}_{SUBSET}\"\n", - "DATASET = f\"fbv/thesis/{EXCHANGE}_{STRATEGY}_none:latest\"\n", - "\n", - "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", - "\n", - "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", - "\n", - "# load unscaled data\n", - "artifact = run.use_artifact(DATASET) \n", - "data_dir = artifact.download()\n", - "\n", - "# load results\n", - "result_dirs = []\n", - "for model in MODELS:\n", - " # retraining is only possible for gbm\n", - " if model == \"gbm\" and RETRAIN:\n", - " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}_retrain:latest\"\n", - " else:\n", - " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}:latest\"\n", - " artifact = run.use_artifact(results) \n", - " result_dir = artifact.download()\n", - " result_dirs.append(result_dir)\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "id": "WmXtH-PEqyQE", - "tags": [] - }, - "outputs": [], - "source": [ - "# p. 35-38\n", - "COLUMNS = [\n", - " \"buy_sell\",\n", - " \"ttm\",\n", - " \"TRADE_SIZE\",\n", - " \"TRADE_PRICE\",\n", - " \"ask_ex\",\n", - " \"ask_size_ex\",\n", - " \"bid_ex\",\n", - " \"bid_size_ex\",\n", - " \"myn\",\n", - " \"option_type\",\n", - " \"issue_type\",\n", - " \"prox_ex\",\n", - " # \"price_ex_lag\",\n", - " # \"price_all_lag\",\n", - " # \"BEST_BID\",\n", - " # \"BEST_ASK\",\n", - "]\n", - "\n", - "\n", - "if SUBSET == \"all\":\n", - " train = pd.read_parquet(\n", - " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " val = pd.read_parquet(\n", - " Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " test = pd.read_parquet(\n", - " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - " eval_data = pd.concat([train, val, test])\n", - " del train, val, test\n", - "\n", - "elif SUBSET == \"test\":\n", - " eval_data = pd.read_parquet(\n", - " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", - " )\n", - "\n", - "\n", - "results = []\n", - "for i, model in tqdm(enumerate(MODELS)):\n", - " result = pd.read_parquet(Path(result_dirs[i], \"results\"), engine=\"fastparquet\")\n", - " result.columns = pd.MultiIndex.from_product([[model], result.columns])\n", - " results.append(result)\n", - "\n", - "results_data = pd.concat(results, axis=1, names=MODELS)\n", - "\n", - "assert len(eval_data) == len(results_data)\n", - "\n", - "X_print = eval_data\n", - "\n", - "del results\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X_print[\"issue_type\"].values" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "bins_tradesize = [-1, 1, 3, 5, 11, np.inf]\n", - "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", - "X_print[\"TRADE_SIZE_binned\"] = pd.cut(\n", - " X_print[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", - ")\n", - "\n", - "# p. 37\n", - "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", - "ttm_labels = [\n", - " \"<= 1\",\n", - " \"(1-2]\",\n", - " \"(2-3]\",\n", - " \"(3-6]\",\n", - " \"(6-12]\",\n", - " \"> 12\",\n", - "]\n", - "X_print[\"ttm_binned\"] = pd.cut(X_print[\"ttm\"], bins_ttm, labels=ttm_labels)\n", - "\n", - "# Security type\n", - "# see 3.0a-mb-explanatory-data-analysis.ipynb\n", - "X_print[\"issue_type\"] = X_print[\"issue_type\"].map(\n", - " {\n", - " \"0\": \"Stock option\",\n", - " \"A\": \"Index option\",\n", - " \"7\": \"Others\",\n", - " \"F\": \"Others\",\n", - " \"%\": \"Others\",\n", - " \" \": \"Others\",\n", - " }\n", - ")\n", - "\n", - "# Moneyness p. 38\n", - "bins_myn = [-1, 0.7, 0.9, 1.1, 1.3, np.inf]\n", - "myn_labels = [\n", - " \"<= 0.7\",\n", - " \"(0.7-0.9]\",\n", - " \"(0.9-1.1]\",\n", - " \"(1.1-1.3]\",\n", - " \"> 1.3\",\n", - "]\n", - "X_print[\"myn_binned\"] = pd.cut(X_print[\"myn\"], bins_myn, labels=myn_labels)\n", - "\n", - "# mid p. 31 + extra category for unknowns\n", - "ask = X_print[\"ask_ex\"]\n", - "bid = X_print[\"bid_ex\"]\n", - "trade_price = X_print[\"TRADE_PRICE\"]\n", - "\n", - "# require ask >= bid\n", - "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", - "\n", - "prox_quotes = np.where(\n", - " trade_price == mid,\n", - " 0, # at mid\n", - " np.where(\n", - " (bid < trade_price) & (trade_price < ask),\n", - " 1, # inside\n", - " np.where(\n", - " (trade_price == bid) | (ask == trade_price),\n", - " 2, # at quotes\n", - " np.where((trade_price < bid) | (ask < trade_price), 3, 4),\n", - " ),\n", - " ),\n", - ") # outside + unclassifiable\n", - "\n", - "bins_prox = [-np.inf, 0, 1, 2, 3, 4]\n", - "prox_labels = [\n", - " \"at mid\",\n", - " \"inside\",\n", - " \"at quotes\",\n", - " \"outside\",\n", - " \"unknown\",\n", - "]\n", - "\n", - "X_print[\"prox_q_binned\"] = pd.cut(prox_quotes, bins_prox, labels=prox_labels)\n", - "X_print[\"mid\"] = mid\n", - "\n", - "# clean up empty buckets, as it causes empty grouping in result set generation\n", - "X_print[\"myn_binned\"] = X_print[\"myn_binned\"].cat.remove_unused_categories()\n", - "X_print[\"ttm_binned\"] = X_print[\"ttm_binned\"].cat.remove_unused_categories()\n", - "X_print[\"prox_q_binned\"] = X_print[\"prox_q_binned\"].cat.remove_unused_categories()\n", - "\n", - "X_print[\"values\"] = 1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X_print" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "X_print.head().T" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Trade size" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "pivot_table = pd.pivot_table(X_print, \n", - " values='values',\n", - " columns='prox_q_binned',\n", - " index='TRADE_SIZE_binned',\n", - " aggfunc=sum,\n", - " fill_value=0,\n", - " margins=True)\n", - "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Moneyness" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "pivot_table = pd.pivot_table(X_print, \n", - " values='values',\n", - " columns='myn_binned',\n", - " index='TRADE_SIZE_binned',\n", - " aggfunc=sum,\n", - " fill_value=0,\n", - " margins=True)\n", - "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Time-to-maturity" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# savickas: trades with longer maturity tend to be smaller\n", - "pivot_table = pd.pivot_table(X_print, \n", - " values='values',\n", - " index='ttm_binned',\n", - " columns='TRADE_SIZE_binned',\n", - " aggfunc=sum,\n", - " fill_value=0,\n", - " margins=True)\n", - "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Index Options" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "pivot_table = pd.pivot_table(X_print, \n", - " values='values',\n", - " index='issue_type',\n", - " columns=None,\n", - " aggfunc=sum,\n", - " fill_value=0,\n", - " margins=True)\n", - "pivot_table.div(pivot_table.iloc[-1], axis=1)\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Distribution of Trades" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "pivot_table = pd.pivot_table(X_print, \n", - " values='values',\n", - " index='prox_q_binned',\n", - " columns=None,\n", - " aggfunc=sum,\n", - " fill_value=0,\n", - " margins=True)\n", - "pivot_table.div(pivot_table.iloc[-1], axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# mid p. 31 + extra category for unknowns\n", - "ask = X_print[\"ask_ex\"]\n", - "bid = X_print[\"bid_ex\"]\n", - "trade_price = X_print[\"TRADE_PRICE\"]\n", - "\n", - "# require ask >= bid\n", - "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", - "\n", - "results = []\n", - "\n", - "# calculate true rel effective spread but not aggregated, convert to %\n", - "es_true = effective_spread(X_print[\"buy_sell\"], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", - "nom_true = np.nanmean(es_true)\n", - "\n", - "eps_true = np.empty(es_true.shape)\n", - "np.divide(es_true, mid, out=eps_true, where=mid != 0)\n", - "rel_true = np.nanmean(eps_true)\n", - "\n", - "\n", - "for classifier in tqdm(classifiers):\n", - "\n", - " # calculate pred rel effective spread but not aggregated convert to %\n", - " es_pred = effective_spread(X_print[classifier], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", - " \n", - " eps_pred = np.empty(es_pred.shape)\n", - " np.divide(es_pred, mid, out=eps_pred, where=mid != 0)\n", - "\n", - " wilcoxon_res = wilcoxon(eps_pred, eps_true, nan_policy=\"omit\", zero_method=\"zsplit\")\n", - "\n", - " res = pd.Series(\n", - " {\n", - " \"nom_pred\": np.nanmean(es_pred),\n", - " \"rel_pred\": np.nanmean(eps_pred),\n", - " \"statistic\":wilcoxon_res.statistic,\n", - " \"pvalue\":wilcoxon_res.pvalue,\n", - " }, name=classifier\n", - " )\n", - " results.append(res)\n", - "\n", - "true_eff = pd.Series({\"nom_pred\":nom_true, \"rel_pred\": rel_true, \"statistic\":np.NaN, \"pvalue\":np.NaN}, name=\"true_eff\")\n", - "\n", - "results.append(true_eff)\n", - "\n", - "results = pd.concat(results, axis=1)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "results.T.style.format(\"{:.3f}\")\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "results.T.style.to_latex(\n", - " f\"../reports/Content/{KEY}-eff-spread.tex\",\n", - " siunitx=True,\n", - " position_float=\"centering\",\n", - " hrules=True,\n", - " clines=\"skip-last;data\",\n", - " label=f\"tab:eff-{KEY}\",\n", - " caption=(f\"long-eff-{KEY}\", f\"short-eff-{KEY}\"),\n", - " convert_css=True,\n", - ")\n" - ] - } - ], - "metadata": { - "colab": { - "include_colab_link": true, - "machine_shape": "hm", - "name": "Untitled2.ipynb", - "provenance": [] - }, - "gpuClass": "premium", - "kernelspec": { - "display_name": "myenv", - "language": "python", - "name": "myenv" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - }, - "vscode": { - "interpreter": { - "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "7WXF7w4VyVgG", + "tags": [] + }, + "outputs": [], + "source": [ + "import os\n", + "import random\n", + "import sys\n", + "from pathlib import Path\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "from sklearn.metrics import accuracy_score\n", + "\n", + "sys.path.append(\"..\")\n", + "import warnings\n", + "\n", + "import wandb\n", + "from tqdm.auto import tqdm\n", + "\n", + "from otc.features.build_features import features_ml" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Summary Statistics" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "run = wandb.init(project=\"thesis\", job_type=\"dataset-creation\", entity=\"fbv\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "exchange = \"cboe\"\n", + "strategy = \"transfer\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dataset = f\"fbv/thesis/{exchange}_{strategy}_none:latest\"\n", + "\n", + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "# load unscaled data\n", + "artifact = run.use_artifact(dataset)\n", + "data_dir = artifact.download()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "train, val, test = None, None, None\n", + "columns = [*features_ml, \"buy_sell\"]\n", + "\n", + "if strategy == \"supervised\":\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + " val = pd.read_parquet(\n", + " Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + " \n", + "elif strategy == \"transfer\":\n", + " # load test set\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=columns\n", + " )\n", + "\n", + " \n", + "elif strategy == \"unsupervised\":\n", + " # load unlabelled training set\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=columns\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def summarize_stats(df):\n", + " summary_stats = pd.DataFrame(index=df.columns) # Create an empty DataFrame with column names as index\n", + "\n", + " # Calculate summary statistics\n", + " # summary_stats['Count'] = df.count()\n", + " # summary_stats['Nunique'] = df.nunique()\n", + "\n", + " summary_stats = df.describe(percentiles=[0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99])\n", + " summary_stats = summary_stats.transpose() # Transpose the table to have columns as variables\n", + "\n", + " # Rename the columns\n", + " summary_stats.rename(columns={'mean': 'Mean', 'std': 'SD', '50%': 'Median'},\n", + " inplace=True)\n", + " return summary_stats[[\"Mean\", \"SD\", \"1%\", \"5%\", \"25%\", \"Median\", \"75%\",\"95%\", \"99%\"]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# all_sets = pd.concat([train, val, test])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "summary = summarize_stats(test)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "KEY = f\"{exchange}-{strategy}-test\"\n", + "FNAME = \"../reports/Content/\" + KEY + \"-summary-stats.tex\"\n", + "\n", + "summary.style.to_latex(\n", + " FNAME,\n", + " siunitx=True,\n", + " position_float=\"centering\",\n", + " hrules=True,\n", + " clines=\"skip-last;data\",\n", + " label=f\"tab:{KEY}\",\n", + " caption=(f\"long{KEY}\", f\"short{KEY}\"),\n", + " convert_css=True,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Insights into distribution" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# set here globally\n", + "EXCHANGE = \"ise\" # \"ise\"\n", + "MODELS = [\"classical\"] # \"classical\", \"fttransformer\", \"gbm\"\n", + "SUBSET = \"all\" # \"all\"\n", + "STRATEGY = \"supervised\" # \"supervised\" \n", + "\n", + "RETRAIN = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "KEY = f\"{EXCHANGE}_{STRATEGY}_{SUBSET}\"\n", + "DATASET = f\"fbv/thesis/{EXCHANGE}_{STRATEGY}_none:latest\"\n", + "\n", + "os.environ[\"GCLOUD_PROJECT\"] = \"flowing-mantis-239216\"\n", + "\n", + "run = wandb.init(project=\"thesis\", entity=\"fbv\")\n", + "\n", + "# load unscaled data\n", + "artifact = run.use_artifact(DATASET) \n", + "data_dir = artifact.download()\n", + "\n", + "# load results\n", + "result_dirs = []\n", + "for model in MODELS:\n", + " # retraining is only possible for gbm\n", + " if model == \"gbm\" and RETRAIN:\n", + " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}_retrain:latest\"\n", + " else:\n", + " results = f\"fbv/thesis/{EXCHANGE}_{model}_{STRATEGY}_{SUBSET}:latest\"\n", + " artifact = run.use_artifact(results) \n", + " result_dir = artifact.download()\n", + " result_dirs.append(result_dir)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "WmXtH-PEqyQE", + "tags": [] + }, + "outputs": [], + "source": [ + "# p. 35-38\n", + "COLUMNS = [\n", + " \"buy_sell\",\n", + " \"ttm\",\n", + " \"TRADE_SIZE\",\n", + " \"TRADE_PRICE\",\n", + " \"ask_ex\",\n", + " \"ask_size_ex\",\n", + " \"bid_ex\",\n", + " \"bid_size_ex\",\n", + " \"myn\",\n", + " \"option_type\",\n", + " \"issue_type\",\n", + " \"prox_ex\",\n", + " # \"price_ex_lag\",\n", + " # \"price_all_lag\",\n", + " # \"BEST_BID\",\n", + " # \"BEST_ASK\",\n", + "]\n", + "\n", + "\n", + "if SUBSET == \"all\":\n", + " train = pd.read_parquet(\n", + " Path(data_dir, \"train_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " val = pd.read_parquet(\n", + " Path(data_dir, \"val_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " test = pd.read_parquet(\n", + " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + " eval_data = pd.concat([train, val, test])\n", + " del train, val, test\n", + "\n", + "elif SUBSET == \"test\":\n", + " eval_data = pd.read_parquet(\n", + " Path(data_dir, \"test_set.parquet\"), engine=\"fastparquet\", columns=COLUMNS\n", + " )\n", + "\n", + "\n", + "results = []\n", + "for i, model in tqdm(enumerate(MODELS)):\n", + " result = pd.read_parquet(Path(result_dirs[i], \"results\"), engine=\"fastparquet\")\n", + " result.columns = pd.MultiIndex.from_product([[model], result.columns])\n", + " results.append(result)\n", + "\n", + "results_data = pd.concat(results, axis=1, names=MODELS)\n", + "\n", + "assert len(eval_data) == len(results_data)\n", + "\n", + "X_print = eval_data\n", + "\n", + "del results\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X_print[\"issue_type\"].values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "bins_tradesize = [-1, 1, 3, 5, 11, np.inf]\n", + "trade_size_labels = [\"(0,1]\", \"(1,3]\", \"(3,5]\", \"(5,11]\", \">11\"]\n", + "X_print[\"TRADE_SIZE_binned\"] = pd.cut(\n", + " X_print[\"TRADE_SIZE\"], bins_tradesize, labels=trade_size_labels\n", + ")\n", + "\n", + "# p. 37\n", + "bins_ttm = [-1, 1, 2, 3, 6, 12, np.inf]\n", + "ttm_labels = [\n", + " \"<= 1\",\n", + " \"(1-2]\",\n", + " \"(2-3]\",\n", + " \"(3-6]\",\n", + " \"(6-12]\",\n", + " \"> 12\",\n", + "]\n", + "X_print[\"ttm_binned\"] = pd.cut(X_print[\"ttm\"], bins_ttm, labels=ttm_labels)\n", + "\n", + "# Security type\n", + "# see 3.0a-mb-explanatory-data-analysis.ipynb\n", + "X_print[\"issue_type\"] = X_print[\"issue_type\"].map(\n", + " {\n", + " \"0\": \"Stock option\",\n", + " \"A\": \"Index option\",\n", + " \"7\": \"Others\",\n", + " \"F\": \"Others\",\n", + " \"%\": \"Others\",\n", + " \" \": \"Others\",\n", + " }\n", + ")\n", + "\n", + "# Moneyness p. 38\n", + "bins_myn = [-1, 0.7, 0.9, 1.1, 1.3, np.inf]\n", + "myn_labels = [\n", + " \"<= 0.7\",\n", + " \"(0.7-0.9]\",\n", + " \"(0.9-1.1]\",\n", + " \"(1.1-1.3]\",\n", + " \"> 1.3\",\n", + "]\n", + "X_print[\"myn_binned\"] = pd.cut(X_print[\"myn\"], bins_myn, labels=myn_labels)\n", + "\n", + "# mid p. 31 + extra category for unknowns\n", + "ask = X_print[\"ask_ex\"]\n", + "bid = X_print[\"bid_ex\"]\n", + "trade_price = X_print[\"TRADE_PRICE\"]\n", + "\n", + "# require ask >= bid\n", + "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", + "\n", + "prox_quotes = np.where(\n", + " trade_price == mid,\n", + " 0, # at mid\n", + " np.where(\n", + " (bid < trade_price) & (trade_price < ask),\n", + " 1, # inside\n", + " np.where(\n", + " (trade_price == bid) | (ask == trade_price),\n", + " 2, # at quotes\n", + " np.where((trade_price < bid) | (ask < trade_price), 3, 4),\n", + " ),\n", + " ),\n", + ") # outside + unclassifiable\n", + "\n", + "bins_prox = [-np.inf, 0, 1, 2, 3, 4]\n", + "prox_labels = [\n", + " \"at mid\",\n", + " \"inside\",\n", + " \"at quotes\",\n", + " \"outside\",\n", + " \"unknown\",\n", + "]\n", + "\n", + "X_print[\"prox_q_binned\"] = pd.cut(prox_quotes, bins_prox, labels=prox_labels)\n", + "X_print[\"mid\"] = mid\n", + "\n", + "# clean up empty buckets, as it causes empty grouping in result set generation\n", + "X_print[\"myn_binned\"] = X_print[\"myn_binned\"].cat.remove_unused_categories()\n", + "X_print[\"ttm_binned\"] = X_print[\"ttm_binned\"].cat.remove_unused_categories()\n", + "X_print[\"prox_q_binned\"] = X_print[\"prox_q_binned\"].cat.remove_unused_categories()\n", + "\n", + "X_print[\"values\"] = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X_print" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "X_print.head().T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Trade size" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pivot_table = pd.pivot_table(X_print, \n", + " values='values',\n", + " columns='prox_q_binned',\n", + " index='TRADE_SIZE_binned',\n", + " aggfunc=sum,\n", + " fill_value=0,\n", + " margins=True)\n", + "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Moneyness" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pivot_table = pd.pivot_table(X_print, \n", + " values='values',\n", + " columns='myn_binned',\n", + " index='TRADE_SIZE_binned',\n", + " aggfunc=sum,\n", + " fill_value=0,\n", + " margins=True)\n", + "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Time-to-maturity" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# savickas: trades with longer maturity tend to be smaller\n", + "pivot_table = pd.pivot_table(X_print, \n", + " values='values',\n", + " index='ttm_binned',\n", + " columns='TRADE_SIZE_binned',\n", + " aggfunc=sum,\n", + " fill_value=0,\n", + " margins=True)\n", + "pivot_table.div(pivot_table.iloc[:,-1], axis=0 )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Index Options" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pivot_table = pd.pivot_table(X_print, \n", + " values='values',\n", + " index='issue_type',\n", + " columns=None,\n", + " aggfunc=sum,\n", + " fill_value=0,\n", + " margins=True)\n", + "pivot_table.div(pivot_table.iloc[-1], axis=1)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Distribution of Trades" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "pivot_table = pd.pivot_table(X_print, \n", + " values='values',\n", + " index='prox_q_binned',\n", + " columns=None,\n", + " aggfunc=sum,\n", + " fill_value=0,\n", + " margins=True)\n", + "pivot_table.div(pivot_table.iloc[-1], axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# mid p. 31 + extra category for unknowns\n", + "ask = X_print[\"ask_ex\"]\n", + "bid = X_print[\"bid_ex\"]\n", + "trade_price = X_print[\"TRADE_PRICE\"]\n", + "\n", + "# require ask >= bid\n", + "mid = np.where(ask >= bid, (ask + bid) * 0.5, np.nan)\n", + "\n", + "results = []\n", + "\n", + "# calculate true rel effective spread but not aggregated, convert to %\n", + "es_true = effective_spread(X_print[\"buy_sell\"], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", + "nom_true = np.nanmean(es_true)\n", + "\n", + "eps_true = np.empty(es_true.shape)\n", + "np.divide(es_true, mid, out=eps_true, where=mid != 0)\n", + "rel_true = np.nanmean(eps_true)\n", + "\n", + "\n", + "for classifier in tqdm(classifiers):\n", + "\n", + " # calculate pred rel effective spread but not aggregated convert to %\n", + " es_pred = effective_spread(X_print[classifier], X_print[\"TRADE_PRICE\"], mid, mode=\"none\")\n", + " \n", + " eps_pred = np.empty(es_pred.shape)\n", + " np.divide(es_pred, mid, out=eps_pred, where=mid != 0)\n", + "\n", + " wilcoxon_res = wilcoxon(eps_pred, eps_true, nan_policy=\"omit\", zero_method=\"zsplit\")\n", + "\n", + " res = pd.Series(\n", + " {\n", + " \"nom_pred\": np.nanmean(es_pred),\n", + " \"rel_pred\": np.nanmean(eps_pred),\n", + " \"statistic\":wilcoxon_res.statistic,\n", + " \"pvalue\":wilcoxon_res.pvalue,\n", + " }, name=classifier\n", + " )\n", + " results.append(res)\n", + "\n", + "true_eff = pd.Series({\"nom_pred\":nom_true, \"rel_pred\": rel_true, \"statistic\":np.NaN, \"pvalue\":np.NaN}, name=\"true_eff\")\n", + "\n", + "results.append(true_eff)\n", + "\n", + "results = pd.concat(results, axis=1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "results.T.style.format(\"{:.3f}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "results.T.style.to_latex(\n", + " f\"../reports/Content/{KEY}-eff-spread.tex\",\n", + " siunitx=True,\n", + " position_float=\"centering\",\n", + " hrules=True,\n", + " clines=\"skip-last;data\",\n", + " label=f\"tab:eff-{KEY}\",\n", + " caption=(f\"long-eff-{KEY}\", f\"short-eff-{KEY}\"),\n", + " convert_css=True,\n", + ")\n" + ] + } + ], + "metadata": { + "colab": { + "include_colab_link": true, + "machine_shape": "hm", + "name": "Untitled2.ipynb", + "provenance": [] + }, + "gpuClass": "premium", + "kernelspec": { + "display_name": "myenv", + "language": "python", + "name": "myenv" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "f8ea8b642289b706932f10b33ee389827410dbaef0ce2c5bf73615e8d3267d88" + } + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 00000000..95ddd72b --- /dev/null +++ b/poetry.lock @@ -0,0 +1,3487 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "aiohttp" +version = "3.8.6" +description = "Async http client/server framework (asyncio)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:41d55fc043954cddbbd82503d9cc3f4814a40bcef30b3569bc7b5e34130718c1"}, + {file = "aiohttp-3.8.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1d84166673694841d8953f0a8d0c90e1087739d24632fe86b1a08819168b4566"}, + {file = "aiohttp-3.8.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:253bf92b744b3170eb4c4ca2fa58f9c4b87aeb1df42f71d4e78815e6e8b73c9e"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fd194939b1f764d6bb05490987bfe104287bbf51b8d862261ccf66f48fb4096"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6c5f938d199a6fdbdc10bbb9447496561c3a9a565b43be564648d81e1102ac22"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2817b2f66ca82ee699acd90e05c95e79bbf1dc986abb62b61ec8aaf851e81c93"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fa375b3d34e71ccccf172cab401cd94a72de7a8cc01847a7b3386204093bb47"}, + {file = "aiohttp-3.8.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9de50a199b7710fa2904be5a4a9b51af587ab24c8e540a7243ab737b45844543"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e1d8cb0b56b3587c5c01de3bf2f600f186da7e7b5f7353d1bf26a8ddca57f965"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8e31e9db1bee8b4f407b77fd2507337a0a80665ad7b6c749d08df595d88f1cf5"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7bc88fc494b1f0311d67f29fee6fd636606f4697e8cc793a2d912ac5b19aa38d"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ec00c3305788e04bf6d29d42e504560e159ccaf0be30c09203b468a6c1ccd3b2"}, + {file = "aiohttp-3.8.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ad1407db8f2f49329729564f71685557157bfa42b48f4b93e53721a16eb813ed"}, + {file = "aiohttp-3.8.6-cp310-cp310-win32.whl", hash = "sha256:ccc360e87341ad47c777f5723f68adbb52b37ab450c8bc3ca9ca1f3e849e5fe2"}, + {file = "aiohttp-3.8.6-cp310-cp310-win_amd64.whl", hash = "sha256:93c15c8e48e5e7b89d5cb4613479d144fda8344e2d886cf694fd36db4cc86865"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6e2f9cc8e5328f829f6e1fb74a0a3a939b14e67e80832975e01929e320386b34"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e6a00ffcc173e765e200ceefb06399ba09c06db97f401f920513a10c803604ca"}, + {file = "aiohttp-3.8.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:41bdc2ba359032e36c0e9de5a3bd00d6fb7ea558a6ce6b70acedf0da86458321"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14cd52ccf40006c7a6cd34a0f8663734e5363fd981807173faf3a017e202fec9"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2d5b785c792802e7b275c420d84f3397668e9d49ab1cb52bd916b3b3ffcf09ad"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1bed815f3dc3d915c5c1e556c397c8667826fbc1b935d95b0ad680787896a358"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96603a562b546632441926cd1293cfcb5b69f0b4159e6077f7c7dbdfb686af4d"}, + {file = "aiohttp-3.8.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d76e8b13161a202d14c9584590c4df4d068c9567c99506497bdd67eaedf36403"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e3f1e3f1a1751bb62b4a1b7f4e435afcdade6c17a4fd9b9d43607cebd242924a"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:76b36b3124f0223903609944a3c8bf28a599b2cc0ce0be60b45211c8e9be97f8"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a2ece4af1f3c967a4390c284797ab595a9f1bc1130ef8b01828915a05a6ae684"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:16d330b3b9db87c3883e565340d292638a878236418b23cc8b9b11a054aaa887"}, + {file = "aiohttp-3.8.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:42c89579f82e49db436b69c938ab3e1559e5a4409eb8639eb4143989bc390f2f"}, + {file = "aiohttp-3.8.6-cp311-cp311-win32.whl", hash = "sha256:efd2fcf7e7b9d7ab16e6b7d54205beded0a9c8566cb30f09c1abe42b4e22bdcb"}, + {file = "aiohttp-3.8.6-cp311-cp311-win_amd64.whl", hash = "sha256:3b2ab182fc28e7a81f6c70bfbd829045d9480063f5ab06f6e601a3eddbbd49a0"}, + {file = "aiohttp-3.8.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:fdee8405931b0615220e5ddf8cd7edd8592c606a8e4ca2a00704883c396e4479"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d25036d161c4fe2225d1abff2bd52c34ed0b1099f02c208cd34d8c05729882f0"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d791245a894be071d5ab04bbb4850534261a7d4fd363b094a7b9963e8cdbd31"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0cccd1de239afa866e4ce5c789b3032442f19c261c7d8a01183fd956b1935349"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f13f60d78224f0dace220d8ab4ef1dbc37115eeeab8c06804fec11bec2bbd07"}, + {file = "aiohttp-3.8.6-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8a9b5a0606faca4f6cc0d338359d6fa137104c337f489cd135bb7fbdbccb1e39"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:13da35c9ceb847732bf5c6c5781dcf4780e14392e5d3b3c689f6d22f8e15ae31"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:4d4cbe4ffa9d05f46a28252efc5941e0462792930caa370a6efaf491f412bc66"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:229852e147f44da0241954fc6cb910ba074e597f06789c867cb7fb0621e0ba7a"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:713103a8bdde61d13490adf47171a1039fd880113981e55401a0f7b42c37d071"}, + {file = "aiohttp-3.8.6-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:45ad816b2c8e3b60b510f30dbd37fe74fd4a772248a52bb021f6fd65dff809b6"}, + {file = "aiohttp-3.8.6-cp36-cp36m-win32.whl", hash = "sha256:2b8d4e166e600dcfbff51919c7a3789ff6ca8b3ecce16e1d9c96d95dd569eb4c"}, + {file = "aiohttp-3.8.6-cp36-cp36m-win_amd64.whl", hash = "sha256:0912ed87fee967940aacc5306d3aa8ba3a459fcd12add0b407081fbefc931e53"}, + {file = "aiohttp-3.8.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2a988a0c673c2e12084f5e6ba3392d76c75ddb8ebc6c7e9ead68248101cd446"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ebf3fd9f141700b510d4b190094db0ce37ac6361a6806c153c161dc6c041ccda"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3161ce82ab85acd267c8f4b14aa226047a6bee1e4e6adb74b798bd42c6ae1f80"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d95fc1bf33a9a81469aa760617b5971331cdd74370d1214f0b3109272c0e1e3c"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c43ecfef7deaf0617cee936836518e7424ee12cb709883f2c9a1adda63cc460"}, + {file = "aiohttp-3.8.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca80e1b90a05a4f476547f904992ae81eda5c2c85c66ee4195bb8f9c5fb47f28"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:90c72ebb7cb3a08a7f40061079817133f502a160561d0675b0a6adf231382c92"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bb54c54510e47a8c7c8e63454a6acc817519337b2b78606c4e840871a3e15349"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:de6a1c9f6803b90e20869e6b99c2c18cef5cc691363954c93cb9adeb26d9f3ae"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:a3628b6c7b880b181a3ae0a0683698513874df63783fd89de99b7b7539e3e8a8"}, + {file = "aiohttp-3.8.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fc37e9aef10a696a5a4474802930079ccfc14d9f9c10b4662169671ff034b7df"}, + {file = "aiohttp-3.8.6-cp37-cp37m-win32.whl", hash = "sha256:f8ef51e459eb2ad8e7a66c1d6440c808485840ad55ecc3cafefadea47d1b1ba2"}, + {file = "aiohttp-3.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:b2fe42e523be344124c6c8ef32a011444e869dc5f883c591ed87f84339de5976"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e2ee0ac5a1f5c7dd3197de309adfb99ac4617ff02b0603fd1e65b07dc772e4b"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:01770d8c04bd8db568abb636c1fdd4f7140b284b8b3e0b4584f070180c1e5c62"}, + {file = "aiohttp-3.8.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3c68330a59506254b556b99a91857428cab98b2f84061260a67865f7f52899f5"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89341b2c19fb5eac30c341133ae2cc3544d40d9b1892749cdd25892bbc6ac951"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71783b0b6455ac8f34b5ec99d83e686892c50498d5d00b8e56d47f41b38fbe04"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f628dbf3c91e12f4d6c8b3f092069567d8eb17814aebba3d7d60c149391aee3a"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04691bc6601ef47c88f0255043df6f570ada1a9ebef99c34bd0b72866c217ae"}, + {file = "aiohttp-3.8.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ee912f7e78287516df155f69da575a0ba33b02dd7c1d6614dbc9463f43066e3"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9c19b26acdd08dd239e0d3669a3dddafd600902e37881f13fbd8a53943079dbc"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:99c5ac4ad492b4a19fc132306cd57075c28446ec2ed970973bbf036bcda1bcc6"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f0f03211fd14a6a0aed2997d4b1c013d49fb7b50eeb9ffdf5e51f23cfe2c77fa"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:8d399dade330c53b4106160f75f55407e9ae7505263ea86f2ccca6bfcbdb4921"}, + {file = "aiohttp-3.8.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec4fd86658c6a8964d75426517dc01cbf840bbf32d055ce64a9e63a40fd7b771"}, + {file = "aiohttp-3.8.6-cp38-cp38-win32.whl", hash = "sha256:33164093be11fcef3ce2571a0dccd9041c9a93fa3bde86569d7b03120d276c6f"}, + {file = "aiohttp-3.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:bdf70bfe5a1414ba9afb9d49f0c912dc524cf60141102f3a11143ba3d291870f"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d52d5dc7c6682b720280f9d9db41d36ebe4791622c842e258c9206232251ab2b"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4ac39027011414dbd3d87f7edb31680e1f430834c8cef029f11c66dad0670aa5"}, + {file = "aiohttp-3.8.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3f5c7ce535a1d2429a634310e308fb7d718905487257060e5d4598e29dc17f0b"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b30e963f9e0d52c28f284d554a9469af073030030cef8693106d918b2ca92f54"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:918810ef188f84152af6b938254911055a72e0f935b5fbc4c1a4ed0b0584aed1"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:002f23e6ea8d3dd8d149e569fd580c999232b5fbc601c48d55398fbc2e582e8c"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4fcf3eabd3fd1a5e6092d1242295fa37d0354b2eb2077e6eb670accad78e40e1"}, + {file = "aiohttp-3.8.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:255ba9d6d5ff1a382bb9a578cd563605aa69bec845680e21c44afc2670607a95"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d67f8baed00870aa390ea2590798766256f31dc5ed3ecc737debb6e97e2ede78"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:86f20cee0f0a317c76573b627b954c412ea766d6ada1a9fcf1b805763ae7feeb"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:39a312d0e991690ccc1a61f1e9e42daa519dcc34ad03eb6f826d94c1190190dd"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e827d48cf802de06d9c935088c2924e3c7e7533377d66b6f31ed175c1620e05e"}, + {file = "aiohttp-3.8.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bd111d7fc5591ddf377a408ed9067045259ff2770f37e2d94e6478d0f3fc0c17"}, + {file = "aiohttp-3.8.6-cp39-cp39-win32.whl", hash = "sha256:caf486ac1e689dda3502567eb89ffe02876546599bbf915ec94b1fa424eeffd4"}, + {file = "aiohttp-3.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:3f0e27e5b733803333bb2371249f41cf42bae8884863e8e8965ec69bebe53132"}, + {file = "aiohttp-3.8.6.tar.gz", hash = "sha256:b0cf2a4501bff9330a8a5248b4ce951851e415bdcce9dc158e76cfd55e15085c"}, +] + +[package.dependencies] +aiosignal = ">=1.1.2" +async-timeout = ">=4.0.0a3,<5.0" +attrs = ">=17.3.0" +charset-normalizer = ">=2.0,<4.0" +frozenlist = ">=1.1.1" +multidict = ">=4.5,<7.0" +yarl = ">=1.0,<2.0" + +[package.extras] +speedups = ["Brotli", "aiodns", "cchardet"] + +[[package]] +name = "aiosignal" +version = "1.3.1" +description = "aiosignal: a list of registered asynchronous callbacks" +optional = false +python-versions = ">=3.7" +files = [ + {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, + {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, +] + +[package.dependencies] +frozenlist = ">=1.1.0" + +[[package]] +name = "alembic" +version = "1.12.1" +description = "A database migration tool for SQLAlchemy." +optional = false +python-versions = ">=3.7" +files = [ + {file = "alembic-1.12.1-py3-none-any.whl", hash = "sha256:47d52e3dfb03666ed945becb723d6482e52190917fdb47071440cfdba05d92cb"}, + {file = "alembic-1.12.1.tar.gz", hash = "sha256:bca5877e9678b454706347bc10b97cb7d67f300320fa5c3a94423e8266e2823f"}, +] + +[package.dependencies] +importlib-metadata = {version = "*", markers = "python_version < \"3.9\""} +importlib-resources = {version = "*", markers = "python_version < \"3.9\""} +Mako = "*" +SQLAlchemy = ">=1.3.0" +typing-extensions = ">=4" + +[package.extras] +tz = ["python-dateutil"] + +[[package]] +name = "appdirs" +version = "1.4.4" +description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = "*" +files = [ + {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"}, + {file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"}, +] + +[[package]] +name = "async-timeout" +version = "4.0.3" +description = "Timeout context manager for asyncio programs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, + {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, +] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "cachetools" +version = "5.3.2" +description = "Extensible memoizing collections and decorators" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cachetools-5.3.2-py3-none-any.whl", hash = "sha256:861f35a13a451f94e301ce2bec7cac63e881232ccce7ed67fab9b5df4d3beaa1"}, + {file = "cachetools-5.3.2.tar.gz", hash = "sha256:086ee420196f7b2ab9ca2db2520aca326318b68fe5ba8bc4d49cca91add450f2"}, +] + +[[package]] +name = "catboost" +version = "1.2.2" +description = "CatBoost Python Package" +optional = false +python-versions = "*" +files = [ + {file = "catboost-1.2.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:806189e8491d3ba5f6a24875689da2f997c95a21d2d32e92144ea391882a75a0"}, + {file = "catboost-1.2.2-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:2108673d05c6e961a1298aea0c722d6c7a0acca112d6ec14cf01a274486af6af"}, + {file = "catboost-1.2.2-cp310-cp310-manylinux2014_x86_64.whl", hash = "sha256:0b17019ce42939a153895cd44430b50c49e3fa7ab65109f98c9a7df461359705"}, + {file = "catboost-1.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:dab0ad5f9dec575b7949ba58cc2ec029128d90611c45a6caa03f9d52d28f3420"}, + {file = "catboost-1.2.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:83f59b7526e5330a96d70f25e162c7a4ab9d9c9def234b48e325f1098c854c0f"}, + {file = "catboost-1.2.2-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:467b6e0064fe5a6aa7efc7f86a91dfe1266df91f623256db792095964b644d0e"}, + {file = "catboost-1.2.2-cp311-cp311-manylinux2014_x86_64.whl", hash = "sha256:db151f661305b13d81d460df1f01580085671a24a71300abbbe17dc8d1c152a0"}, + {file = "catboost-1.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:0b8b5cdc2f1e1452018867a55902dc440d8a67a0869d5258f59b290d917cd73a"}, + {file = "catboost-1.2.2-cp37-cp37m-macosx_11_0_universal2.whl", hash = "sha256:d82d2a2914a6dec8b95cc107d9b6686ad00b0177144561bce14e44ef4c91a488"}, + {file = "catboost-1.2.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:d2a281797abc6e6572621c4c99a3aded9ef32b25bfdbf7824021f84f9fbebd63"}, + {file = "catboost-1.2.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:d0f0e39ab9cb1e5287c785bc8a7448b2ebeff6257f4509693008043b8b24e53e"}, + {file = "catboost-1.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:7714aeef4c079592f64b5cb79e78c0b5c636784b41bca882f5ff6d8f4481c734"}, + {file = "catboost-1.2.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:aa758d5a3cb1c4a5f87d2399ccc7879b63f3db711fc34b1c285b5499c4112234"}, + {file = "catboost-1.2.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:6ad09ae45d69bc0ea8685cb92e6df8db1f99796392bb54ba588c2291890eea66"}, + {file = "catboost-1.2.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:7a57052030cb0a7b8cc1db98d6de3c00f864b6f36275bc0608d85f9ea04df751"}, + {file = "catboost-1.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:fb0a8902b78179d9008e608f57626195726cd7328ac052f1ee2e46663bb8f964"}, + {file = "catboost-1.2.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:2a7c3a081af1da25c3d25e3be249ac85a979c5dd4ab4fba5c4f5742b83c8b434"}, + {file = "catboost-1.2.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:85459ee572e3e81f4cbde76b9ba08c3a2c9c31586861947bdbe95dbc29672205"}, + {file = "catboost-1.2.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:f6f3ae50f84a177455d0739ae08333db4fe2642278a8c287be95f2d6cdc9cdf8"}, + {file = "catboost-1.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:1c0c3973542c5c46898c157a9f545ad80a36b8d8b17d92424a07376818911162"}, + {file = "catboost-1.2.2.tar.gz", hash = "sha256:c9381af807369fa6a24288a028eebbcfcec939c897ffd95729ca0f891d1d49c4"}, +] + +[package.dependencies] +graphviz = "*" +matplotlib = "*" +numpy = ">=1.16.0" +pandas = ">=0.24" +plotly = "*" +scipy = "*" +six = "*" + +[package.extras] +widget = ["ipython", "ipywidgets (>=7.0,<9.0)", "traitlets"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +description = "Validate configuration and produce human readable error messages." +optional = false +python-versions = ">=3.8" +files = [ + {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, + {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, +] + +[[package]] +name = "chardet" +version = "5.2.0" +description = "Universal encoding detector for Python 3" +optional = false +python-versions = ">=3.7" +files = [ + {file = "chardet-5.2.0-py3-none-any.whl", hash = "sha256:e1cf59446890a00105fe7b7912492ea04b6e6f06d4b742b2c788469e34c82970"}, + {file = "chardet-5.2.0.tar.gz", hash = "sha256:1b3b6ff479a8c414bc3fa2c0852995695c4a026dcd6d0633b2dd092ca39c1cf7"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.1" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.1.tar.gz", hash = "sha256:d9137a876020661972ca6eec0766d81aef8a5627df628b664b234b73396e727e"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8aee051c89e13565c6bd366813c386939f8e928af93c29fda4af86d25b73d8f8"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:352a88c3df0d1fa886562384b86f9a9e27563d4704ee0e9d56ec6fcd270ea690"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:223b4d54561c01048f657fa6ce41461d5ad8ff128b9678cfe8b2ecd951e3f8a2"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f861d94c2a450b974b86093c6c027888627b8082f1299dfd5a4bae8e2292821"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1171ef1fc5ab4693c5d151ae0fdad7f7349920eabbaca6271f95969fa0756c2d"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28f512b9a33235545fbbdac6a330a510b63be278a50071a336afc1b78781b147"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0e842112fe3f1a4ffcf64b06dc4c61a88441c2f02f373367f7b4c1aa9be2ad5"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f9bc2ce123637a60ebe819f9fccc614da1bcc05798bbbaf2dd4ec91f3e08846"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f194cce575e59ffe442c10a360182a986535fd90b57f7debfaa5c845c409ecc3"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:9a74041ba0bfa9bc9b9bb2cd3238a6ab3b7618e759b41bd15b5f6ad958d17605"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b578cbe580e3b41ad17b1c428f382c814b32a6ce90f2d8e39e2e635d49e498d1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6db3cfb9b4fcecb4390db154e75b49578c87a3b9979b40cdf90d7e4b945656e1"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:debb633f3f7856f95ad957d9b9c781f8e2c6303ef21724ec94bea2ce2fcbd056"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win32.whl", hash = "sha256:87071618d3d8ec8b186d53cb6e66955ef2a0e4fa63ccd3709c0c90ac5a43520f"}, + {file = "charset_normalizer-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:e372d7dfd154009142631de2d316adad3cc1c36c32a38b16a4751ba78da2a397"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ae4070f741f8d809075ef697877fd350ecf0b7c5837ed68738607ee0a2c572cf"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:58e875eb7016fd014c0eea46c6fa92b87b62c0cb31b9feae25cbbe62c919f54d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dbd95e300367aa0827496fe75a1766d198d34385a58f97683fe6e07f89ca3e3c"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de0b4caa1c8a21394e8ce971997614a17648f94e1cd0640fbd6b4d14cab13a72"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:985c7965f62f6f32bf432e2681173db41336a9c2611693247069288bcb0c7f8b"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a15c1fe6d26e83fd2e5972425a772cca158eae58b05d4a25a4e474c221053e2d"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae55d592b02c4349525b6ed8f74c692509e5adffa842e582c0f861751701a673"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be4d9c2770044a59715eb57c1144dedea7c5d5ae80c68fb9959515037cde2008"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:851cf693fb3aaef71031237cd68699dded198657ec1e76a76eb8be58c03a5d1f"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:31bbaba7218904d2eabecf4feec0d07469284e952a27400f23b6628439439fa7"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:871d045d6ccc181fd863a3cd66ee8e395523ebfbc57f85f91f035f50cee8e3d4"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:501adc5eb6cd5f40a6f77fbd90e5ab915c8fd6e8c614af2db5561e16c600d6f3"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f5fb672c396d826ca16a022ac04c9dce74e00a1c344f6ad1a0fdc1ba1f332213"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win32.whl", hash = "sha256:bb06098d019766ca16fc915ecaa455c1f1cd594204e7f840cd6258237b5079a8"}, + {file = "charset_normalizer-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:8af5a8917b8af42295e86b64903156b4f110a30dca5f3b5aedea123fbd638bff"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7ae8e5142dcc7a49168f4055255dbcced01dc1714a90a21f87448dc8d90617d1"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5b70bab78accbc672f50e878a5b73ca692f45f5b5e25c8066d748c09405e6a55"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ceca5876032362ae73b83347be8b5dbd2d1faf3358deb38c9c88776779b2e2f"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34d95638ff3613849f473afc33f65c401a89f3b9528d0d213c7037c398a51296"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9edbe6a5bf8b56a4a84533ba2b2f489d0046e755c29616ef8830f9e7d9cf5728"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6a02a3c7950cafaadcd46a226ad9e12fc9744652cc69f9e5534f98b47f3bbcf"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10b8dd31e10f32410751b3430996f9807fc4d1587ca69772e2aa940a82ab571a"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edc0202099ea1d82844316604e17d2b175044f9bcb6b398aab781eba957224bd"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b891a2f68e09c5ef989007fac11476ed33c5c9994449a4e2c3386529d703dc8b"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:71ef3b9be10070360f289aea4838c784f8b851be3ba58cf796262b57775c2f14"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:55602981b2dbf8184c098bc10287e8c245e351cd4fdcad050bd7199d5a8bf514"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:46fb9970aa5eeca547d7aa0de5d4b124a288b42eaefac677bde805013c95725c"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:520b7a142d2524f999447b3a0cf95115df81c4f33003c51a6ab637cbda9d0bf4"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win32.whl", hash = "sha256:8ec8ef42c6cd5856a7613dcd1eaf21e5573b2185263d87d27c8edcae33b62a61"}, + {file = "charset_normalizer-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:baec8148d6b8bd5cee1ae138ba658c71f5b03e0d69d5907703e3e1df96db5e41"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63a6f59e2d01310f754c270e4a257426fe5a591dc487f1983b3bbe793cf6bac6"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6bfc32a68bc0933819cfdfe45f9abc3cae3877e1d90aac7259d57e6e0f85b1"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f3100d86dcd03c03f7e9c3fdb23d92e32abbca07e7c13ebd7ddfbcb06f5991f"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:39b70a6f88eebe239fa775190796d55a33cfb6d36b9ffdd37843f7c4c1b5dc67"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e12f8ee80aa35e746230a2af83e81bd6b52daa92a8afaef4fea4a2ce9b9f4fa"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b6cefa579e1237ce198619b76eaa148b71894fb0d6bcf9024460f9bf30fd228"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:61f1e3fb621f5420523abb71f5771a204b33c21d31e7d9d86881b2cffe92c47c"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f6e2a839f83a6a76854d12dbebde50e4b1afa63e27761549d006fa53e9aa80e"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:1ec937546cad86d0dce5396748bf392bb7b62a9eeb8c66efac60e947697f0e58"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:82ca51ff0fc5b641a2d4e1cc8c5ff108699b7a56d7f3ad6f6da9dbb6f0145b48"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:633968254f8d421e70f91c6ebe71ed0ab140220469cf87a9857e21c16687c034"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win32.whl", hash = "sha256:c0c72d34e7de5604df0fde3644cc079feee5e55464967d10b24b1de268deceb9"}, + {file = "charset_normalizer-3.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:63accd11149c0f9a99e3bc095bbdb5a464862d77a7e309ad5938fbc8721235ae"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5a3580a4fdc4ac05f9e53c57f965e3594b2f99796231380adb2baaab96e22761"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2465aa50c9299d615d757c1c888bc6fef384b7c4aec81c05a0172b4400f98557"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:cb7cd68814308aade9d0c93c5bd2ade9f9441666f8ba5aa9c2d4b389cb5e2a45"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e43805ccafa0a91831f9cd5443aa34528c0c3f2cc48c4cb3d9a7721053874b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:854cc74367180beb327ab9d00f964f6d91da06450b0855cbbb09187bcdb02de5"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c15070ebf11b8b7fd1bfff7217e9324963c82dbdf6182ff7050519e350e7ad9f"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c4c99f98fc3a1835af8179dcc9013f93594d0670e2fa80c83aa36346ee763d2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fb765362688821404ad6cf86772fc54993ec11577cd5a92ac44b4c2ba52155b"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dced27917823df984fe0c80a5c4ad75cf58df0fbfae890bc08004cd3888922a2"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a66bcdf19c1a523e41b8e9d53d0cedbfbac2e93c649a2e9502cb26c014d0980c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ecd26be9f112c4f96718290c10f4caea6cc798459a3a76636b817a0ed7874e42"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f70fd716855cd3b855316b226a1ac8bdb3caf4f7ea96edcccc6f484217c9597"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:17a866d61259c7de1bdadef418a37755050ddb4b922df8b356503234fff7932c"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win32.whl", hash = "sha256:548eefad783ed787b38cb6f9a574bd8664468cc76d1538215d510a3cd41406cb"}, + {file = "charset_normalizer-3.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:45f053a0ece92c734d874861ffe6e3cc92150e32136dd59ab1fb070575189c97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bc791ec3fd0c4309a753f95bb6c749ef0d8ea3aea91f07ee1cf06b7b02118f2f"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0c8c61fb505c7dad1d251c284e712d4e0372cef3b067f7ddf82a7fa82e1e9a93"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2c092be3885a1b7899cd85ce24acedc1034199d6fca1483fa2c3a35c86e43041"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2000c54c395d9e5e44c99dc7c20a64dc371f777faf8bae4919ad3e99ce5253e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4cb50a0335382aac15c31b61d8531bc9bb657cfd848b1d7158009472189f3d62"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c30187840d36d0ba2893bc3271a36a517a717f9fd383a98e2697ee890a37c273"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe81b35c33772e56f4b6cf62cf4aedc1762ef7162a31e6ac7fe5e40d0149eb67"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0bf89afcbcf4d1bb2652f6580e5e55a840fdf87384f6063c4a4f0c95e378656"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:06cf46bdff72f58645434d467bf5228080801298fbba19fe268a01b4534467f5"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3c66df3f41abee950d6638adc7eac4730a306b022570f71dd0bd6ba53503ab57"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd805513198304026bd379d1d516afbf6c3c13f4382134a2c526b8b854da1c2e"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:9505dc359edb6a330efcd2be825fdb73ee3e628d9010597aa1aee5aa63442e97"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:31445f38053476a0c4e6d12b047b08ced81e2c7c712e5a1ad97bc913256f91b2"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win32.whl", hash = "sha256:bd28b31730f0e982ace8663d108e01199098432a30a4c410d06fe08fdb9e93f4"}, + {file = "charset_normalizer-3.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:555fe186da0068d3354cdf4bbcbc609b0ecae4d04c921cc13e209eece7720727"}, + {file = "charset_normalizer-3.3.1-py3-none-any.whl", hash = "sha256:800561453acdecedaac137bf09cd719c7a440b6800ec182f077bb8e7025fb708"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "colorlog" +version = "6.7.0" +description = "Add colours to the output of Python's logging module." +optional = false +python-versions = ">=3.6" +files = [ + {file = "colorlog-6.7.0-py2.py3-none-any.whl", hash = "sha256:0d33ca236784a1ba3ff9c532d4964126d8a2c44f1f0cb1d2b0728196f512f662"}, + {file = "colorlog-6.7.0.tar.gz", hash = "sha256:bd94bd21c1e13fac7bd3153f4bc3a7dc0eb0974b8bc2fdf1a989e474f6e582e5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +development = ["black", "flake8", "mypy", "pytest", "types-colorama"] + +[[package]] +name = "contourpy" +version = "1.1.0" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.8" +files = [ + {file = "contourpy-1.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:89f06eff3ce2f4b3eb24c1055a26981bffe4e7264acd86f15b97e40530b794bc"}, + {file = "contourpy-1.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dffcc2ddec1782dd2f2ce1ef16f070861af4fb78c69862ce0aab801495dda6a3"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25ae46595e22f93592d39a7eac3d638cda552c3e1160255258b695f7b58e5655"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:17cfaf5ec9862bc93af1ec1f302457371c34e688fbd381f4035a06cd47324f48"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18a64814ae7bce73925131381603fff0116e2df25230dfc80d6d690aa6e20b37"}, + {file = "contourpy-1.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c81f22b4f572f8a2110b0b741bb64e5a6427e0a198b2cdc1fbaf85f352a3aa"}, + {file = "contourpy-1.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:53cc3a40635abedbec7f1bde60f8c189c49e84ac180c665f2cd7c162cc454baa"}, + {file = "contourpy-1.1.0-cp310-cp310-win32.whl", hash = "sha256:9b2dd2ca3ac561aceef4c7c13ba654aaa404cf885b187427760d7f7d4c57cff8"}, + {file = "contourpy-1.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:1f795597073b09d631782e7245016a4323cf1cf0b4e06eef7ea6627e06a37ff2"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0b7b04ed0961647691cfe5d82115dd072af7ce8846d31a5fac6c142dcce8b882"}, + {file = "contourpy-1.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:27bc79200c742f9746d7dd51a734ee326a292d77e7d94c8af6e08d1e6c15d545"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052cc634bf903c604ef1a00a5aa093c54f81a2612faedaa43295809ffdde885e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9382a1c0bc46230fb881c36229bfa23d8c303b889b788b939365578d762b5c18"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e5cec36c5090e75a9ac9dbd0ff4a8cf7cecd60f1b6dc23a374c7d980a1cd710e"}, + {file = "contourpy-1.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0cbd657e9bde94cd0e33aa7df94fb73c1ab7799378d3b3f902eb8eb2e04a3a"}, + {file = "contourpy-1.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:181cbace49874f4358e2929aaf7ba84006acb76694102e88dd15af861996c16e"}, + {file = "contourpy-1.1.0-cp311-cp311-win32.whl", hash = "sha256:edb989d31065b1acef3828a3688f88b2abb799a7db891c9e282df5ec7e46221b"}, + {file = "contourpy-1.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fb3b7d9e6243bfa1efb93ccfe64ec610d85cfe5aec2c25f97fbbd2e58b531256"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bcb41692aa09aeb19c7c213411854402f29f6613845ad2453d30bf421fe68fed"}, + {file = "contourpy-1.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5d123a5bc63cd34c27ff9c7ac1cd978909e9c71da12e05be0231c608048bb2ae"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62013a2cf68abc80dadfd2307299bfa8f5aa0dcaec5b2954caeb5fa094171103"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b6616375d7de55797d7a66ee7d087efe27f03d336c27cf1f32c02b8c1a5ac70"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:317267d915490d1e84577924bd61ba71bf8681a30e0d6c545f577363157e5e94"}, + {file = "contourpy-1.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d551f3a442655f3dcc1285723f9acd646ca5858834efeab4598d706206b09c9f"}, + {file = "contourpy-1.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7a117ce7df5a938fe035cad481b0189049e8d92433b4b33aa7fc609344aafa1"}, + {file = "contourpy-1.1.0-cp38-cp38-win32.whl", hash = "sha256:108dfb5b3e731046a96c60bdc46a1a0ebee0760418951abecbe0fc07b5b93b27"}, + {file = "contourpy-1.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:d4f26b25b4f86087e7d75e63212756c38546e70f2a92d2be44f80114826e1cd4"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc00bb4225d57bff7ebb634646c0ee2a1298402ec10a5fe7af79df9a51c1bfd9"}, + {file = "contourpy-1.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:189ceb1525eb0655ab8487a9a9c41f42a73ba52d6789754788d1883fb06b2d8a"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f2931ed4741f98f74b410b16e5213f71dcccee67518970c42f64153ea9313b9"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f511c05fab7f12e0b1b7730ebdc2ec8deedcfb505bc27eb570ff47c51a8f15"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:143dde50520a9f90e4a2703f367cf8ec96a73042b72e68fcd184e1279962eb6f"}, + {file = "contourpy-1.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e94bef2580e25b5fdb183bf98a2faa2adc5b638736b2c0a4da98691da641316a"}, + {file = "contourpy-1.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ed614aea8462735e7d70141374bd7650afd1c3f3cb0c2dbbcbe44e14331bf002"}, + {file = "contourpy-1.1.0-cp39-cp39-win32.whl", hash = "sha256:71551f9520f008b2950bef5f16b0e3587506ef4f23c734b71ffb7b89f8721999"}, + {file = "contourpy-1.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:438ba416d02f82b692e371858143970ed2eb6337d9cdbbede0d8ad9f3d7dd17d"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a698c6a7a432789e587168573a864a7ea374c6be8d4f31f9d87c001d5a843493"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:397b0ac8a12880412da3551a8cb5a187d3298a72802b45a3bd1805e204ad8439"}, + {file = "contourpy-1.1.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a67259c2b493b00e5a4d0f7bfae51fb4b3371395e47d079a4446e9b0f4d70e76"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2b836d22bd2c7bb2700348e4521b25e077255ebb6ab68e351ab5aa91ca27e027"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084eaa568400cfaf7179b847ac871582199b1b44d5699198e9602ecbbb5f6104"}, + {file = "contourpy-1.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:911ff4fd53e26b019f898f32db0d4956c9d227d51338fb3b03ec72ff0084ee5f"}, + {file = "contourpy-1.1.0.tar.gz", hash = "sha256:e53046c3863828d21d531cc3b53786e6580eb1ba02477e8681009b6aa0870b21"}, +] + +[package.dependencies] +numpy = ">=1.16" + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.2.0)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] + +[[package]] +name = "contourpy" +version = "1.1.1" +description = "Python library for calculating contours of 2D quadrilateral grids" +optional = false +python-versions = ">=3.8" +files = [ + {file = "contourpy-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:46e24f5412c948d81736509377e255f6040e94216bf1a9b5ea1eaa9d29f6ec1b"}, + {file = "contourpy-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e48694d6a9c5a26ee85b10130c77a011a4fedf50a7279fa0bdaf44bafb4299d"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a66045af6cf00e19d02191ab578a50cb93b2028c3eefed999793698e9ea768ae"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ebf42695f75ee1a952f98ce9775c873e4971732a87334b099dde90b6af6a916"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6aec19457617ef468ff091669cca01fa7ea557b12b59a7908b9474bb9674cf0"}, + {file = "contourpy-1.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:462c59914dc6d81e0b11f37e560b8a7c2dbab6aca4f38be31519d442d6cde1a1"}, + {file = "contourpy-1.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6d0a8efc258659edc5299f9ef32d8d81de8b53b45d67bf4bfa3067f31366764d"}, + {file = "contourpy-1.1.1-cp310-cp310-win32.whl", hash = "sha256:d6ab42f223e58b7dac1bb0af32194a7b9311065583cc75ff59dcf301afd8a431"}, + {file = "contourpy-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:549174b0713d49871c6dee90a4b499d3f12f5e5f69641cd23c50a4542e2ca1eb"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:407d864db716a067cc696d61fa1ef6637fedf03606e8417fe2aeed20a061e6b2"}, + {file = "contourpy-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:dfe80c017973e6a4c367e037cb31601044dd55e6bfacd57370674867d15a899b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e30aaf2b8a2bac57eb7e1650df1b3a4130e8d0c66fc2f861039d507a11760e1b"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3de23ca4f381c3770dee6d10ead6fff524d540c0f662e763ad1530bde5112532"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:566f0e41df06dfef2431defcfaa155f0acfa1ca4acbf8fd80895b1e7e2ada40e"}, + {file = "contourpy-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b04c2f0adaf255bf756cf08ebef1be132d3c7a06fe6f9877d55640c5e60c72c5"}, + {file = "contourpy-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d0c188ae66b772d9d61d43c6030500344c13e3f73a00d1dc241da896f379bb62"}, + {file = "contourpy-1.1.1-cp311-cp311-win32.whl", hash = "sha256:0683e1ae20dc038075d92e0e0148f09ffcefab120e57f6b4c9c0f477ec171f33"}, + {file = "contourpy-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:8636cd2fc5da0fb102a2504fa2c4bea3cbc149533b345d72cdf0e7a924decc45"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:560f1d68a33e89c62da5da4077ba98137a5e4d3a271b29f2f195d0fba2adcb6a"}, + {file = "contourpy-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:24216552104ae8f3b34120ef84825400b16eb6133af2e27a190fdc13529f023e"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56de98a2fb23025882a18b60c7f0ea2d2d70bbbcfcf878f9067234b1c4818442"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:07d6f11dfaf80a84c97f1a5ba50d129d9303c5b4206f776e94037332e298dda8"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f1eaac5257a8f8a047248d60e8f9315c6cff58f7803971170d952555ef6344a7"}, + {file = "contourpy-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19557fa407e70f20bfaba7d55b4d97b14f9480856c4fb65812e8a05fe1c6f9bf"}, + {file = "contourpy-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:081f3c0880712e40effc5f4c3b08feca6d064cb8cfbb372ca548105b86fd6c3d"}, + {file = "contourpy-1.1.1-cp312-cp312-win32.whl", hash = "sha256:059c3d2a94b930f4dafe8105bcdc1b21de99b30b51b5bce74c753686de858cb6"}, + {file = "contourpy-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:f44d78b61740e4e8c71db1cf1fd56d9050a4747681c59ec1094750a658ceb970"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:70e5a10f8093d228bb2b552beeb318b8928b8a94763ef03b858ef3612b29395d"}, + {file = "contourpy-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8394e652925a18ef0091115e3cc191fef350ab6dc3cc417f06da66bf98071ae9"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5bd5680f844c3ff0008523a71949a3ff5e4953eb7701b28760805bc9bcff217"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:66544f853bfa85c0d07a68f6c648b2ec81dafd30f272565c37ab47a33b220684"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0c02b75acfea5cab07585d25069207e478d12309557f90a61b5a3b4f77f46ce"}, + {file = "contourpy-1.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41339b24471c58dc1499e56783fedc1afa4bb018bcd035cfb0ee2ad2a7501ef8"}, + {file = "contourpy-1.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f29fb0b3f1217dfe9362ec55440d0743fe868497359f2cf93293f4b2701b8251"}, + {file = "contourpy-1.1.1-cp38-cp38-win32.whl", hash = "sha256:f9dc7f933975367251c1b34da882c4f0e0b2e24bb35dc906d2f598a40b72bfc7"}, + {file = "contourpy-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:498e53573e8b94b1caeb9e62d7c2d053c263ebb6aa259c81050766beb50ff8d9"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ba42e3810999a0ddd0439e6e5dbf6d034055cdc72b7c5c839f37a7c274cb4eba"}, + {file = "contourpy-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c06e4c6e234fcc65435223c7b2a90f286b7f1b2733058bdf1345d218cc59e34"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca6fab080484e419528e98624fb5c4282148b847e3602dc8dbe0cb0669469887"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93df44ab351119d14cd1e6b52a5063d3336f0754b72736cc63db59307dabb718"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eafbef886566dc1047d7b3d4b14db0d5b7deb99638d8e1be4e23a7c7ac59ff0f"}, + {file = "contourpy-1.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efe0fab26d598e1ec07d72cf03eaeeba8e42b4ecf6b9ccb5a356fde60ff08b85"}, + {file = "contourpy-1.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f08e469821a5e4751c97fcd34bcb586bc243c39c2e39321822060ba902eac49e"}, + {file = "contourpy-1.1.1-cp39-cp39-win32.whl", hash = "sha256:bfc8a5e9238232a45ebc5cb3bfee71f1167064c8d382cadd6076f0d51cff1da0"}, + {file = "contourpy-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:c84fdf3da00c2827d634de4fcf17e3e067490c4aea82833625c4c8e6cdea0887"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:229a25f68046c5cf8067d6d6351c8b99e40da11b04d8416bf8d2b1d75922521e"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a10dab5ea1bd4401c9483450b5b0ba5416be799bbd50fc7a6cc5e2a15e03e8a3"}, + {file = "contourpy-1.1.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:4f9147051cb8fdb29a51dc2482d792b3b23e50f8f57e3720ca2e3d438b7adf23"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a75cc163a5f4531a256f2c523bd80db509a49fc23721b36dd1ef2f60ff41c3cb"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b53d5769aa1f2d4ea407c65f2d1d08002952fac1d9e9d307aa2e1023554a163"}, + {file = "contourpy-1.1.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11b836b7dbfb74e049c302bbf74b4b8f6cb9d0b6ca1bf86cfa8ba144aedadd9c"}, + {file = "contourpy-1.1.1.tar.gz", hash = "sha256:96ba37c2e24b7212a77da85004c38e7c4d155d3e72a45eeaf22c1f03f607e8ab"}, +] + +[package.dependencies] +numpy = {version = ">=1.16,<2.0", markers = "python_version <= \"3.11\""} + +[package.extras] +bokeh = ["bokeh", "selenium"] +docs = ["furo", "sphinx (>=7.2)", "sphinx-copybutton"] +mypy = ["contourpy[bokeh,docs]", "docutils-stubs", "mypy (==1.4.1)", "types-Pillow"] +test = ["Pillow", "contourpy[test-no-images]", "matplotlib"] +test-no-images = ["pytest", "pytest-cov", "wurlitzer"] + +[[package]] +name = "coverage" +version = "7.3.2" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"}, + {file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"}, + {file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"}, + {file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"}, + {file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"}, + {file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"}, + {file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"}, + {file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"}, + {file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"}, + {file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"}, + {file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"}, + {file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"}, + {file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"}, + {file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"}, + {file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"}, + {file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"}, + {file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"}, + {file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"}, + {file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"}, + {file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"}, + {file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"}, + {file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"}, + {file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"}, + {file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"}, + {file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"}, + {file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"}, + {file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"}, + {file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cramjam" +version = "2.7.0" +description = "Thin Python bindings to de/compression algorithms in Rust" +optional = false +python-versions = ">=3.7" +files = [ + {file = "cramjam-2.7.0-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:aac9d49e16f473ceb4eaf74a53180eac3363127f01855c39122b400a988e80bf"}, + {file = "cramjam-2.7.0-cp310-cp310-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:a08dcb7c7b54f82db4ee9120aaace06326499c0d4108770ee7ac63d7bd1d803d"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5c411d785cec410d4164e4ecc76b6c152761fbb61325bcc4acbdc8926874c0b"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d07c5af763501bd23523658aeb535082eaac014746f7973df85f76b0d9b40967"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7f93316abc1abfd348b04afc6cadbbd4fba44cd91e7b9803c9330045a7a1885"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d56afb5f278a18743a218514825b6ab176f18a4084d8f6515c64e3acef19478"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ea1c781d3760df0b6ad80b7b19dc8e038e0638fb1cfabc68da96cedb8d0adca"}, + {file = "cramjam-2.7.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f3544ea95d0e98ac926d92d652adc417e78091117cbe2ef7733e26c40601604c"}, + {file = "cramjam-2.7.0-cp310-none-win32.whl", hash = "sha256:0ffb891294e77f2a3b0137992ebd6eb9b1f1bc3728d7d4314632e30270855117"}, + {file = "cramjam-2.7.0-cp310-none-win_amd64.whl", hash = "sha256:79c36d95e89b43c29595c889c7a4d30d29aefc55d7c58a26a058b9bbe7abd5cf"}, + {file = "cramjam-2.7.0-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:71bf6a6632648333c402a8692fe61f45416066eb0d8b7f4530cdf37fee221a11"}, + {file = "cramjam-2.7.0-cp311-cp311-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bee04fd1cdd5f2a2e91e4b271f22e228c698fe7b7f8ef209374d717f7889e80c"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60951e64d3e05ef2a46d2a92fc4e4563ae5e28bb3b6f231f2dca68a5078a72dc"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e6231fd3ac680c34c0d8405abfa8c3d12f92e28d0897d960aa905f053cc09e63"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2602c42ed101ada634fa37253d40946f0468b2b749689781cba715a7d78038e"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbc59b223750a901d65d96333461ab17076594fa34448ed2ef911bd4b628f068"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fab800ed93fb129d85c63f26660b695fb194efb29765a163f269321778e28a8d"}, + {file = "cramjam-2.7.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b48b11c328d91250dadc63c00753f5ba26eb9df5fe75ba2ce8a78631260479d"}, + {file = "cramjam-2.7.0-cp311-none-win32.whl", hash = "sha256:bef07e7d4607c4d70627e58eb630fe60e48b80a61ab05b33314e3296eb90af78"}, + {file = "cramjam-2.7.0-cp311-none-win_amd64.whl", hash = "sha256:3f2e41dc8143d0e88ec9ba3ff66c8d2aea486b04931119abe9e394f9961d74bc"}, + {file = "cramjam-2.7.0-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8e82276b120000834af3f776cbe22ac3016cd9e0ed00e7f3fb31e2ce95e17181"}, + {file = "cramjam-2.7.0-cp312-cp312-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:2b5a463b01d8867f78a361defb4fadca63635965e8204f7e2409b717d85f0c1d"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b84565611f36ee8c3944b96bb01ee4d44c101acf84f1430c9414986ab3a7fb03"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3cd45d09229960a89e0e3bbf71d29ac399391446f51279f3202846d7da106eb7"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4bb065d054e49645414bc84eaa49a6b7ed6c7185fb8ba2648c518344cf481144"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9a3f45cd17730c00358643a814d5921a31c8a0d238582e08594fa86fdbc8401c"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bf4ec082a7647ed7463c5e0bd176850a9f013c258ad98f53055bcd1716c7fac"}, + {file = "cramjam-2.7.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9f9e403be6307e98a47cc7d0132fe1fe4683c873c5d7d9da099fbac9c299a4b0"}, + {file = "cramjam-2.7.0-cp312-none-win32.whl", hash = "sha256:fd2e81c69baacb95fa28cdf844f714d7c03f0c805f4fa2decc5e9565e6b4405d"}, + {file = "cramjam-2.7.0-cp312-none-win_amd64.whl", hash = "sha256:831951a3eccebd5911387e3fff14483747d3dae5ad496afbd50447ffe2d03dba"}, + {file = "cramjam-2.7.0-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:d143ccb3f5aae640f0c2dd6244d43f5e5e81d847b50c2eb9f08dcc3dc33f367a"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47ae97247a58d3095be800420bba7e43cc6958e67f9dfddd12decdb4c99c4d6f"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a8f0fd14bd11f2a625e5c554fd93c7775082c31ffd9fbabb4fe9db3031645d0"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:89b683919ffc846b91b405d5f14df8a2ba1167f4ed9277150298fbe91a3d4aae"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:66d6a7906fbe8c2e46e987d5a3a9cb235e931b3e4721ac7d8573151c419e3f73"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:272ab041e95e4088321bffd63ead85d32f86f9fc79f37944663abb59e7fecbb1"}, + {file = "cramjam-2.7.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9698ed7fe78b4de81dcee0624311ee93a4436f0b3e3c6b147a6745a3fd210272"}, + {file = "cramjam-2.7.0-cp37-none-win32.whl", hash = "sha256:5e3869a2ecb7764f18e81afa07aa15a6f28921ae4508ab002314aafecfe7a285"}, + {file = "cramjam-2.7.0-cp37-none-win_amd64.whl", hash = "sha256:58bf5b4dd8f1edaa3bd66b51a26790115efa36cebf66a198a60d095739010b36"}, + {file = "cramjam-2.7.0-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:1bfd9e9f050a4ef82644a5443742bd6e4d41afc201d5142dfbb5ac73a4f96b94"}, + {file = "cramjam-2.7.0-cp38-cp38-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:e8b8b968db6a6ec03de231ca17536f8cd69d74e36f0e47e68391a22231c0042c"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:820421600d395d0e11b9da1e983acde453637090f5a15abb45f5182cd35f9c3a"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f8d684a8b918e289bd213d55ea5f67dbf6cc379492e2a7e094724ec62846dea"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4f48e35701528beed092d97c5a1a6ba6c8902c3485d7e3a55c463162bb66afa0"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:241b9853de56524895c17541d34bdcdd316261247253cb9faeb57a21cc2ae28c"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b0fa1f8600fdf093a4e5eac5dc56084047abec50d589a8121618e3fb1f9de3f"}, + {file = "cramjam-2.7.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:01573d3c05f75845af75f87d9f6d4d995ee48fafc9c9662679d944c71e658c59"}, + {file = "cramjam-2.7.0-cp38-none-win32.whl", hash = "sha256:44e262f083a0d1c19bc7b8bf8aaa54d31653eab67762cdaeb68fb40b844d50b9"}, + {file = "cramjam-2.7.0-cp38-none-win_amd64.whl", hash = "sha256:2645f0e01735231e3c4d1568c95cc00ed477c1c2e2ed45cb123bef2ccbe72282"}, + {file = "cramjam-2.7.0-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:f52718e1c7aed3d0e3ffbbe5c085d9c449daa726379788ddb27cb62ffc2b6ba1"}, + {file = "cramjam-2.7.0-cp39-cp39-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:ee4bc46e5cf87d6097833bca33a66f2724b4773242a71ed642d13682fedefb71"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd77e784289fc44a5e6487b2e263f07cc271f25a8395e97213b6a934fe47a768"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53ac8df43546d3f70acbc5c17424a8c083418bd6d2cacfbd5108aaa8f3eb26db"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ca6309d06edf29a9a5c22e25d1d7f7609abb8ae7281583bc486afb19fd645898"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96ff622f0db7f89d7c9aeadd9cc0c9bf61e804841a03a22ca919aa4955640d"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc87176851c50c5aaf6bacafb6bed5a86e3b4ee6a749d6ec13f3d37ae0e951a"}, + {file = "cramjam-2.7.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f9340c70d95ea102cf51a07ecc09f93f1363e585d97b5276734a5f8c4476e560"}, + {file = "cramjam-2.7.0-cp39-none-win32.whl", hash = "sha256:3d5ed0fa20b42e063ef66ad01d9948e868bbfc327bf86604e078b67f074f76f3"}, + {file = "cramjam-2.7.0-cp39-none-win_amd64.whl", hash = "sha256:7e44dda432a8c8a47cb73869201d2f9777604bd913d859def84c659fb736cfd3"}, + {file = "cramjam-2.7.0-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:22927dbdda85d8719074e061f9ec024c9bf16088e5e4c6c1c134c46e2d9153b7"}, + {file = "cramjam-2.7.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee80ebd85acec1031e7563cce3de3961bd3f2ec8947c5bf84a9356b25af67a75"}, + {file = "cramjam-2.7.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91bb03ca0d3857f319afd13525d5c6214a55aa49778ce46a02c16f0eee37907c"}, + {file = "cramjam-2.7.0-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:202e4a5a496ea49d0bb5252fbee8b6e421d256968773c7a8b3e86d98eec9228e"}, + {file = "cramjam-2.7.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19c44de9dee2ea0c586a5b12adc9bc28224544717bce88a94c3ee202b9ece25d"}, + {file = "cramjam-2.7.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03a72a689c93b8a2c7c08b529c1224c47bd469722e559af231016694b90f6442"}, + {file = "cramjam-2.7.0-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:fbffb1f63edf4cb4272a25de288c2f2e20914bb93e003883656774e61794b960"}, + {file = "cramjam-2.7.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df46019cb999d874ce86e08d71d7d2983c052d6a63f7aa6bce960e4e05e8ea37"}, + {file = "cramjam-2.7.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44fe99233ef2f42ff03d8395e7d97e0c45306eb356f6f01fa69bdb49783fdb8a"}, + {file = "cramjam-2.7.0.tar.gz", hash = "sha256:579fb724eec048b1a18ca8f7ad9a7ef296dc02eba5f87fd4d5031f0c32c5c9ac"}, +] + +[package.extras] +dev = ["black (==22.3.0)", "hypothesis", "numpy", "pytest (>=5.30)", "pytest-xdist"] + +[[package]] +name = "cycler" +version = "0.12.1" +description = "Composable style cycles" +optional = false +python-versions = ">=3.8" +files = [ + {file = "cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30"}, + {file = "cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c"}, +] + +[package.extras] +docs = ["ipython", "matplotlib", "numpydoc", "sphinx"] +tests = ["pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "decorator" +version = "5.1.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.5" +files = [ + {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, + {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, +] + +[[package]] +name = "distlib" +version = "0.3.7" +description = "Distribution utilities" +optional = false +python-versions = "*" +files = [ + {file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"}, + {file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"}, +] + +[[package]] +name = "docker-pycreds" +version = "0.4.0" +description = "Python bindings for the docker credentials store API" +optional = false +python-versions = "*" +files = [ + {file = "docker-pycreds-0.4.0.tar.gz", hash = "sha256:6ce3270bcaf404cc4c3e27e4b6c70d3521deae82fb508767870fdbf772d584d4"}, + {file = "docker_pycreds-0.4.0-py2.py3-none-any.whl", hash = "sha256:7266112468627868005106ec19cd0d722702d2b7d5912a28e19b826c3d37af49"}, +] + +[package.dependencies] +six = ">=1.4.0" + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fastparquet" +version = "2023.10.1" +description = "Python support for Parquet file format" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fastparquet-2023.10.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:75a00475e96d26214dace147b27ab782da7a0ae230cade05ea9181c3aec2e637"}, + {file = "fastparquet-2023.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:af0c1d5559aa0a4fff8eb3b301c8177b6813bb15fe9d2007ad0dc89f8fa519c5"}, + {file = "fastparquet-2023.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b798cdfa8f01cd573b135a493a4d0686ebbcd3a412d6e59889a7ae41ff90efeb"}, + {file = "fastparquet-2023.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a746f521da7459707899fc33b334b2d21f590380f472fc27642f3ef28ee451d2"}, + {file = "fastparquet-2023.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e86d64898e846ed0f5745427436e5772fd7bb5d9a930f1dca8233e90385e126b"}, + {file = "fastparquet-2023.10.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5c3afafd4a0907216f5ee4f835f47ad16b84c5dede4c5ca4c0754dffe3eb72d7"}, + {file = "fastparquet-2023.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68d26a1172be5b02018f6c28603f195807955d8262b913349385d977f3ae081f"}, + {file = "fastparquet-2023.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:b7086ca3a0d8ae8680b380da9b7057a1491d629945b1dd228eba5b362e2e39aa"}, + {file = "fastparquet-2023.10.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7f8d53f5e5049b21893964cd27154c2a7c8180f3ffd1f2693f80e0f834a3a35e"}, + {file = "fastparquet-2023.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea74f28494fda892641a564f728d046a074fdea5b9ff664ef9554c0da563bad4"}, + {file = "fastparquet-2023.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ab978612d21630033df0a0b12423ed826fe36e83a1710b155968c3c6e2b3174a"}, + {file = "fastparquet-2023.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc30c502feaa67c058c496eb4a734eba8bd373f0d24a32cc69360c79f7220ef"}, + {file = "fastparquet-2023.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99568ae6bbbd973b32d796cb664ba156b101e5d1931dba780fe2dc0d9b227dfd"}, + {file = "fastparquet-2023.10.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:53b9ad8d646c2609854cbe7d7b17be343664cabae1cd0eb119011e389df8484d"}, + {file = "fastparquet-2023.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2a9ee49039223a1e216c409c25072be1f362de27197cbec5f90cf2e736df3b0"}, + {file = "fastparquet-2023.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:9133d2f975c6e05187be4b558060e6a4aafeba02dceaf849cf6ad46d32e59405"}, + {file = "fastparquet-2023.10.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b826696cd48f1defb6fcafb4c9798102233e54f3f3491251c034dde3d94f420a"}, + {file = "fastparquet-2023.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bf2d58bee17e0eea8565c2bcd2b339ee032472751651e21f000eb564ad3cd5cf"}, + {file = "fastparquet-2023.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9296098d06c6692ee477fe491381eda39fc0dcfe2fce210496491fe16ce27ef8"}, + {file = "fastparquet-2023.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c975d648ea491e684135e9e3c0a15b440d66d0772fe497269e5c9c4eaaeb62a2"}, + {file = "fastparquet-2023.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4c5208db1f38c8ac5f50f309f77bdb828fa7f247b82e2df88d847ad3bec38903"}, + {file = "fastparquet-2023.10.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:118d1832ed2098f313936044012083c8c1b07da85ee11612895f3c4ef27bfd8a"}, + {file = "fastparquet-2023.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:35cff597d2778b6fe8ef7dc36cba056cd7337151dbfc2fb08abaa6b109c75140"}, + {file = "fastparquet-2023.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2da633a0bd1889f30acb1b6dffa99832739802d0ae5f455b4e5eb720ab701e09"}, + {file = "fastparquet-2023.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8aff041900ebcb4c2510bede80695fed35fb7c24dfd83b60ba8b56d7ede4e0fe"}, + {file = "fastparquet-2023.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62aabf43b6bbbc074b89f9a4769f7276204b6585d2d8fae770a0b782da5b9fc9"}, + {file = "fastparquet-2023.10.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ba85d9e5c298515a347f94bc65c0b570391b344d765dc349bafb35137466ddb2"}, + {file = "fastparquet-2023.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2be7d33969e724c8aa777122d6032845a362cb2075f6e6f2c5b2150bd6223cc8"}, + {file = "fastparquet-2023.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:2a0c1f485d3085fe98dbae9ead2e97a886deb99d3db7af635296bfd3f4f2f814"}, + {file = "fastparquet-2023.10.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1fac5319aabcbc4acc2feb5df68336de755de7d60a2ee9329fef178ac016e236"}, + {file = "fastparquet-2023.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c61d26705e9a2ad2d52ed1d527c75e96e6a9a04be35bd4c8d6f4accd778f9b05"}, + {file = "fastparquet-2023.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2635f0f37a983e35be9b8013b84361e3d0cdd4f514b822016445c029b1c6e007"}, + {file = "fastparquet-2023.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cde8f6798d37e2af38ada058fc7018c2157d90a8dd728c0c59fab85b8adb9215"}, + {file = "fastparquet-2023.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20c17c5e7186723a175c9e7da94285bdef3cb477cb7cca0e2812b1e245279671"}, + {file = "fastparquet-2023.10.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:91ee6b5b0efc18586e61da6662119de92fc7bf552c3a08a13eb2af16bc12f16a"}, + {file = "fastparquet-2023.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:332cb3b204e1de64dcfc4c5d0b517ea665856d19c139f693e8c9efc11992e19e"}, + {file = "fastparquet-2023.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:5eb06a70daf50d70290b87f3a5ca6f25eb24ad850bcc68197b5438d92b11c763"}, + {file = "fastparquet-2023.10.1.tar.gz", hash = "sha256:076fedfba2b56782b4823c1d351424425cfeaa5b8644c542416ca1363fe6d921"}, +] + +[package.dependencies] +cramjam = ">=2.3" +fsspec = "*" +numpy = ">=1.20.3" +packaging = "*" +pandas = ">=1.5.0" + +[package.extras] +lzo = ["python-lzo"] + +[[package]] +name = "filelock" +version = "3.13.0" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.8" +files = [ + {file = "filelock-3.13.0-py3-none-any.whl", hash = "sha256:a552f4fde758f4eab33191e9548f671970f8b06d436d31388c9aa1e5861a710f"}, + {file = "filelock-3.13.0.tar.gz", hash = "sha256:63c6052c82a1a24c873a549fbd39a26982e8f35a3016da231ead11a5be9dad44"}, +] + +[package.extras] +docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +typing = ["typing-extensions (>=4.8)"] + +[[package]] +name = "fonttools" +version = "4.43.1" +description = "Tools to manipulate font files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fonttools-4.43.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bf11e2cca121df35e295bd34b309046c29476ee739753bc6bc9d5050de319273"}, + {file = "fonttools-4.43.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:10b3922875ffcba636674f406f9ab9a559564fdbaa253d66222019d569db869c"}, + {file = "fonttools-4.43.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f727c3e3d08fd25352ed76cc3cb61486f8ed3f46109edf39e5a60fc9fecf6ca"}, + {file = "fonttools-4.43.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad0b3f6342cfa14be996971ea2b28b125ad681c6277c4cd0fbdb50340220dfb6"}, + {file = "fonttools-4.43.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b7ad05b2beeebafb86aa01982e9768d61c2232f16470f9d0d8e385798e37184"}, + {file = "fonttools-4.43.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4c54466f642d2116686268c3e5f35ebb10e49b0d48d41a847f0e171c785f7ac7"}, + {file = "fonttools-4.43.1-cp310-cp310-win32.whl", hash = "sha256:1e09da7e8519e336239fbd375156488a4c4945f11c4c5792ee086dd84f784d02"}, + {file = "fonttools-4.43.1-cp310-cp310-win_amd64.whl", hash = "sha256:1cf9e974f63b1080b1d2686180fc1fbfd3bfcfa3e1128695b5de337eb9075cef"}, + {file = "fonttools-4.43.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:5db46659cfe4e321158de74c6f71617e65dc92e54980086823a207f1c1c0e24b"}, + {file = "fonttools-4.43.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1952c89a45caceedf2ab2506d9a95756e12b235c7182a7a0fff4f5e52227204f"}, + {file = "fonttools-4.43.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c36da88422e0270fbc7fd959dc9749d31a958506c1d000e16703c2fce43e3d0"}, + {file = "fonttools-4.43.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bbbf8174501285049e64d174e29f9578495e1b3b16c07c31910d55ad57683d8"}, + {file = "fonttools-4.43.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d4071bd1c183b8d0b368cc9ed3c07a0f6eb1bdfc4941c4c024c49a35429ac7cd"}, + {file = "fonttools-4.43.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d21099b411e2006d3c3e1f9aaf339e12037dbf7bf9337faf0e93ec915991f43b"}, + {file = "fonttools-4.43.1-cp311-cp311-win32.whl", hash = "sha256:b84a1c00f832feb9d0585ca8432fba104c819e42ff685fcce83537e2e7e91204"}, + {file = "fonttools-4.43.1-cp311-cp311-win_amd64.whl", hash = "sha256:9a2f0aa6ca7c9bc1058a9d0b35483d4216e0c1bbe3962bc62ce112749954c7b8"}, + {file = "fonttools-4.43.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4d9740e3783c748521e77d3c397dc0662062c88fd93600a3c2087d3d627cd5e5"}, + {file = "fonttools-4.43.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:884ef38a5a2fd47b0c1291647b15f4e88b9de5338ffa24ee52c77d52b4dfd09c"}, + {file = "fonttools-4.43.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9648518ef687ba818db3fcc5d9aae27a369253ac09a81ed25c3867e8657a0680"}, + {file = "fonttools-4.43.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95e974d70238fc2be5f444fa91f6347191d0e914d5d8ae002c9aa189572cc215"}, + {file = "fonttools-4.43.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:34f713dad41aa21c637b4e04fe507c36b986a40f7179dcc86402237e2d39dcd3"}, + {file = "fonttools-4.43.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:360201d46165fc0753229afe785900bc9596ee6974833124f4e5e9f98d0f592b"}, + {file = "fonttools-4.43.1-cp312-cp312-win32.whl", hash = "sha256:bb6d2f8ef81ea076877d76acfb6f9534a9c5f31dc94ba70ad001267ac3a8e56f"}, + {file = "fonttools-4.43.1-cp312-cp312-win_amd64.whl", hash = "sha256:25d3da8a01442cbc1106490eddb6d31d7dffb38c1edbfabbcc8db371b3386d72"}, + {file = "fonttools-4.43.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8da417431bfc9885a505e86ba706f03f598c85f5a9c54f67d63e84b9948ce590"}, + {file = "fonttools-4.43.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51669b60ee2a4ad6c7fc17539a43ffffc8ef69fd5dbed186a38a79c0ac1f5db7"}, + {file = "fonttools-4.43.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:748015d6f28f704e7d95cd3c808b483c5fb87fd3eefe172a9da54746ad56bfb6"}, + {file = "fonttools-4.43.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a58eb5e736d7cf198eee94844b81c9573102ae5989ebcaa1d1a37acd04b33d"}, + {file = "fonttools-4.43.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6bb5ea9076e0e39defa2c325fc086593ae582088e91c0746bee7a5a197be3da0"}, + {file = "fonttools-4.43.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5f37e31291bf99a63328668bb83b0669f2688f329c4c0d80643acee6e63cd933"}, + {file = "fonttools-4.43.1-cp38-cp38-win32.whl", hash = "sha256:9c60ecfa62839f7184f741d0509b5c039d391c3aff71dc5bc57b87cc305cff3b"}, + {file = "fonttools-4.43.1-cp38-cp38-win_amd64.whl", hash = "sha256:fe9b1ec799b6086460a7480e0f55c447b1aca0a4eecc53e444f639e967348896"}, + {file = "fonttools-4.43.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13a9a185259ed144def3682f74fdcf6596f2294e56fe62dfd2be736674500dba"}, + {file = "fonttools-4.43.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2adca1b46d69dce4a37eecc096fe01a65d81a2f5c13b25ad54d5430ae430b13"}, + {file = "fonttools-4.43.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18eefac1b247049a3a44bcd6e8c8fd8b97f3cad6f728173b5d81dced12d6c477"}, + {file = "fonttools-4.43.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2062542a7565091cea4cc14dd99feff473268b5b8afdee564f7067dd9fff5860"}, + {file = "fonttools-4.43.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18a2477c62a728f4d6e88c45ee9ee0229405e7267d7d79ce1f5ce0f3e9f8ab86"}, + {file = "fonttools-4.43.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a7a06f8d95b7496e53af80d974d63516ffb263a468e614978f3899a6df52d4b3"}, + {file = "fonttools-4.43.1-cp39-cp39-win32.whl", hash = "sha256:10003ebd81fec0192c889e63a9c8c63f88c7d72ae0460b7ba0cd2a1db246e5ad"}, + {file = "fonttools-4.43.1-cp39-cp39-win_amd64.whl", hash = "sha256:e117a92b07407a061cde48158c03587ab97e74e7d73cb65e6aadb17af191162a"}, + {file = "fonttools-4.43.1-py3-none-any.whl", hash = "sha256:4f88cae635bfe4bbbdc29d479a297bb525a94889184bb69fa9560c2d4834ddb9"}, + {file = "fonttools-4.43.1.tar.gz", hash = "sha256:17dbc2eeafb38d5d0e865dcce16e313c58265a6d2d20081c435f84dc5a9d8212"}, +] + +[package.extras] +all = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "fs (>=2.2.0,<3)", "lxml (>=4.0,<5)", "lz4 (>=1.7.4.2)", "matplotlib", "munkres", "scipy", "skia-pathops (>=0.5.0)", "sympy", "uharfbuzz (>=0.23.0)", "unicodedata2 (>=15.0.0)", "xattr", "zopfli (>=0.1.4)"] +graphite = ["lz4 (>=1.7.4.2)"] +interpolatable = ["munkres", "scipy"] +lxml = ["lxml (>=4.0,<5)"] +pathops = ["skia-pathops (>=0.5.0)"] +plot = ["matplotlib"] +repacker = ["uharfbuzz (>=0.23.0)"] +symfont = ["sympy"] +type1 = ["xattr"] +ufo = ["fs (>=2.2.0,<3)"] +unicode = ["unicodedata2 (>=15.0.0)"] +woff = ["brotli (>=1.0.1)", "brotlicffi (>=0.8.0)", "zopfli (>=0.1.4)"] + +[[package]] +name = "frozenlist" +version = "1.4.0" +description = "A list-like structure which implements collections.abc.MutableSequence" +optional = false +python-versions = ">=3.8" +files = [ + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:764226ceef3125e53ea2cb275000e309c0aa5464d43bd72abd661e27fffc26ab"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d6484756b12f40003c6128bfcc3fa9f0d49a687e171186c2d85ec82e3758c559"}, + {file = "frozenlist-1.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9ac08e601308e41eb533f232dbf6b7e4cea762f9f84f6357136eed926c15d12c"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d081f13b095d74b67d550de04df1c756831f3b83dc9881c38985834387487f1b"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:71932b597f9895f011f47f17d6428252fc728ba2ae6024e13c3398a087c2cdea"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:981b9ab5a0a3178ff413bca62526bb784249421c24ad7381e39d67981be2c326"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e41f3de4df3e80de75845d3e743b3f1c4c8613c3997a912dbf0229fc61a8b963"}, + {file = "frozenlist-1.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6918d49b1f90821e93069682c06ffde41829c346c66b721e65a5c62b4bab0300"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e5c8764c7829343d919cc2dfc587a8db01c4f70a4ebbc49abde5d4b158b007b"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8d0edd6b1c7fb94922bf569c9b092ee187a83f03fb1a63076e7774b60f9481a8"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e29cda763f752553fa14c68fb2195150bfab22b352572cb36c43c47bedba70eb"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:0c7c1b47859ee2cac3846fde1c1dc0f15da6cec5a0e5c72d101e0f83dcb67ff9"}, + {file = "frozenlist-1.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:901289d524fdd571be1c7be054f48b1f88ce8dddcbdf1ec698b27d4b8b9e5d62"}, + {file = "frozenlist-1.4.0-cp310-cp310-win32.whl", hash = "sha256:1a0848b52815006ea6596c395f87449f693dc419061cc21e970f139d466dc0a0"}, + {file = "frozenlist-1.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:b206646d176a007466358aa21d85cd8600a415c67c9bd15403336c331a10d956"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:de343e75f40e972bae1ef6090267f8260c1446a1695e77096db6cfa25e759a95"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ad2a9eb6d9839ae241701d0918f54c51365a51407fd80f6b8289e2dfca977cc3"}, + {file = "frozenlist-1.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:bd7bd3b3830247580de99c99ea2a01416dfc3c34471ca1298bccabf86d0ff4dc"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bdf1847068c362f16b353163391210269e4f0569a3c166bc6a9f74ccbfc7e839"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38461d02d66de17455072c9ba981d35f1d2a73024bee7790ac2f9e361ef1cd0c"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5a32087d720c608f42caed0ef36d2b3ea61a9d09ee59a5142d6070da9041b8f"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd65632acaf0d47608190a71bfe46b209719bf2beb59507db08ccdbe712f969b"}, + {file = "frozenlist-1.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:261b9f5d17cac914531331ff1b1d452125bf5daa05faf73b71d935485b0c510b"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b89ac9768b82205936771f8d2eb3ce88503b1556324c9f903e7156669f521472"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:008eb8b31b3ea6896da16c38c1b136cb9fec9e249e77f6211d479db79a4eaf01"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e74b0506fa5aa5598ac6a975a12aa8928cbb58e1f5ac8360792ef15de1aa848f"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:490132667476f6781b4c9458298b0c1cddf237488abd228b0b3650e5ecba7467"}, + {file = "frozenlist-1.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:76d4711f6f6d08551a7e9ef28c722f4a50dd0fc204c56b4bcd95c6cc05ce6fbb"}, + {file = "frozenlist-1.4.0-cp311-cp311-win32.whl", hash = "sha256:a02eb8ab2b8f200179b5f62b59757685ae9987996ae549ccf30f983f40602431"}, + {file = "frozenlist-1.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:515e1abc578dd3b275d6a5114030b1330ba044ffba03f94091842852f806f1c1"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f0ed05f5079c708fe74bf9027e95125334b6978bf07fd5ab923e9e55e5fbb9d3"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ca265542ca427bf97aed183c1676e2a9c66942e822b14dc6e5f42e038f92a503"}, + {file = "frozenlist-1.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:491e014f5c43656da08958808588cc6c016847b4360e327a62cb308c791bd2d9"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:17ae5cd0f333f94f2e03aaf140bb762c64783935cc764ff9c82dff626089bebf"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e78fb68cf9c1a6aa4a9a12e960a5c9dfbdb89b3695197aa7064705662515de2"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5655a942f5f5d2c9ed93d72148226d75369b4f6952680211972a33e59b1dfdc"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c11b0746f5d946fecf750428a95f3e9ebe792c1ee3b1e96eeba145dc631a9672"}, + {file = "frozenlist-1.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e66d2a64d44d50d2543405fb183a21f76b3b5fd16f130f5c99187c3fb4e64919"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:88f7bc0fcca81f985f78dd0fa68d2c75abf8272b1f5c323ea4a01a4d7a614efc"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5833593c25ac59ede40ed4de6d67eb42928cca97f26feea219f21d0ed0959b79"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:fec520865f42e5c7f050c2a79038897b1c7d1595e907a9e08e3353293ffc948e"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:b826d97e4276750beca7c8f0f1a4938892697a6bcd8ec8217b3312dad6982781"}, + {file = "frozenlist-1.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ceb6ec0a10c65540421e20ebd29083c50e6d1143278746a4ef6bcf6153171eb8"}, + {file = "frozenlist-1.4.0-cp38-cp38-win32.whl", hash = "sha256:2b8bcf994563466db019fab287ff390fffbfdb4f905fc77bc1c1d604b1c689cc"}, + {file = "frozenlist-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:a6c8097e01886188e5be3e6b14e94ab365f384736aa1fca6a0b9e35bd4a30bc7"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6c38721585f285203e4b4132a352eb3daa19121a035f3182e08e437cface44bf"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a0c6da9aee33ff0b1a451e867da0c1f47408112b3391dd43133838339e410963"}, + {file = "frozenlist-1.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93ea75c050c5bb3d98016b4ba2497851eadf0ac154d88a67d7a6816206f6fa7f"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f61e2dc5ad442c52b4887f1fdc112f97caeff4d9e6ebe78879364ac59f1663e1"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa384489fefeb62321b238e64c07ef48398fe80f9e1e6afeff22e140e0850eef"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10ff5faaa22786315ef57097a279b833ecab1a0bfb07d604c9cbb1c4cdc2ed87"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:007df07a6e3eb3e33e9a1fe6a9db7af152bbd8a185f9aaa6ece10a3529e3e1c6"}, + {file = "frozenlist-1.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f4f399d28478d1f604c2ff9119907af9726aed73680e5ed1ca634d377abb087"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c5374b80521d3d3f2ec5572e05adc94601985cc526fb276d0c8574a6d749f1b3"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ce31ae3e19f3c902de379cf1323d90c649425b86de7bbdf82871b8a2a0615f3d"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7211ef110a9194b6042449431e08c4d80c0481e5891e58d429df5899690511c2"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:556de4430ce324c836789fa4560ca62d1591d2538b8ceb0b4f68fb7b2384a27a"}, + {file = "frozenlist-1.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7645a8e814a3ee34a89c4a372011dcd817964ce8cb273c8ed6119d706e9613e3"}, + {file = "frozenlist-1.4.0-cp39-cp39-win32.whl", hash = "sha256:19488c57c12d4e8095a922f328df3f179c820c212940a498623ed39160bc3c2f"}, + {file = "frozenlist-1.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:6221d84d463fb110bdd7619b69cb43878a11d51cbb9394ae3105d082d5199167"}, + {file = "frozenlist-1.4.0.tar.gz", hash = "sha256:09163bdf0b2907454042edb19f887c6d33806adc71fbd54afc14908bfdc22251"}, +] + +[[package]] +name = "fsspec" +version = "2023.10.0" +description = "File-system specification" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2023.10.0-py3-none-any.whl", hash = "sha256:346a8f024efeb749d2a5fca7ba8854474b1ff9af7c3faaf636a4548781136529"}, + {file = "fsspec-2023.10.0.tar.gz", hash = "sha256:330c66757591df346ad3091a53bd907e15348c2ba17d63fd54f5c39c4457d2a5"}, +] + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + +[[package]] +name = "gcsfs" +version = "2023.10.0" +description = "Convenient Filesystem interface over GCS" +optional = false +python-versions = ">=3.8" +files = [ + {file = "gcsfs-2023.10.0-py2.py3-none-any.whl", hash = "sha256:f3ad41652a596ca56e44778e041f428d022add3eff62b97a47302014affd270f"}, + {file = "gcsfs-2023.10.0.tar.gz", hash = "sha256:1915e6d766faad9a295e815b13c59966b925a274108b8a56f673623bf4aef83f"}, +] + +[package.dependencies] +aiohttp = "<4.0.0a0 || >4.0.0a0,<4.0.0a1 || >4.0.0a1" +decorator = ">4.1.2" +fsspec = "2023.10.0" +google-auth = ">=1.2" +google-auth-oauthlib = "*" +google-cloud-storage = "*" +requests = "*" + +[package.extras] +crc = ["crcmod"] +gcsfuse = ["fusepy"] + +[[package]] +name = "gitdb" +version = "4.0.11" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, + {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.40" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.40-py3-none-any.whl", hash = "sha256:cf14627d5a8049ffbf49915732e5eddbe8134c3bdb9d476e6182b676fc573f8a"}, + {file = "GitPython-3.1.40.tar.gz", hash = "sha256:22b126e9ffb671fdd0c129796343a02bf67bf2994b35449ffc9321aa755e18a4"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-instafail", "pytest-subtests", "pytest-sugar"] + +[[package]] +name = "google-api-core" +version = "2.12.0" +description = "Google API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-api-core-2.12.0.tar.gz", hash = "sha256:c22e01b1e3c4dcd90998494879612c38d0a3411d1f7b679eb89e2abe3ce1f553"}, + {file = "google_api_core-2.12.0-py3-none-any.whl", hash = "sha256:ec6054f7d64ad13b41e43d96f735acbd763b0f3b695dabaa2d579673f6a6e160"}, +] + +[package.dependencies] +google-auth = ">=2.14.1,<3.0.dev0" +googleapis-common-protos = ">=1.56.2,<2.0.dev0" +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" +requests = ">=2.18.0,<3.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status (>=1.33.2,<2.0.dev0)", "grpcio-status (>=1.49.1,<2.0.dev0)"] +grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] + +[[package]] +name = "google-auth" +version = "2.23.3" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-auth-2.23.3.tar.gz", hash = "sha256:6864247895eea5d13b9c57c9e03abb49cb94ce2dc7c58e91cba3248c7477c9e3"}, + {file = "google_auth-2.23.3-py2.py3-none-any.whl", hash = "sha256:a8f4608e65c244ead9e0538f181a96c6e11199ec114d41f1d7b1bffa96937bda"}, +] + +[package.dependencies] +cachetools = ">=2.0.0,<6.0" +pyasn1-modules = ">=0.2.1" +rsa = ">=3.1.4,<5" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0.dev0)", "requests (>=2.20.0,<3.0.0.dev0)"] +enterprise-cert = ["cryptography (==36.0.2)", "pyopenssl (==22.0.0)"] +pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] +reauth = ["pyu2f (>=0.1.5)"] +requests = ["requests (>=2.20.0,<3.0.0.dev0)"] + +[[package]] +name = "google-auth-oauthlib" +version = "1.1.0" +description = "Google Authentication Library" +optional = false +python-versions = ">=3.6" +files = [ + {file = "google-auth-oauthlib-1.1.0.tar.gz", hash = "sha256:83ea8c3b0881e453790baff4448e8a6112ac8778d1de9da0b68010b843937afb"}, + {file = "google_auth_oauthlib-1.1.0-py2.py3-none-any.whl", hash = "sha256:089c6e587d36f4803ac7e0720c045c6a8b1fd1790088b8424975b90d0ee61c12"}, +] + +[package.dependencies] +google-auth = ">=2.15.0" +requests-oauthlib = ">=0.7.0" + +[package.extras] +tool = ["click (>=6.0.0)"] + +[[package]] +name = "google-cloud-core" +version = "2.3.3" +description = "Google Cloud API client core library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-core-2.3.3.tar.gz", hash = "sha256:37b80273c8d7eee1ae816b3a20ae43585ea50506cb0e60f3cf5be5f87f1373cb"}, + {file = "google_cloud_core-2.3.3-py2.py3-none-any.whl", hash = "sha256:fbd11cad3e98a7e5b0343dc07cb1039a5ffd7a5bb96e1f1e27cee4bda4a90863"}, +] + +[package.dependencies] +google-api-core = ">=1.31.6,<2.0.dev0 || >2.3.0,<3.0.0dev" +google-auth = ">=1.25.0,<3.0dev" + +[package.extras] +grpc = ["grpcio (>=1.38.0,<2.0dev)"] + +[[package]] +name = "google-cloud-storage" +version = "2.12.0" +description = "Google Cloud Storage API client library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-cloud-storage-2.12.0.tar.gz", hash = "sha256:57c0bcda2f5e11f008a155d8636d8381d5abab46b58e0cae0e46dd5e595e6b46"}, + {file = "google_cloud_storage-2.12.0-py2.py3-none-any.whl", hash = "sha256:bc52563439d42981b6e21b071a76da2791672776eda3ba99d13a8061ebbd6e5e"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0dev" +google-auth = ">=2.23.3,<3.0dev" +google-cloud-core = ">=2.3.0,<3.0dev" +google-crc32c = ">=1.0,<2.0dev" +google-resumable-media = ">=2.6.0" +requests = ">=2.18.0,<3.0.0dev" + +[package.extras] +protobuf = ["protobuf (<5.0.0dev)"] + +[[package]] +name = "google-crc32c" +version = "1.5.0" +description = "A python wrapper of the C library 'Google CRC32C'" +optional = false +python-versions = ">=3.7" +files = [ + {file = "google-crc32c-1.5.0.tar.gz", hash = "sha256:89284716bc6a5a415d4eaa11b1726d2d60a0cd12aadf5439828353662ede9dd7"}, + {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:596d1f98fc70232fcb6590c439f43b350cb762fb5d61ce7b0e9db4539654cc13"}, + {file = "google_crc32c-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:be82c3c8cfb15b30f36768797a640e800513793d6ae1724aaaafe5bf86f8f346"}, + {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:461665ff58895f508e2866824a47bdee72497b091c730071f2b7575d5762ab65"}, + {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2096eddb4e7c7bdae4bd69ad364e55e07b8316653234a56552d9c988bd2d61b"}, + {file = "google_crc32c-1.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:116a7c3c616dd14a3de8c64a965828b197e5f2d121fedd2f8c5585c547e87b02"}, + {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5829b792bf5822fd0a6f6eb34c5f81dd074f01d570ed7f36aa101d6fc7a0a6e4"}, + {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:64e52e2b3970bd891309c113b54cf0e4384762c934d5ae56e283f9a0afcd953e"}, + {file = "google_crc32c-1.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:02ebb8bf46c13e36998aeaad1de9b48f4caf545e91d14041270d9dca767b780c"}, + {file = "google_crc32c-1.5.0-cp310-cp310-win32.whl", hash = "sha256:2e920d506ec85eb4ba50cd4228c2bec05642894d4c73c59b3a2fe20346bd00ee"}, + {file = "google_crc32c-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:07eb3c611ce363c51a933bf6bd7f8e3878a51d124acfc89452a75120bc436289"}, + {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cae0274952c079886567f3f4f685bcaf5708f0a23a5f5216fdab71f81a6c0273"}, + {file = "google_crc32c-1.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1034d91442ead5a95b5aaef90dbfaca8633b0247d1e41621d1e9f9db88c36298"}, + {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c42c70cd1d362284289c6273adda4c6af8039a8ae12dc451dcd61cdabb8ab57"}, + {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8485b340a6a9e76c62a7dce3c98e5f102c9219f4cfbf896a00cf48caf078d438"}, + {file = "google_crc32c-1.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77e2fd3057c9d78e225fa0a2160f96b64a824de17840351b26825b0848022906"}, + {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f583edb943cf2e09c60441b910d6a20b4d9d626c75a36c8fcac01a6c96c01183"}, + {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:a1fd716e7a01f8e717490fbe2e431d2905ab8aa598b9b12f8d10abebb36b04dd"}, + {file = "google_crc32c-1.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:72218785ce41b9cfd2fc1d6a017dc1ff7acfc4c17d01053265c41a2c0cc39b8c"}, + {file = "google_crc32c-1.5.0-cp311-cp311-win32.whl", hash = "sha256:66741ef4ee08ea0b2cc3c86916ab66b6aef03768525627fd6a1b34968b4e3709"}, + {file = "google_crc32c-1.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:ba1eb1843304b1e5537e1fca632fa894d6f6deca8d6389636ee5b4797affb968"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:98cb4d057f285bd80d8778ebc4fde6b4d509ac3f331758fb1528b733215443ae"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd8536e902db7e365f49e7d9029283403974ccf29b13fc7028b97e2295b33556"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:19e0a019d2c4dcc5e598cd4a4bc7b008546b0358bd322537c74ad47a5386884f"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02c65b9817512edc6a4ae7c7e987fea799d2e0ee40c53ec573a692bee24de876"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6ac08d24c1f16bd2bf5eca8eaf8304812f44af5cfe5062006ec676e7e1d50afc"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3359fc442a743e870f4588fcf5dcbc1bf929df1fad8fb9905cd94e5edb02e84c"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e986b206dae4476f41bcec1faa057851f3889503a70e1bdb2378d406223994a"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:de06adc872bcd8c2a4e0dc51250e9e65ef2ca91be023b9d13ebd67c2ba552e1e"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-win32.whl", hash = "sha256:d3515f198eaa2f0ed49f8819d5732d70698c3fa37384146079b3799b97667a94"}, + {file = "google_crc32c-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:67b741654b851abafb7bc625b6d1cdd520a379074e64b6a128e3b688c3c04740"}, + {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c02ec1c5856179f171e032a31d6f8bf84e5a75c45c33b2e20a3de353b266ebd8"}, + {file = "google_crc32c-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:edfedb64740750e1a3b16152620220f51d58ff1b4abceb339ca92e934775c27a"}, + {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84e6e8cd997930fc66d5bb4fde61e2b62ba19d62b7abd7a69920406f9ecca946"}, + {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:024894d9d3cfbc5943f8f230e23950cd4906b2fe004c72e29b209420a1e6b05a"}, + {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:998679bf62b7fb599d2878aa3ed06b9ce688b8974893e7223c60db155f26bd8d"}, + {file = "google_crc32c-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:83c681c526a3439b5cf94f7420471705bbf96262f49a6fe546a6db5f687a3d4a"}, + {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4c6fdd4fccbec90cc8a01fc00773fcd5fa28db683c116ee3cb35cd5da9ef6c37"}, + {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5ae44e10a8e3407dbe138984f21e536583f2bba1be9491239f942c2464ac0894"}, + {file = "google_crc32c-1.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:37933ec6e693e51a5b07505bd05de57eee12f3e8c32b07da7e73669398e6630a"}, + {file = "google_crc32c-1.5.0-cp38-cp38-win32.whl", hash = "sha256:fe70e325aa68fa4b5edf7d1a4b6f691eb04bbccac0ace68e34820d283b5f80d4"}, + {file = "google_crc32c-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:74dea7751d98034887dbd821b7aae3e1d36eda111d6ca36c206c44478035709c"}, + {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c6c777a480337ac14f38564ac88ae82d4cd238bf293f0a22295b66eb89ffced7"}, + {file = "google_crc32c-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:759ce4851a4bb15ecabae28f4d2e18983c244eddd767f560165563bf9aefbc8d"}, + {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f13cae8cc389a440def0c8c52057f37359014ccbc9dc1f0827936bcd367c6100"}, + {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e560628513ed34759456a416bf86b54b2476c59144a9138165c9a1575801d0d9"}, + {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1674e4307fa3024fc897ca774e9c7562c957af85df55efe2988ed9056dc4e57"}, + {file = "google_crc32c-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:278d2ed7c16cfc075c91378c4f47924c0625f5fc84b2d50d921b18b7975bd210"}, + {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d5280312b9af0976231f9e317c20e4a61cd2f9629b7bfea6a693d1878a264ebd"}, + {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b87e1a59c38f275c0e3676fc2ab6d59eccecfd460be267ac360cc31f7bcde96"}, + {file = "google_crc32c-1.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7c074fece789b5034b9b1404a1f8208fc2d4c6ce9decdd16e8220c5a793e6f61"}, + {file = "google_crc32c-1.5.0-cp39-cp39-win32.whl", hash = "sha256:7f57f14606cd1dd0f0de396e1e53824c371e9544a822648cd76c034d209b559c"}, + {file = "google_crc32c-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:a2355cba1f4ad8b6988a4ca3feed5bff33f6af2d7f134852cf279c2aebfde541"}, + {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f314013e7dcd5cf45ab1945d92e713eec788166262ae8deb2cfacd53def27325"}, + {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b747a674c20a67343cb61d43fdd9207ce5da6a99f629c6e2541aa0e89215bcd"}, + {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8f24ed114432de109aa9fd317278518a5af2d31ac2ea6b952b2f7782b43da091"}, + {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8667b48e7a7ef66afba2c81e1094ef526388d35b873966d8a9a447974ed9178"}, + {file = "google_crc32c-1.5.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:1c7abdac90433b09bad6c43a43af253e688c9cfc1c86d332aed13f9a7c7f65e2"}, + {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6f998db4e71b645350b9ac28a2167e6632c239963ca9da411523bb439c5c514d"}, + {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c99616c853bb585301df6de07ca2cadad344fd1ada6d62bb30aec05219c45d2"}, + {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ad40e31093a4af319dadf503b2467ccdc8f67c72e4bcba97f8c10cb078207b5"}, + {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd67cf24a553339d5062eff51013780a00d6f97a39ca062781d06b3a73b15462"}, + {file = "google_crc32c-1.5.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:398af5e3ba9cf768787eef45c803ff9614cc3e22a5b2f7d7ae116df8b11e3314"}, + {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b1f8133c9a275df5613a451e73f36c2aea4fe13c5c8997e22cf355ebd7bd0728"}, + {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ba053c5f50430a3fcfd36f75aff9caeba0440b2d076afdb79a318d6ca245f88"}, + {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:272d3892a1e1a2dbc39cc5cde96834c236d5327e2122d3aaa19f6614531bb6eb"}, + {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:635f5d4dd18758a1fbd1049a8e8d2fee4ffed124462d837d1a02a0e009c3ab31"}, + {file = "google_crc32c-1.5.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c672d99a345849301784604bfeaeba4db0c7aae50b95be04dd651fd2a7310b93"}, +] + +[package.extras] +testing = ["pytest"] + +[[package]] +name = "google-resumable-media" +version = "2.6.0" +description = "Utilities for Google Media Downloads and Resumable Uploads" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "google-resumable-media-2.6.0.tar.gz", hash = "sha256:972852f6c65f933e15a4a210c2b96930763b47197cdf4aa5f5bea435efb626e7"}, + {file = "google_resumable_media-2.6.0-py2.py3-none-any.whl", hash = "sha256:fc03d344381970f79eebb632a3c18bb1828593a2dc5572b5f90115ef7d11e81b"}, +] + +[package.dependencies] +google-crc32c = ">=1.0,<2.0dev" + +[package.extras] +aiohttp = ["aiohttp (>=3.6.2,<4.0.0dev)", "google-auth (>=1.22.0,<2.0dev)"] +requests = ["requests (>=2.18.0,<3.0.0dev)"] + +[[package]] +name = "googleapis-common-protos" +version = "1.61.0" +description = "Common protobufs used in Google APIs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "googleapis-common-protos-1.61.0.tar.gz", hash = "sha256:8a64866a97f6304a7179873a465d6eee97b7a24ec6cfd78e0f575e96b821240b"}, + {file = "googleapis_common_protos-1.61.0-py2.py3-none-any.whl", hash = "sha256:22f1915393bb3245343f6efe87f6fe868532efc12aa26b391b15132e1279f1c0"}, +] + +[package.dependencies] +protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0.dev0" + +[package.extras] +grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] + +[[package]] +name = "graphviz" +version = "0.20.1" +description = "Simple Python interface for Graphviz" +optional = false +python-versions = ">=3.7" +files = [ + {file = "graphviz-0.20.1-py3-none-any.whl", hash = "sha256:587c58a223b51611c0cf461132da386edd896a029524ca61a1462b880bf97977"}, + {file = "graphviz-0.20.1.zip", hash = "sha256:8c58f14adaa3b947daf26c19bc1e98c4e0702cdc31cf99153e6f06904d492bf8"}, +] + +[package.extras] +dev = ["flake8", "pep8-naming", "tox (>=3)", "twine", "wheel"] +docs = ["sphinx (>=5)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"] +test = ["coverage", "mock (>=4)", "pytest (>=7)", "pytest-cov", "pytest-mock (>=3)"] + +[[package]] +name = "greenlet" +version = "3.0.1" +description = "Lightweight in-process concurrent programming" +optional = false +python-versions = ">=3.7" +files = [ + {file = "greenlet-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f89e21afe925fcfa655965ca8ea10f24773a1791400989ff32f467badfe4a064"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28e89e232c7593d33cac35425b58950789962011cc274aa43ef8865f2e11f46d"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8ba29306c5de7717b5761b9ea74f9c72b9e2b834e24aa984da99cbfc70157fd"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19bbdf1cce0346ef7341705d71e2ecf6f41a35c311137f29b8a2dc2341374565"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599daf06ea59bfedbec564b1692b0166a0045f32b6f0933b0dd4df59a854caf2"}, + {file = "greenlet-3.0.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b641161c302efbb860ae6b081f406839a8b7d5573f20a455539823802c655f63"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d57e20ba591727da0c230ab2c3f200ac9d6d333860d85348816e1dca4cc4792e"}, + {file = "greenlet-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5805e71e5b570d490938d55552f5a9e10f477c19400c38bf1d5190d760691846"}, + {file = "greenlet-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:52e93b28db27ae7d208748f45d2db8a7b6a380e0d703f099c949d0f0d80b70e9"}, + {file = "greenlet-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f7bfb769f7efa0eefcd039dd19d843a4fbfbac52f1878b1da2ed5793ec9b1a65"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91e6c7db42638dc45cf2e13c73be16bf83179f7859b07cfc139518941320be96"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1757936efea16e3f03db20efd0cd50a1c86b06734f9f7338a90c4ba85ec2ad5a"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19075157a10055759066854a973b3d1325d964d498a805bb68a1f9af4aaef8ec"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9d21aaa84557d64209af04ff48e0ad5e28c5cca67ce43444e939579d085da72"}, + {file = "greenlet-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2847e5d7beedb8d614186962c3d774d40d3374d580d2cbdab7f184580a39d234"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:97e7ac860d64e2dcba5c5944cfc8fa9ea185cd84061c623536154d5a89237884"}, + {file = "greenlet-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b2c02d2ad98116e914d4f3155ffc905fd0c025d901ead3f6ed07385e19122c94"}, + {file = "greenlet-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:22f79120a24aeeae2b4471c711dcf4f8c736a2bb2fabad2a67ac9a55ea72523c"}, + {file = "greenlet-3.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:100f78a29707ca1525ea47388cec8a049405147719f47ebf3895e7509c6446aa"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60d5772e8195f4e9ebf74046a9121bbb90090f6550f81d8956a05387ba139353"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:daa7197b43c707462f06d2c693ffdbb5991cbb8b80b5b984007de431493a319c"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea6b8aa9e08eea388c5f7a276fabb1d4b6b9d6e4ceb12cc477c3d352001768a9"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d11ebbd679e927593978aa44c10fc2092bc454b7d13fdc958d3e9d508aba7d0"}, + {file = "greenlet-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dbd4c177afb8a8d9ba348d925b0b67246147af806f0b104af4d24f144d461cd5"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20107edf7c2c3644c67c12205dc60b1bb11d26b2610b276f97d666110d1b511d"}, + {file = "greenlet-3.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8bef097455dea90ffe855286926ae02d8faa335ed8e4067326257cb571fc1445"}, + {file = "greenlet-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:b2d3337dcfaa99698aa2377c81c9ca72fcd89c07e7eb62ece3f23a3fe89b2ce4"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:80ac992f25d10aaebe1ee15df45ca0d7571d0f70b645c08ec68733fb7a020206"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:337322096d92808f76ad26061a8f5fccb22b0809bea39212cd6c406f6a7060d2"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9934adbd0f6e476f0ecff3c94626529f344f57b38c9a541f87098710b18af0a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4d815b794fd8868c4d67602692c21bf5293a75e4b607bb92a11e821e2b859a"}, + {file = "greenlet-3.0.1-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:41bdeeb552d814bcd7fb52172b304898a35818107cc8778b5101423c9017b3de"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6e6061bf1e9565c29002e3c601cf68569c450be7fc3f7336671af7ddb4657166"}, + {file = "greenlet-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:fa24255ae3c0ab67e613556375a4341af04a084bd58764731972bcbc8baeba36"}, + {file = "greenlet-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:b489c36d1327868d207002391f662a1d163bdc8daf10ab2e5f6e41b9b96de3b1"}, + {file = "greenlet-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:f33f3258aae89da191c6ebaa3bc517c6c4cbc9b9f689e5d8452f7aedbb913fa8"}, + {file = "greenlet-3.0.1-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:d2905ce1df400360463c772b55d8e2518d0e488a87cdea13dd2c71dcb2a1fa16"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a02d259510b3630f330c86557331a3b0e0c79dac3d166e449a39363beaae174"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:55d62807f1c5a1682075c62436702aaba941daa316e9161e4b6ccebbbf38bda3"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3fcc780ae8edbb1d050d920ab44790201f027d59fdbd21362340a85c79066a74"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eddd98afc726f8aee1948858aed9e6feeb1758889dfd869072d4465973f6bfd"}, + {file = "greenlet-3.0.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eabe7090db68c981fca689299c2d116400b553f4b713266b130cfc9e2aa9c5a9"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f2f6d303f3dee132b322a14cd8765287b8f86cdc10d2cb6a6fae234ea488888e"}, + {file = "greenlet-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d923ff276f1c1f9680d32832f8d6c040fe9306cbfb5d161b0911e9634be9ef0a"}, + {file = "greenlet-3.0.1-cp38-cp38-win32.whl", hash = "sha256:0b6f9f8ca7093fd4433472fd99b5650f8a26dcd8ba410e14094c1e44cd3ceddd"}, + {file = "greenlet-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:990066bff27c4fcf3b69382b86f4c99b3652bab2a7e685d968cd4d0cfc6f67c6"}, + {file = "greenlet-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ce85c43ae54845272f6f9cd8320d034d7a946e9773c693b27d620edec825e376"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89ee2e967bd7ff85d84a2de09df10e021c9b38c7d91dead95b406ed6350c6997"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87c8ceb0cf8a5a51b8008b643844b7f4a8264a2c13fcbcd8a8316161725383fe"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6a8c9d4f8692917a3dc7eb25a6fb337bff86909febe2f793ec1928cd97bedfc"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fbc5b8f3dfe24784cee8ce0be3da2d8a79e46a276593db6868382d9c50d97b1"}, + {file = "greenlet-3.0.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85d2b77e7c9382f004b41d9c72c85537fac834fb141b0296942d52bf03fe4a3d"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:696d8e7d82398e810f2b3622b24e87906763b6ebfd90e361e88eb85b0e554dc8"}, + {file = "greenlet-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:329c5a2e5a0ee942f2992c5e3ff40be03e75f745f48847f118a3cfece7a28546"}, + {file = "greenlet-3.0.1-cp39-cp39-win32.whl", hash = "sha256:cf868e08690cb89360eebc73ba4be7fb461cfbc6168dd88e2fbbe6f31812cd57"}, + {file = "greenlet-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ac4a39d1abae48184d420aa8e5e63efd1b75c8444dd95daa3e03f6c6310e9619"}, + {file = "greenlet-3.0.1.tar.gz", hash = "sha256:816bd9488a94cba78d93e1abb58000e8266fa9cc2aa9ccdd6eb0696acb24005b"}, +] + +[package.extras] +docs = ["Sphinx"] +test = ["objgraph", "psutil"] + +[[package]] +name = "identify" +version = "2.5.31" +description = "File identification library for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "identify-2.5.31-py2.py3-none-any.whl", hash = "sha256:90199cb9e7bd3c5407a9b7e81b4abec4bb9d249991c79439ec8af740afc6293d"}, + {file = "identify-2.5.31.tar.gz", hash = "sha256:7736b3c7a28233637e3c36550646fc6389bedd74ae84cb788200cc8e2dd60b75"}, +] + +[package.extras] +license = ["ukkonen"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "importlib-resources" +version = "6.1.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, + {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "joblib" +version = "1.3.2" +description = "Lightweight pipelining with Python functions" +optional = false +python-versions = ">=3.7" +files = [ + {file = "joblib-1.3.2-py3-none-any.whl", hash = "sha256:ef4331c65f239985f3f2220ecc87db222f08fd22097a3dd5698f693875f8cbb9"}, + {file = "joblib-1.3.2.tar.gz", hash = "sha256:92f865e621e17784e7955080b6d042489e3b8e294949cc44c6eac304f59772b1"}, +] + +[[package]] +name = "kiwisolver" +version = "1.4.5" +description = "A fast implementation of the Cassowary constraint solver" +optional = false +python-versions = ">=3.7" +files = [ + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:05703cf211d585109fcd72207a31bb170a0f22144d68298dc5e61b3c946518af"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:146d14bebb7f1dc4d5fbf74f8a6cb15ac42baadee8912eb84ac0b3b2a3dc6ac3"}, + {file = "kiwisolver-1.4.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6ef7afcd2d281494c0a9101d5c571970708ad911d028137cd558f02b851c08b4"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9eaa8b117dc8337728e834b9c6e2611f10c79e38f65157c4c38e9400286f5cb1"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec20916e7b4cbfb1f12380e46486ec4bcbaa91a9c448b97023fde0d5bbf9e4ff"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39b42c68602539407884cf70d6a480a469b93b81b7701378ba5e2328660c847a"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa12042de0171fad672b6c59df69106d20d5596e4f87b5e8f76df757a7c399aa"}, + {file = "kiwisolver-1.4.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a40773c71d7ccdd3798f6489aaac9eee213d566850a9533f8d26332d626b82c"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:19df6e621f6d8b4b9c4d45f40a66839294ff2bb235e64d2178f7522d9170ac5b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:83d78376d0d4fd884e2c114d0621624b73d2aba4e2788182d286309ebdeed770"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:e391b1f0a8a5a10ab3b9bb6afcfd74f2175f24f8975fb87ecae700d1503cdee0"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:852542f9481f4a62dbb5dd99e8ab7aedfeb8fb6342349a181d4036877410f525"}, + {file = "kiwisolver-1.4.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:59edc41b24031bc25108e210c0def6f6c2191210492a972d585a06ff246bb79b"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win32.whl", hash = "sha256:a6aa6315319a052b4ee378aa171959c898a6183f15c1e541821c5c59beaa0238"}, + {file = "kiwisolver-1.4.5-cp310-cp310-win_amd64.whl", hash = "sha256:d0ef46024e6a3d79c01ff13801cb19d0cad7fd859b15037aec74315540acc276"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:11863aa14a51fd6ec28688d76f1735f8f69ab1fabf388851a595d0721af042f5"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:8ab3919a9997ab7ef2fbbed0cc99bb28d3c13e6d4b1ad36e97e482558a91be90"}, + {file = "kiwisolver-1.4.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fcc700eadbbccbf6bc1bcb9dbe0786b4b1cb91ca0dcda336eef5c2beed37b797"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfdd7c0b105af050eb3d64997809dc21da247cf44e63dc73ff0fd20b96be55a9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76c6a5964640638cdeaa0c359382e5703e9293030fe730018ca06bc2010c4437"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bbea0db94288e29afcc4c28afbf3a7ccaf2d7e027489c449cf7e8f83c6346eb9"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ceec1a6bc6cab1d6ff5d06592a91a692f90ec7505d6463a88a52cc0eb58545da"}, + {file = "kiwisolver-1.4.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:040c1aebeda72197ef477a906782b5ab0d387642e93bda547336b8957c61022e"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f91de7223d4c7b793867797bacd1ee53bfe7359bd70d27b7b58a04efbb9436c8"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:faae4860798c31530dd184046a900e652c95513796ef51a12bc086710c2eec4d"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:b0157420efcb803e71d1b28e2c287518b8808b7cf1ab8af36718fd0a2c453eb0"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:06f54715b7737c2fecdbf140d1afb11a33d59508a47bf11bb38ecf21dc9ab79f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fdb7adb641a0d13bdcd4ef48e062363d8a9ad4a182ac7647ec88f695e719ae9f"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win32.whl", hash = "sha256:bb86433b1cfe686da83ce32a9d3a8dd308e85c76b60896d58f082136f10bffac"}, + {file = "kiwisolver-1.4.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c08e1312a9cf1074d17b17728d3dfce2a5125b2d791527f33ffbe805200a355"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:32d5cf40c4f7c7b3ca500f8985eb3fb3a7dfc023215e876f207956b5ea26632a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f846c260f483d1fd217fe5ed7c173fb109efa6b1fc8381c8b7552c5781756192"}, + {file = "kiwisolver-1.4.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5ff5cf3571589b6d13bfbfd6bcd7a3f659e42f96b5fd1c4830c4cf21d4f5ef45"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7269d9e5f1084a653d575c7ec012ff57f0c042258bf5db0954bf551c158466e7"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da802a19d6e15dffe4b0c24b38b3af68e6c1a68e6e1d8f30148c83864f3881db"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3aba7311af82e335dd1e36ffff68aaca609ca6290c2cb6d821a39aa075d8e3ff"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:763773d53f07244148ccac5b084da5adb90bfaee39c197554f01b286cf869228"}, + {file = "kiwisolver-1.4.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2270953c0d8cdab5d422bee7d2007f043473f9d2999631c86a223c9db56cbd16"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d099e745a512f7e3bbe7249ca835f4d357c586d78d79ae8f1dcd4d8adeb9bda9"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:74db36e14a7d1ce0986fa104f7d5637aea5c82ca6326ed0ec5694280942d1162"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:7e5bab140c309cb3a6ce373a9e71eb7e4873c70c2dda01df6820474f9889d6d4"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0f114aa76dc1b8f636d077979c0ac22e7cd8f3493abbab152f20eb8d3cda71f3"}, + {file = "kiwisolver-1.4.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88a2df29d4724b9237fc0c6eaf2a1adae0cdc0b3e9f4d8e7dc54b16812d2d81a"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win32.whl", hash = "sha256:72d40b33e834371fd330fb1472ca19d9b8327acb79a5821d4008391db8e29f20"}, + {file = "kiwisolver-1.4.5-cp312-cp312-win_amd64.whl", hash = "sha256:2c5674c4e74d939b9d91dda0fae10597ac7521768fec9e399c70a1f27e2ea2d9"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3a2b053a0ab7a3960c98725cfb0bf5b48ba82f64ec95fe06f1d06c99b552e130"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cd32d6c13807e5c66a7cbb79f90b553642f296ae4518a60d8d76243b0ad2898"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59ec7b7c7e1a61061850d53aaf8e93db63dce0c936db1fda2658b70e4a1be709"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da4cfb373035def307905d05041c1d06d8936452fe89d464743ae7fb8371078b"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2400873bccc260b6ae184b2b8a4fec0e4082d30648eadb7c3d9a13405d861e89"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1b04139c4236a0f3aff534479b58f6f849a8b351e1314826c2d230849ed48985"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:4e66e81a5779b65ac21764c295087de82235597a2293d18d943f8e9e32746265"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7931d8f1f67c4be9ba1dd9c451fb0eeca1a25b89e4d3f89e828fe12a519b782a"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b3f7e75f3015df442238cca659f8baa5f42ce2a8582727981cbfa15fee0ee205"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:bbf1d63eef84b2e8c89011b7f2235b1e0bf7dacc11cac9431fc6468e99ac77fb"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4c380469bd3f970ef677bf2bcba2b6b0b4d5c75e7a020fb863ef75084efad66f"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win32.whl", hash = "sha256:9408acf3270c4b6baad483865191e3e582b638b1654a007c62e3efe96f09a9a3"}, + {file = "kiwisolver-1.4.5-cp37-cp37m-win_amd64.whl", hash = "sha256:5b94529f9b2591b7af5f3e0e730a4e0a41ea174af35a4fd067775f9bdfeee01a"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:11c7de8f692fc99816e8ac50d1d1aef4f75126eefc33ac79aac02c099fd3db71"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:53abb58632235cd154176ced1ae8f0d29a6657aa1aa9decf50b899b755bc2b93"}, + {file = "kiwisolver-1.4.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:88b9f257ca61b838b6f8094a62418421f87ac2a1069f7e896c36a7d86b5d4c29"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3195782b26fc03aa9c6913d5bad5aeb864bdc372924c093b0f1cebad603dd712"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc579bf0f502e54926519451b920e875f433aceb4624a3646b3252b5caa9e0b6"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a580c91d686376f0f7c295357595c5a026e6cbc3d77b7c36e290201e7c11ecb"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cfe6ab8da05c01ba6fbea630377b5da2cd9bcbc6338510116b01c1bc939a2c18"}, + {file = "kiwisolver-1.4.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2e5a98f0ec99beb3c10e13b387f8db39106d53993f498b295f0c914328b1333"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a51a263952b1429e429ff236d2f5a21c5125437861baeed77f5e1cc2d2c7c6da"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3edd2fa14e68c9be82c5b16689e8d63d89fe927e56debd6e1dbce7a26a17f81b"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:74d1b44c6cfc897df648cc9fdaa09bc3e7679926e6f96df05775d4fb3946571c"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:76d9289ed3f7501012e05abb8358bbb129149dbd173f1f57a1bf1c22d19ab7cc"}, + {file = "kiwisolver-1.4.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:92dea1ffe3714fa8eb6a314d2b3c773208d865a0e0d35e713ec54eea08a66250"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win32.whl", hash = "sha256:5c90ae8c8d32e472be041e76f9d2f2dbff4d0b0be8bd4041770eddb18cf49a4e"}, + {file = "kiwisolver-1.4.5-cp38-cp38-win_amd64.whl", hash = "sha256:c7940c1dc63eb37a67721b10d703247552416f719c4188c54e04334321351ced"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9407b6a5f0d675e8a827ad8742e1d6b49d9c1a1da5d952a67d50ef5f4170b18d"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:15568384086b6df3c65353820a4473575dbad192e35010f622c6ce3eebd57af9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0dc9db8e79f0036e8173c466d21ef18e1befc02de8bf8aa8dc0813a6dc8a7046"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:cdc8a402aaee9a798b50d8b827d7ecf75edc5fb35ea0f91f213ff927c15f4ff0"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6c3bd3cde54cafb87d74d8db50b909705c62b17c2099b8f2e25b461882e544ff"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:955e8513d07a283056b1396e9a57ceddbd272d9252c14f154d450d227606eb54"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:346f5343b9e3f00b8db8ba359350eb124b98c99efd0b408728ac6ebf38173958"}, + {file = "kiwisolver-1.4.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b9098e0049e88c6a24ff64545cdfc50807818ba6c1b739cae221bbbcbc58aad3"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:00bd361b903dc4bbf4eb165f24d1acbee754fce22ded24c3d56eec268658a5cf"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7b8b454bac16428b22560d0a1cf0a09875339cab69df61d7805bf48919415901"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f1d072c2eb0ad60d4c183f3fb44ac6f73fb7a8f16a2694a91f988275cbf352f9"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:31a82d498054cac9f6d0b53d02bb85811185bcb477d4b60144f915f3b3126342"}, + {file = "kiwisolver-1.4.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6512cb89e334e4700febbffaaa52761b65b4f5a3cf33f960213d5656cea36a77"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win32.whl", hash = "sha256:9db8ea4c388fdb0f780fe91346fd438657ea602d58348753d9fb265ce1bca67f"}, + {file = "kiwisolver-1.4.5-cp39-cp39-win_amd64.whl", hash = "sha256:59415f46a37f7f2efeec758353dd2eae1b07640d8ca0f0c42548ec4125492635"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:5c7b3b3a728dc6faf3fc372ef24f21d1e3cee2ac3e9596691d746e5a536de920"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:620ced262a86244e2be10a676b646f29c34537d0d9cc8eb26c08f53d98013390"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:378a214a1e3bbf5ac4a8708304318b4f890da88c9e6a07699c4ae7174c09a68d"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf7be1207676ac608a50cd08f102f6742dbfc70e8d60c4db1c6897f62f71523"}, + {file = "kiwisolver-1.4.5-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:ba55dce0a9b8ff59495ddd050a0225d58bd0983d09f87cfe2b6aec4f2c1234e4"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:fd32ea360bcbb92d28933fc05ed09bffcb1704ba3fc7942e81db0fd4f81a7892"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:5e7139af55d1688f8b960ee9ad5adafc4ac17c1c473fe07133ac092310d76544"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:dced8146011d2bc2e883f9bd68618b8247387f4bbec46d7392b3c3b032640126"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9bf3325c47b11b2e51bca0824ea217c7cd84491d8ac4eefd1e409705ef092bd"}, + {file = "kiwisolver-1.4.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5794cf59533bc3f1b1c821f7206a3617999db9fbefc345360aafe2e067514929"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e368f200bbc2e4f905b8e71eb38b3c04333bddaa6a2464a6355487b02bb7fb09"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d706eba36b4c4d5bc6c6377bb6568098765e990cfc21ee16d13963fab7b3e7"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85267bd1aa8880a9c88a8cb71e18d3d64d2751a790e6ca6c27b8ccc724bcd5ad"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210ef2c3a1f03272649aff1ef992df2e724748918c4bc2d5a90352849eb40bea"}, + {file = "kiwisolver-1.4.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:11d011a7574eb3b82bcc9c1a1d35c1d7075677fdd15de527d91b46bd35e935ee"}, + {file = "kiwisolver-1.4.5.tar.gz", hash = "sha256:e57e563a57fb22a142da34f38acc2fc1a5c864bc29ca1517a88abc963e60d6ec"}, +] + +[[package]] +name = "lxml" +version = "4.9.3" +description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" +files = [ + {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"}, + {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"}, + {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"}, + {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"}, + {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"}, + {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"}, + {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"}, + {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"}, + {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"}, + {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"}, + {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"}, + {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"}, + {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"}, + {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"}, + {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"}, + {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"}, + {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"}, + {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"}, + {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"}, + {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"}, + {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"}, + {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"}, + {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"}, + {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"}, + {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"}, + {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"}, + {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"}, + {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"}, + {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"}, + {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"}, + {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"}, + {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"}, + {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"}, + {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"}, + {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"}, + {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"}, + {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"}, + {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"}, + {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"}, + {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"}, + {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"}, + {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"}, + {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"}, + {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"}, + {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"}, + {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"}, + {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"}, + {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"}, + {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"}, + {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"}, + {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"}, + {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"}, + {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"}, + {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"}, + {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"}, + {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"}, + {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"}, + {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"}, + {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"}, + {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"}, + {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"}, + {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"}, + {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"}, + {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"}, + {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"}, + {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"}, + {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"}, + {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"}, + {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"}, + {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"}, + {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"}, + {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"}, +] + +[package.extras] +cssselect = ["cssselect (>=0.7)"] +html5 = ["html5lib"] +htmlsoup = ["BeautifulSoup4"] +source = ["Cython (>=0.29.35)"] + +[[package]] +name = "mako" +version = "1.2.4" +description = "A super-fast templating language that borrows the best ideas from the existing templating languages." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Mako-1.2.4-py3-none-any.whl", hash = "sha256:c97c79c018b9165ac9922ae4f32da095ffd3c4e6872b45eded42926deea46818"}, + {file = "Mako-1.2.4.tar.gz", hash = "sha256:d60a3903dc3bb01a18ad6a89cdbe2e4eadc69c0bc8ef1e3773ba53d44c3f7a34"}, +] + +[package.dependencies] +MarkupSafe = ">=0.9.2" + +[package.extras] +babel = ["Babel"] +lingua = ["lingua"] +testing = ["pytest"] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + +[[package]] +name = "matplotlib" +version = "3.7.3" +description = "Python plotting package" +optional = false +python-versions = ">=3.8" +files = [ + {file = "matplotlib-3.7.3-cp310-cp310-macosx_10_12_universal2.whl", hash = "sha256:085c33b27561d9c04386789d5aa5eb4a932ddef43cfcdd0e01735f9a6e85ce0c"}, + {file = "matplotlib-3.7.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c568e80e1c17f68a727f30f591926751b97b98314d8e59804f54f86ae6fa6a22"}, + {file = "matplotlib-3.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7baf98c5ad59c5c4743ea884bb025cbffa52dacdfdac0da3e6021a285a90377e"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:236024f582e40dac39bca592258888b38ae47a9fed7b8de652d68d3d02d47d2b"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12b4f6795efea037ce2d41e7c417ad8bd02d5719c6ad4a8450a0708f4a1cfb89"}, + {file = "matplotlib-3.7.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b2136cc6c5415b78977e0e8c608647d597204b05b1d9089ccf513c7d913733"}, + {file = "matplotlib-3.7.3-cp310-cp310-win32.whl", hash = "sha256:122dcbf9be0086e2a95d9e5e0632dbf3bd5b65eaa68c369363310a6c87753059"}, + {file = "matplotlib-3.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4aab27d9e33293389e3c1d7c881d414a72bdfda0fedc3a6bf46c6fa88d9b8015"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_10_12_universal2.whl", hash = "sha256:d5adc743de91e8e0b13df60deb1b1c285b8effea3d66223afceb14b63c9b05de"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:55de4cf7cd0071b8ebf203981b53ab64f988a0a1f897a2dff300a1124e8bcd8b"}, + {file = "matplotlib-3.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ac03377fd908aaee2312d0b11735753e907adb6f4d1d102de5e2425249693f6c"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:755bafc10a46918ce9a39980009b54b02dd249594e5adf52f9c56acfddb5d0b7"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a6094c6f8e8d18db631754df4fe9a34dec3caf074f6869a7db09f18f9b1d6b2"}, + {file = "matplotlib-3.7.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:272dba2f1b107790ed78ebf5385b8d14b27ad9e90419de340364b49fe549a993"}, + {file = "matplotlib-3.7.3-cp311-cp311-win32.whl", hash = "sha256:591c123bed1cb4b9996fb60b41a6d89c2ec4943244540776c5f1283fb6960a53"}, + {file = "matplotlib-3.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:3bf3a178c6504694cee8b88b353df0051583f2f6f8faa146f67115c27c856881"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_10_12_universal2.whl", hash = "sha256:edf54cac8ee3603f3093616b40a931e8c063969756a4d78a86e82c2fea9659f7"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:91e36a85ea639a1ba9f91427041eac064b04829945fe331a92617b6cb21d27e5"}, + {file = "matplotlib-3.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:caf5eaaf7c68f8d7df269dfbcaf46f48a70ff482bfcebdcc97519671023f2a7d"}, + {file = "matplotlib-3.7.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74bf57f505efea376097e948b7cdd87191a7ce8180616390aef496639edf601f"}, + {file = "matplotlib-3.7.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee152a88a0da527840a426535514b6ed8ac4240eb856b1da92cf48124320e346"}, + {file = "matplotlib-3.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:67a410a9c9e07cbc83581eeea144bbe298870bf0ac0ee2f2e10a015ab7efee19"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_10_12_universal2.whl", hash = "sha256:259999c05285cb993d7f2a419cea547863fa215379eda81f7254c9e932963729"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:3f4e7fd5a6157e1d018ce2166ec8e531a481dd4a36f035b5c23edfe05a25419a"}, + {file = "matplotlib-3.7.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:faa3d12d8811d08d14080a8b7b9caea9a457dc495350166b56df0db4b9909ef5"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:336e88900c11441e458da01c8414fc57e04e17f9d3bb94958a76faa2652bcf6b"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:12f4c0dd8aa280d796c8772ea8265a14f11a04319baa3a16daa5556065e8baea"}, + {file = "matplotlib-3.7.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1990955b11e7918d256cf3b956b10997f405b7917a3f1c7d8e69c1d15c7b1930"}, + {file = "matplotlib-3.7.3-cp38-cp38-win32.whl", hash = "sha256:e78707b751260b42b721507ad7aa60fe4026d7f51c74cca6b9cd8b123ebb633a"}, + {file = "matplotlib-3.7.3-cp38-cp38-win_amd64.whl", hash = "sha256:e594ee43c59ea39ca5c6244667cac9d017a3527febc31f5532ad9135cf7469ec"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_10_12_universal2.whl", hash = "sha256:6eaa1cf0e94c936a26b78f6d756c5fbc12e0a58c8a68b7248a2a31456ce4e234"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0a97af9d22e8ebedc9f00b043d9bbd29a375e9e10b656982012dded44c10fd77"}, + {file = "matplotlib-3.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f9c6c16597af660433ab330b59ee2934b832ee1fabcaf5cbde7b2add840f31e"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a7240259b4b9cbc62381f6378cff4d57af539162a18e832c1e48042fabc40b6b"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747c6191d2e88ae854809e69aa358dbf852ff1a5738401b85c1cc9012309897a"}, + {file = "matplotlib-3.7.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec726b08a5275d827aa91bb951e68234a4423adb91cf65bc0fcdc0f2777663f7"}, + {file = "matplotlib-3.7.3-cp39-cp39-win32.whl", hash = "sha256:40e3b9b450c6534f07278310c4e34caff41c2a42377e4b9d47b0f8d3ac1083a2"}, + {file = "matplotlib-3.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:dfc118642903a23e309b1da32886bb39a4314147d013e820c86b5fb4cb2e36d0"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:165c8082bf8fc0360c24aa4724a22eaadbfd8c28bf1ccf7e94d685cad48261e4"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebd8470cc2a3594746ff0513aecbfa2c55ff6f58e6cef2efb1a54eb87c88ffa2"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7153453669c9672b52095119fd21dd032d19225d48413a2871519b17db4b0fde"}, + {file = "matplotlib-3.7.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:498a08267dc69dd8f24c4b5d7423fa584d7ce0027ba71f7881df05fc09b89bb7"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48999c4b19b5a0c058c9cd828ff6fc7748390679f6cf9a2ad653a3e802c87d3"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:22d65d18b4ee8070a5fea5761d59293f1f9e2fac37ec9ce090463b0e629432fd"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c40cde976c36693cc0767e27cf5f443f91c23520060bd9496678364adfafe9c"}, + {file = "matplotlib-3.7.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:39018a2b17592448fbfdf4b8352955e6c3905359939791d4ff429296494d1a0c"}, + {file = "matplotlib-3.7.3.tar.gz", hash = "sha256:f09b3dd6bdeb588de91f853bbb2d6f0ff8ab693485b0c49035eaa510cb4f142e"}, +] + +[package.dependencies] +contourpy = ">=1.0.1" +cycler = ">=0.10" +fonttools = ">=4.22.0" +importlib-resources = {version = ">=3.2.0", markers = "python_version < \"3.10\""} +kiwisolver = ">=1.0.1" +numpy = ">=1.20,<2" +packaging = ">=20.0" +pillow = ">=6.2.0" +pyparsing = ">=2.3.1" +python-dateutil = ">=2.7" +setuptools_scm = ">=7" + +[[package]] +name = "modin" +version = "0.17.1" +description = "Modin: Make your pandas code run faster by changing one line of code." +optional = false +python-versions = ">=3.6" +files = [ + {file = "modin-0.17.1-py3-none-any.whl", hash = "sha256:4d9e660f413cf275dc91cf45da8ac425de70528c203c3acedb094ee816e2e1dc"}, + {file = "modin-0.17.1.tar.gz", hash = "sha256:a45a7fbc48a7f30fb0e02e60ad71d609e45fe5947aae74a87fefaa0021bd4e94"}, +] + +[package.dependencies] +fsspec = "*" +numpy = ">=1.18.5" +packaging = "*" +pandas = "1.5.2" +psutil = "*" + +[package.extras] +all = ["boto3", "cloudpickle", "dask (>=2.22.0)", "distributed (>=2.22.0)", "modin-spreadsheet (>=0.1.0)", "pyarrow (>=4.0.1)", "ray[default] (>=1.4.0,<2.1.0)", "redis (>=3.5.0,<4.0.0)", "rpyc (==4.1.5)"] +dask = ["dask (>=2.22.0)", "distributed (>=2.22.0)"] +ray = ["pyarrow (>=4.0.1)", "ray[default] (>=1.4.0,<2.1.0)", "redis (>=3.5.0,<4.0.0)"] +remote = ["boto3", "cloudpickle", "rpyc (==4.1.5)"] +spreadsheet = ["modin-spreadsheet (>=0.1.0)"] +sql = ["dfsql (>=0.4.2)", "pyparsing (<=2.4.7)"] + +[[package]] +name = "mpmath" +version = "1.3.0" +description = "Python library for arbitrary-precision floating-point arithmetic" +optional = false +python-versions = "*" +files = [ + {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, + {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, +] + +[package.extras] +develop = ["codecov", "pycodestyle", "pytest (>=4.6)", "pytest-cov", "wheel"] +docs = ["sphinx"] +gmpy = ["gmpy2 (>=2.1.0a4)"] +tests = ["pytest (>=4.6)"] + +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + +[[package]] +name = "mypy" +version = "1.6.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mypy-1.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e5012e5cc2ac628177eaac0e83d622b2dd499e28253d4107a08ecc59ede3fc2c"}, + {file = "mypy-1.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d8fbb68711905f8912e5af474ca8b78d077447d8f3918997fecbf26943ff3cbb"}, + {file = "mypy-1.6.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a1ad938fee7d2d96ca666c77b7c494c3c5bd88dff792220e1afbebb2925b5e"}, + {file = "mypy-1.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b96ae2c1279d1065413965c607712006205a9ac541895004a1e0d4f281f2ff9f"}, + {file = "mypy-1.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:40b1844d2e8b232ed92e50a4bd11c48d2daa351f9deee6c194b83bf03e418b0c"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:81af8adaa5e3099469e7623436881eff6b3b06db5ef75e6f5b6d4871263547e5"}, + {file = "mypy-1.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8c223fa57cb154c7eab5156856c231c3f5eace1e0bed9b32a24696b7ba3c3245"}, + {file = "mypy-1.6.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8032e00ce71c3ceb93eeba63963b864bf635a18f6c0c12da6c13c450eedb183"}, + {file = "mypy-1.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4c46b51de523817a0045b150ed11b56f9fff55f12b9edd0f3ed35b15a2809de0"}, + {file = "mypy-1.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:19f905bcfd9e167159b3d63ecd8cb5e696151c3e59a1742e79bc3bcb540c42c7"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:82e469518d3e9a321912955cc702d418773a2fd1e91c651280a1bda10622f02f"}, + {file = "mypy-1.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d4473c22cc296425bbbce7e9429588e76e05bc7342da359d6520b6427bf76660"}, + {file = "mypy-1.6.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59a0d7d24dfb26729e0a068639a6ce3500e31d6655df8557156c51c1cb874ce7"}, + {file = "mypy-1.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cfd13d47b29ed3bbaafaff7d8b21e90d827631afda134836962011acb5904b71"}, + {file = "mypy-1.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:eb4f18589d196a4cbe5290b435d135dee96567e07c2b2d43b5c4621b6501531a"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:41697773aa0bf53ff917aa077e2cde7aa50254f28750f9b88884acea38a16169"}, + {file = "mypy-1.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7274b0c57737bd3476d2229c6389b2ec9eefeb090bbaf77777e9d6b1b5a9d143"}, + {file = "mypy-1.6.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbaf4662e498c8c2e352da5f5bca5ab29d378895fa2d980630656178bd607c46"}, + {file = "mypy-1.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bb8ccb4724f7d8601938571bf3f24da0da791fe2db7be3d9e79849cb64e0ae85"}, + {file = "mypy-1.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:68351911e85145f582b5aa6cd9ad666c8958bcae897a1bfda8f4940472463c45"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:49ae115da099dcc0922a7a895c1eec82c1518109ea5c162ed50e3b3594c71208"}, + {file = "mypy-1.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8b27958f8c76bed8edaa63da0739d76e4e9ad4ed325c814f9b3851425582a3cd"}, + {file = "mypy-1.6.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:925cd6a3b7b55dfba252b7c4561892311c5358c6b5a601847015a1ad4eb7d332"}, + {file = "mypy-1.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f57e6b6927a49550da3d122f0cb983d400f843a8a82e65b3b380d3d7259468f"}, + {file = "mypy-1.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:a43ef1c8ddfdb9575691720b6352761f3f53d85f1b57d7745701041053deff30"}, + {file = "mypy-1.6.1-py3-none-any.whl", hash = "sha256:4cbe68ef919c28ea561165206a2dcb68591c50f3bcf777932323bc208d949cf1"}, + {file = "mypy-1.6.1.tar.gz", hash = "sha256:4d01c00d09a0be62a4ca3f933e315455bde83f37f892ba4b08ce92f3cf44bcc1"}, +] + +[package.dependencies] +mypy-extensions = ">=1.0.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=4.1.0" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "networkx" +version = "3.1" +description = "Python package for creating and manipulating graphs and networks" +optional = false +python-versions = ">=3.8" +files = [ + {file = "networkx-3.1-py3-none-any.whl", hash = "sha256:4f33f68cb2afcf86f28a45f43efc27a9386b535d567d2127f8f61d51dec58d36"}, + {file = "networkx-3.1.tar.gz", hash = "sha256:de346335408f84de0eada6ff9fafafff9bcda11f0a0dfaa931133debb146ab61"}, +] + +[package.extras] +default = ["matplotlib (>=3.4)", "numpy (>=1.20)", "pandas (>=1.3)", "scipy (>=1.8)"] +developer = ["mypy (>=1.1)", "pre-commit (>=3.2)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.4)", "pydata-sphinx-theme (>=0.13)", "sphinx (>=6.1)", "sphinx-gallery (>=0.12)", "texext (>=0.6.7)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.10)", "sympy (>=1.10)"] +test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] + +[[package]] +name = "nodeenv" +version = "1.8.0" +description = "Node.js virtual environment builder" +optional = false +python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +files = [ + {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, + {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, +] + +[package.dependencies] +setuptools = "*" + +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + +[[package]] +name = "oauthlib" +version = "3.2.2" +description = "A generic, spec-compliant, thorough implementation of the OAuth request-signing logic" +optional = false +python-versions = ">=3.6" +files = [ + {file = "oauthlib-3.2.2-py3-none-any.whl", hash = "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca"}, + {file = "oauthlib-3.2.2.tar.gz", hash = "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918"}, +] + +[package.extras] +rsa = ["cryptography (>=3.0.0)"] +signals = ["blinker (>=1.4.0)"] +signedtoken = ["cryptography (>=3.0.0)", "pyjwt (>=2.0.0,<3)"] + +[[package]] +name = "optuna" +version = "3.4.0" +description = "A hyperparameter optimization framework" +optional = false +python-versions = ">=3.7" +files = [ + {file = "optuna-3.4.0-py3-none-any.whl", hash = "sha256:4854a6e6ec68eae3f1cbf18525abde1fcf2a22dd4f3b79912e5d43f539ba8eb1"}, + {file = "optuna-3.4.0.tar.gz", hash = "sha256:aa4a2d294ca047d7dc16292707c018cc619bdde1ec435d34721311428942d2db"}, +] + +[package.dependencies] +alembic = ">=1.5.0" +colorlog = "*" +numpy = "*" +packaging = ">=20.0" +PyYAML = "*" +sqlalchemy = ">=1.3.0" +tqdm = "*" + +[package.extras] +benchmark = ["asv (>=0.5.0)", "botorch", "cma", "scikit-optimize", "virtualenv"] +checking = ["black", "blackdoc", "flake8", "isort", "mypy", "mypy-boto3-s3", "types-PyYAML", "types-redis", "types-setuptools", "types-tqdm", "typing-extensions (>=3.10.0.0)"] +document = ["ase", "botorch", "cma", "cmaes (>=0.10.0)", "distributed", "fvcore", "lightgbm", "matplotlib (!=3.6.0)", "mlflow", "pandas", "pillow", "plotly (>=4.9.0)", "scikit-learn", "scikit-optimize", "sphinx", "sphinx-copybutton", "sphinx-gallery", "sphinx-plotly-directive", "sphinx-rtd-theme (>=1.2.0)", "torch", "torchaudio", "torchvision"] +integration = ["botorch (>=0.4.0)", "catboost (>=0.26)", "catboost (>=0.26,<1.2)", "cma", "distributed", "fastai", "lightgbm", "mlflow", "pandas", "pytorch-ignite", "pytorch-lightning (>=1.6.0)", "scikit-learn (>=0.24.2)", "scikit-optimize", "shap", "tensorflow", "torch", "torchaudio", "torchvision", "wandb", "xgboost"] +optional = ["boto3", "botorch", "cmaes (>=0.10.0)", "google-cloud-storage", "matplotlib (!=3.6.0)", "pandas", "plotly (>=4.9.0)", "redis", "scikit-learn (>=0.24.2)"] +test = ["coverage", "fakeredis[lua]", "kaleido", "moto", "pytest", "scipy (>=1.9.2)"] + +[[package]] +name = "ordereddict" +version = "1.1" +description = "A drop-in substitute for Py2.7's new collections.OrderedDict that works in Python 2.4-2.6." +optional = false +python-versions = "*" +files = [ + {file = "ordereddict-1.1.tar.gz", hash = "sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pandas" +version = "1.5.2" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-1.5.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e9dbacd22555c2d47f262ef96bb4e30880e5956169741400af8b306bbb24a273"}, + {file = "pandas-1.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e2b83abd292194f350bb04e188f9379d36b8dfac24dd445d5c87575f3beaf789"}, + {file = "pandas-1.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2552bffc808641c6eb471e55aa6899fa002ac94e4eebfa9ec058649122db5824"}, + {file = "pandas-1.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fc87eac0541a7d24648a001d553406f4256e744d92df1df8ebe41829a915028"}, + {file = "pandas-1.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0d8fd58df5d17ddb8c72a5075d87cd80d71b542571b5f78178fb067fa4e9c72"}, + {file = "pandas-1.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:4aed257c7484d01c9a194d9a94758b37d3d751849c05a0050c087a358c41ad1f"}, + {file = "pandas-1.5.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:375262829c8c700c3e7cbb336810b94367b9c4889818bbd910d0ecb4e45dc261"}, + {file = "pandas-1.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc3cd122bea268998b79adebbb8343b735a5511ec14efb70a39e7acbc11ccbdc"}, + {file = "pandas-1.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b4f5a82afa4f1ff482ab8ded2ae8a453a2cdfde2001567b3ca24a4c5c5ca0db3"}, + {file = "pandas-1.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8092a368d3eb7116e270525329a3e5c15ae796ccdf7ccb17839a73b4f5084a39"}, + {file = "pandas-1.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6257b314fc14958f8122779e5a1557517b0f8e500cfb2bd53fa1f75a8ad0af2"}, + {file = "pandas-1.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:82ae615826da838a8e5d4d630eb70c993ab8636f0eff13cb28aafc4291b632b5"}, + {file = "pandas-1.5.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:457d8c3d42314ff47cc2d6c54f8fc0d23954b47977b2caed09cd9635cb75388b"}, + {file = "pandas-1.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c009a92e81ce836212ce7aa98b219db7961a8b95999b97af566b8dc8c33e9519"}, + {file = "pandas-1.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:71f510b0efe1629bf2f7c0eadb1ff0b9cf611e87b73cd017e6b7d6adb40e2b3a"}, + {file = "pandas-1.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a40dd1e9f22e01e66ed534d6a965eb99546b41d4d52dbdb66565608fde48203f"}, + {file = "pandas-1.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ae7e989f12628f41e804847a8cc2943d362440132919a69429d4dea1f164da0"}, + {file = "pandas-1.5.2-cp38-cp38-win32.whl", hash = "sha256:530948945e7b6c95e6fa7aa4be2be25764af53fba93fe76d912e35d1c9ee46f5"}, + {file = "pandas-1.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:73f219fdc1777cf3c45fde7f0708732ec6950dfc598afc50588d0d285fddaefc"}, + {file = "pandas-1.5.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:9608000a5a45f663be6af5c70c3cbe634fa19243e720eb380c0d378666bc7702"}, + {file = "pandas-1.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:315e19a3e5c2ab47a67467fc0362cb36c7c60a93b6457f675d7d9615edad2ebe"}, + {file = "pandas-1.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e18bc3764cbb5e118be139b3b611bc3fbc5d3be42a7e827d1096f46087b395eb"}, + {file = "pandas-1.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0183cb04a057cc38fde5244909fca9826d5d57c4a5b7390c0cc3fa7acd9fa883"}, + {file = "pandas-1.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:344021ed3e639e017b452aa8f5f6bf38a8806f5852e217a7594417fb9bbfa00e"}, + {file = "pandas-1.5.2-cp39-cp39-win32.whl", hash = "sha256:e7469271497960b6a781eaa930cba8af400dd59b62ec9ca2f4d31a19f2f91090"}, + {file = "pandas-1.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:c218796d59d5abd8780170c937b812c9637e84c32f8271bbf9845970f8c1351f"}, + {file = "pandas-1.5.2.tar.gz", hash = "sha256:220b98d15cee0b2cd839a6358bd1f273d0356bf964c1a1aeb32d47db0215488b"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, +] +python-dateutil = ">=2.8.1" +pytz = ">=2020.1" + +[package.extras] +test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] + +[[package]] +name = "pandas-datareader" +version = "0.10.0" +description = "Data readers extracted from the pandas codebase,should be compatible with recent pandas versions" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pandas-datareader-0.10.0.tar.gz", hash = "sha256:9fc3c63d39bc0c10c2683f1c6d503ff625020383e38f6cbe14134826b454d5a6"}, + {file = "pandas_datareader-0.10.0-py3-none-any.whl", hash = "sha256:0b95ff3635bc3ee1a6073521b557ab0e3c39d219f4a3b720b6b0bc6e8cdb4bb7"}, +] + +[package.dependencies] +lxml = "*" +pandas = ">=0.23" +requests = ">=2.19.0" + +[[package]] +name = "pathtools" +version = "0.1.2" +description = "File system general utilities" +optional = false +python-versions = "*" +files = [ + {file = "pathtools-0.1.2.tar.gz", hash = "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"}, +] + +[[package]] +name = "pillow" +version = "10.1.0" +description = "Python Imaging Library (Fork)" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Pillow-10.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:1ab05f3db77e98f93964697c8efc49c7954b08dd61cff526b7f2531a22410106"}, + {file = "Pillow-10.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6932a7652464746fcb484f7fc3618e6503d2066d853f68a4bd97193a3996e273"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f63b5a68daedc54c7c3464508d8c12075e56dcfbd42f8c1bf40169061ae666"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0949b55eb607898e28eaccb525ab104b2d86542a85c74baf3a6dc24002edec2"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:ae88931f93214777c7a3aa0a8f92a683f83ecde27f65a45f95f22d289a69e593"}, + {file = "Pillow-10.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b0eb01ca85b2361b09480784a7931fc648ed8b7836f01fb9241141b968feb1db"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d27b5997bdd2eb9fb199982bb7eb6164db0426904020dc38c10203187ae2ff2f"}, + {file = "Pillow-10.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7df5608bc38bd37ef585ae9c38c9cd46d7c81498f086915b0f97255ea60c2818"}, + {file = "Pillow-10.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:41f67248d92a5e0a2076d3517d8d4b1e41a97e2df10eb8f93106c89107f38b57"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1fb29c07478e6c06a46b867e43b0bcdb241b44cc52be9bc25ce5944eed4648e7"}, + {file = "Pillow-10.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2cdc65a46e74514ce742c2013cd4a2d12e8553e3a2563c64879f7c7e4d28bce7"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50d08cd0a2ecd2a8657bd3d82c71efd5a58edb04d9308185d66c3a5a5bed9610"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:062a1610e3bc258bff2328ec43f34244fcec972ee0717200cb1425214fe5b839"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:61f1a9d247317fa08a308daaa8ee7b3f760ab1809ca2da14ecc88ae4257d6172"}, + {file = "Pillow-10.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:a646e48de237d860c36e0db37ecaecaa3619e6f3e9d5319e527ccbc8151df061"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:47e5bf85b80abc03be7455c95b6d6e4896a62f6541c1f2ce77a7d2bb832af262"}, + {file = "Pillow-10.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a92386125e9ee90381c3369f57a2a50fa9e6aa8b1cf1d9c4b200d41a7dd8e992"}, + {file = "Pillow-10.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0f7c276c05a9767e877a0b4c5050c8bee6a6d960d7f0c11ebda6b99746068c2a"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_10_10_x86_64.whl", hash = "sha256:a89b8312d51715b510a4fe9fc13686283f376cfd5abca8cd1c65e4c76e21081b"}, + {file = "Pillow-10.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:00f438bb841382b15d7deb9a05cc946ee0f2c352653c7aa659e75e592f6fa17d"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d929a19f5469b3f4df33a3df2983db070ebb2088a1e145e18facbc28cae5b27"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a92109192b360634a4489c0c756364c0c3a2992906752165ecb50544c251312"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:0248f86b3ea061e67817c47ecbe82c23f9dd5d5226200eb9090b3873d3ca32de"}, + {file = "Pillow-10.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9882a7451c680c12f232a422730f986a1fcd808da0fd428f08b671237237d651"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1c3ac5423c8c1da5928aa12c6e258921956757d976405e9467c5f39d1d577a4b"}, + {file = "Pillow-10.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:806abdd8249ba3953c33742506fe414880bad78ac25cc9a9b1c6ae97bedd573f"}, + {file = "Pillow-10.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:eaed6977fa73408b7b8a24e8b14e59e1668cfc0f4c40193ea7ced8e210adf996"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:fe1e26e1ffc38be097f0ba1d0d07fcade2bcfd1d023cda5b29935ae8052bd793"}, + {file = "Pillow-10.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7e3daa202beb61821c06d2517428e8e7c1aab08943e92ec9e5755c2fc9ba5e"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24fadc71218ad2b8ffe437b54876c9382b4a29e030a05a9879f615091f42ffc2"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa1d323703cfdac2036af05191b969b910d8f115cf53093125e4058f62012c9a"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:912e3812a1dbbc834da2b32299b124b5ddcb664ed354916fd1ed6f193f0e2d01"}, + {file = "Pillow-10.1.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7dbaa3c7de82ef37e7708521be41db5565004258ca76945ad74a8e998c30af8d"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:9d7bc666bd8c5a4225e7ac71f2f9d12466ec555e89092728ea0f5c0c2422ea80"}, + {file = "Pillow-10.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baada14941c83079bf84c037e2d8b7506ce201e92e3d2fa0d1303507a8538212"}, + {file = "Pillow-10.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:2ef6721c97894a7aa77723740a09547197533146fba8355e86d6d9a4a1056b14"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:0a026c188be3b443916179f5d04548092e253beb0c3e2ee0a4e2cdad72f66099"}, + {file = "Pillow-10.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04f6f6149f266a100374ca3cc368b67fb27c4af9f1cc8cb6306d849dcdf12616"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb40c011447712d2e19cc261c82655f75f32cb724788df315ed992a4d65696bb"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a8413794b4ad9719346cd9306118450b7b00d9a15846451549314a58ac42219"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:c9aeea7b63edb7884b031a35305629a7593272b54f429a9869a4f63a1bf04c34"}, + {file = "Pillow-10.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:b4005fee46ed9be0b8fb42be0c20e79411533d1fd58edabebc0dd24626882cfd"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0152565c6aa6ebbfb1e5d8624140a440f2b99bf7afaafbdbf6430426497f28"}, + {file = "Pillow-10.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d921bc90b1defa55c9917ca6b6b71430e4286fc9e44c55ead78ca1a9f9eba5f2"}, + {file = "Pillow-10.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfe96560c6ce2f4c07d6647af2d0f3c54cc33289894ebd88cfbb3bcd5391e256"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-macosx_10_10_x86_64.whl", hash = "sha256:937bdc5a7f5343d1c97dc98149a0be7eb9704e937fe3dc7140e229ae4fc572a7"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c25762197144e211efb5f4e8ad656f36c8d214d390585d1d21281f46d556ba"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:afc8eef765d948543a4775f00b7b8c079b3321d6b675dde0d02afa2ee23000b4"}, + {file = "Pillow-10.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:883f216eac8712b83a63f41b76ddfb7b2afab1b74abbb413c5df6680f071a6b9"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-macosx_10_10_x86_64.whl", hash = "sha256:b920e4d028f6442bea9a75b7491c063f0b9a3972520731ed26c83e254302eb1e"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c41d960babf951e01a49c9746f92c5a7e0d939d1652d7ba30f6b3090f27e412"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1fafabe50a6977ac70dfe829b2d5735fd54e190ab55259ec8aea4aaea412fa0b"}, + {file = "Pillow-10.1.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3b834f4b16173e5b92ab6566f0473bfb09f939ba14b23b8da1f54fa63e4b623f"}, + {file = "Pillow-10.1.0.tar.gz", hash = "sha256:e6bf8de6c36ed96c86ea3b6e1d5273c53f46ef518a062464cd7ef5dd2cf92e38"}, +] + +[package.extras] +docs = ["furo", "olefile", "sphinx (>=2.4)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-removed-in", "sphinxext-opengraph"] +tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "platformdirs" +version = "3.11.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.11.0-py3-none-any.whl", hash = "sha256:e9d171d00af68be50e9202731309c4e658fd8bc76f55c11c7dd760d023bda68e"}, + {file = "platformdirs-3.11.0.tar.gz", hash = "sha256:cf8ee52a3afdb965072dcc652433e0c7e3e40cf5ea1477cd4b3b1d2eb75495b3"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "plotly" +version = "5.18.0" +description = "An open-source, interactive data visualization library for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "plotly-5.18.0-py3-none-any.whl", hash = "sha256:23aa8ea2f4fb364a20d34ad38235524bd9d691bf5299e800bca608c31e8db8de"}, + {file = "plotly-5.18.0.tar.gz", hash = "sha256:360a31e6fbb49d12b007036eb6929521343d6bee2236f8459915821baefa2cbb"}, +] + +[package.dependencies] +packaging = "*" +tenacity = ">=6.2.0" + +[[package]] +name = "pluggy" +version = "1.3.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, + {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pre-commit" +version = "3.5.0" +description = "A framework for managing and maintaining multi-language pre-commit hooks." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660"}, + {file = "pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32"}, +] + +[package.dependencies] +cfgv = ">=2.0.0" +identify = ">=1.0.0" +nodeenv = ">=0.11.1" +pyyaml = ">=5.1" +virtualenv = ">=20.10.0" + +[[package]] +name = "protobuf" +version = "4.24.4" +description = "" +optional = false +python-versions = ">=3.7" +files = [ + {file = "protobuf-4.24.4-cp310-abi3-win32.whl", hash = "sha256:ec9912d5cb6714a5710e28e592ee1093d68c5ebfeda61983b3f40331da0b1ebb"}, + {file = "protobuf-4.24.4-cp310-abi3-win_amd64.whl", hash = "sha256:1badab72aa8a3a2b812eacfede5020472e16c6b2212d737cefd685884c191085"}, + {file = "protobuf-4.24.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e61a27f362369c2f33248a0ff6896c20dcd47b5d48239cb9720134bef6082e4"}, + {file = "protobuf-4.24.4-cp37-abi3-manylinux2014_aarch64.whl", hash = "sha256:bffa46ad9612e6779d0e51ae586fde768339b791a50610d85eb162daeb23661e"}, + {file = "protobuf-4.24.4-cp37-abi3-manylinux2014_x86_64.whl", hash = "sha256:b493cb590960ff863743b9ff1452c413c2ee12b782f48beca77c8da3e2ffe9d9"}, + {file = "protobuf-4.24.4-cp37-cp37m-win32.whl", hash = "sha256:dbbed8a56e56cee8d9d522ce844a1379a72a70f453bde6243e3c86c30c2a3d46"}, + {file = "protobuf-4.24.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6b7d2e1c753715dcfe9d284a25a52d67818dd43c4932574307daf836f0071e37"}, + {file = "protobuf-4.24.4-cp38-cp38-win32.whl", hash = "sha256:02212557a76cd99574775a81fefeba8738d0f668d6abd0c6b1d3adcc75503dbe"}, + {file = "protobuf-4.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:2fa3886dfaae6b4c5ed2730d3bf47c7a38a72b3a1f0acb4d4caf68e6874b947b"}, + {file = "protobuf-4.24.4-cp39-cp39-win32.whl", hash = "sha256:b77272f3e28bb416e2071186cb39efd4abbf696d682cbb5dc731308ad37fa6dd"}, + {file = "protobuf-4.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:9fee5e8aa20ef1b84123bb9232b3f4a5114d9897ed89b4b8142d81924e05d79b"}, + {file = "protobuf-4.24.4-py3-none-any.whl", hash = "sha256:80797ce7424f8c8d2f2547e2d42bfbb6c08230ce5832d6c099a37335c9c90a92"}, + {file = "protobuf-4.24.4.tar.gz", hash = "sha256:5a70731910cd9104762161719c3d883c960151eea077134458503723b60e3667"}, +] + +[[package]] +name = "psutil" +version = "5.9.6" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "psutil-5.9.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fb8a697f11b0f5994550555fcfe3e69799e5b060c8ecf9e2f75c69302cc35c0d"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:91ecd2d9c00db9817a4b4192107cf6954addb5d9d67a969a4f436dbc9200f88c"}, + {file = "psutil-5.9.6-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:10e8c17b4f898d64b121149afb136c53ea8b68c7531155147867b7b1ac9e7e28"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:18cd22c5db486f33998f37e2bb054cc62fd06646995285e02a51b1e08da97017"}, + {file = "psutil-5.9.6-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:ca2780f5e038379e520281e4c032dddd086906ddff9ef0d1b9dcf00710e5071c"}, + {file = "psutil-5.9.6-cp27-none-win32.whl", hash = "sha256:70cb3beb98bc3fd5ac9ac617a327af7e7f826373ee64c80efd4eb2856e5051e9"}, + {file = "psutil-5.9.6-cp27-none-win_amd64.whl", hash = "sha256:51dc3d54607c73148f63732c727856f5febec1c7c336f8f41fcbd6315cce76ac"}, + {file = "psutil-5.9.6-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c69596f9fc2f8acd574a12d5f8b7b1ba3765a641ea5d60fb4736bf3c08a8214a"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:92e0cc43c524834af53e9d3369245e6cc3b130e78e26100d1f63cdb0abeb3d3c"}, + {file = "psutil-5.9.6-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:748c9dd2583ed86347ed65d0035f45fa8c851e8d90354c122ab72319b5f366f4"}, + {file = "psutil-5.9.6-cp36-cp36m-win32.whl", hash = "sha256:3ebf2158c16cc69db777e3c7decb3c0f43a7af94a60d72e87b2823aebac3d602"}, + {file = "psutil-5.9.6-cp36-cp36m-win_amd64.whl", hash = "sha256:ff18b8d1a784b810df0b0fff3bcb50ab941c3b8e2c8de5726f9c71c601c611aa"}, + {file = "psutil-5.9.6-cp37-abi3-win32.whl", hash = "sha256:a6f01f03bf1843280f4ad16f4bde26b817847b4c1a0db59bf6419807bc5ce05c"}, + {file = "psutil-5.9.6-cp37-abi3-win_amd64.whl", hash = "sha256:6e5fb8dc711a514da83098bc5234264e551ad980cec5f85dabf4d38ed6f15e9a"}, + {file = "psutil-5.9.6-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:daecbcbd29b289aac14ece28eca6a3e60aa361754cf6da3dfb20d4d32b6c7f57"}, + {file = "psutil-5.9.6.tar.gz", hash = "sha256:e4b92ddcd7dd4cdd3f900180ea1e104932c7bce234fb88976e2a3b296441225a"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "pyasn1" +version = "0.5.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, + {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, +] + +[[package]] +name = "pyasn1-modules" +version = "0.3.0" +description = "A collection of ASN.1-based protocols modules" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1_modules-0.3.0-py2.py3-none-any.whl", hash = "sha256:d3ccd6ed470d9ffbc716be08bd90efbd44d0734bc9303818f7336070984a162d"}, + {file = "pyasn1_modules-0.3.0.tar.gz", hash = "sha256:5bd01446b736eb9d31512a30d46c1ac3395d676c6f3cafa4c03eb54b9925631c"}, +] + +[package.dependencies] +pyasn1 = ">=0.4.6,<0.6.0" + +[[package]] +name = "pydantic" +version = "1.10.13" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, + {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, + {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, + {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, + {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, +] + +[package.dependencies] +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "pyparsing" +version = "3.1.1" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = false +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"}, + {file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + +[[package]] +name = "pyproject-api" +version = "1.6.1" +description = "API to interact with the python pyproject.toml based projects" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyproject_api-1.6.1-py3-none-any.whl", hash = "sha256:4c0116d60476b0786c88692cf4e325a9814965e2469c5998b830bba16b183675"}, + {file = "pyproject_api-1.6.1.tar.gz", hash = "sha256:1817dc018adc0d1ff9ca1ed8c60e1623d5aaca40814b953af14a9cf9a5cae538"}, +] + +[package.dependencies] +packaging = ">=23.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (<7.2)", "sphinx-autodoc-typehints (>=1.24)"] +testing = ["covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "setuptools (>=68.1.2)", "wheel (>=0.41.2)"] + +[[package]] +name = "pytest" +version = "7.4.3" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"}, + {file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "0.5.1" +description = "Add .env support to your django/flask apps in development and deployments" +optional = false +python-versions = "*" +files = [ + {file = "python-dotenv-0.5.1.tar.gz", hash = "sha256:d139a406b7dd0ecc161f0b9cd1620de93bda026fe3c776bd1216414898704c8d"}, + {file = "python_dotenv-0.5.1-py2.py3-none-any.whl", hash = "sha256:46d58321d745d9d6f23e802b51dec8c2320a43c1ef0423671ed2a084bbd77eff"}, +] + +[package.dependencies] +click = ">=5.0" +ordereddict = "*" + +[[package]] +name = "pytz" +version = "2023.3.post1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"}, + {file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.1" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"}, + {file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, + {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, + {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, + {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, + {file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, + {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, + {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, + {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, + {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, + {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"}, + {file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"}, + {file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"}, + {file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"}, + {file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"}, + {file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, + {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, + {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, + {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, + {file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, + {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, + {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, + {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, + {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-oauthlib" +version = "1.3.1" +description = "OAuthlib authentication support for Requests." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "requests-oauthlib-1.3.1.tar.gz", hash = "sha256:75beac4a47881eeb94d5ea5d6ad31ef88856affe2332b9aafb52c6452ccf0d7a"}, + {file = "requests_oauthlib-1.3.1-py2.py3-none-any.whl", hash = "sha256:2577c501a2fb8d05a304c09d090d6e47c306fef15809d102b327cf8364bddab5"}, +] + +[package.dependencies] +oauthlib = ">=3.0.0" +requests = ">=2.0.0" + +[package.extras] +rsa = ["oauthlib[signedtoken] (>=3.0.0)"] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruff" +version = "0.1.3" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.1.3-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:b46d43d51f7061652eeadb426a9e3caa1e0002470229ab2fc19de8a7b0766901"}, + {file = "ruff-0.1.3-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:b8afeb9abd26b4029c72adc9921b8363374f4e7edb78385ffaa80278313a15f9"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca3cf365bf32e9ba7e6db3f48a4d3e2c446cd19ebee04f05338bc3910114528b"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4874c165f96c14a00590dcc727a04dca0cfd110334c24b039458c06cf78a672e"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eec2dd31eed114e48ea42dbffc443e9b7221976554a504767ceaee3dd38edeb8"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:dc3ec4edb3b73f21b4aa51337e16674c752f1d76a4a543af56d7d04e97769613"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e3de9ed2e39160800281848ff4670e1698037ca039bda7b9274f849258d26ce"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c595193881922cc0556a90f3af99b1c5681f0c552e7a2a189956141d8666fe8"}, + {file = "ruff-0.1.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f75e670d529aa2288cd00fc0e9b9287603d95e1536d7a7e0cafe00f75e0dd9d"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:76dd49f6cd945d82d9d4a9a6622c54a994689d8d7b22fa1322983389b4892e20"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:918b454bc4f8874a616f0d725590277c42949431ceb303950e87fef7a7d94cb3"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d8859605e729cd5e53aa38275568dbbdb4fe882d2ea2714c5453b678dca83784"}, + {file = "ruff-0.1.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0b6c55f5ef8d9dd05b230bb6ab80bc4381ecb60ae56db0330f660ea240cb0d4a"}, + {file = "ruff-0.1.3-py3-none-win32.whl", hash = "sha256:3e7afcbdcfbe3399c34e0f6370c30f6e529193c731b885316c5a09c9e4317eef"}, + {file = "ruff-0.1.3-py3-none-win_amd64.whl", hash = "sha256:7a18df6638cec4a5bd75350639b2bb2a2366e01222825562c7346674bdceb7ea"}, + {file = "ruff-0.1.3-py3-none-win_arm64.whl", hash = "sha256:12fd53696c83a194a2db7f9a46337ce06445fb9aa7d25ea6f293cf75b21aca9f"}, + {file = "ruff-0.1.3.tar.gz", hash = "sha256:3ba6145369a151401d5db79f0a47d50e470384d0d89d0d6f7fab0b589ad07c34"}, +] + +[[package]] +name = "scikit-learn" +version = "1.3.2" +description = "A set of python modules for machine learning and data mining" +optional = false +python-versions = ">=3.8" +files = [ + {file = "scikit-learn-1.3.2.tar.gz", hash = "sha256:a2f54c76accc15a34bfb9066e6c7a56c1e7235dda5762b990792330b52ccfb05"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e326c0eb5cf4d6ba40f93776a20e9a7a69524c4db0757e7ce24ba222471ee8a1"}, + {file = "scikit_learn-1.3.2-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:535805c2a01ccb40ca4ab7d081d771aea67e535153e35a1fd99418fcedd1648a"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1215e5e58e9880b554b01187b8c9390bf4dc4692eedeaf542d3273f4785e342c"}, + {file = "scikit_learn-1.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ee107923a623b9f517754ea2f69ea3b62fc898a3641766cb7deb2f2ce450161"}, + {file = "scikit_learn-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:35a22e8015048c628ad099da9df5ab3004cdbf81edc75b396fd0cff8699ac58c"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6fb6bc98f234fda43163ddbe36df8bcde1d13ee176c6dc9b92bb7d3fc842eb66"}, + {file = "scikit_learn-1.3.2-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:18424efee518a1cde7b0b53a422cde2f6625197de6af36da0b57ec502f126157"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3271552a5eb16f208a6f7f617b8cc6d1f137b52c8a1ef8edf547db0259b2c9fb"}, + {file = "scikit_learn-1.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4144a5004a676d5022b798d9e573b05139e77f271253a4703eed295bde0433"}, + {file = "scikit_learn-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:67f37d708f042a9b8d59551cf94d30431e01374e00dc2645fa186059c6c5d78b"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8db94cd8a2e038b37a80a04df8783e09caac77cbe052146432e67800e430c028"}, + {file = "scikit_learn-1.3.2-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:61a6efd384258789aa89415a410dcdb39a50e19d3d8410bd29be365bcdd512d5"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb06f8dce3f5ddc5dee1715a9b9f19f20d295bed8e3cd4fa51e1d050347de525"}, + {file = "scikit_learn-1.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b2de18d86f630d68fe1f87af690d451388bb186480afc719e5f770590c2ef6c"}, + {file = "scikit_learn-1.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:0402638c9a7c219ee52c94cbebc8fcb5eb9fe9c773717965c1f4185588ad3107"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a19f90f95ba93c1a7f7924906d0576a84da7f3b2282ac3bfb7a08a32801add93"}, + {file = "scikit_learn-1.3.2-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:b8692e395a03a60cd927125eef3a8e3424d86dde9b2370d544f0ea35f78a8073"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15e1e94cc23d04d39da797ee34236ce2375ddea158b10bee3c343647d615581d"}, + {file = "scikit_learn-1.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:785a2213086b7b1abf037aeadbbd6d67159feb3e30263434139c98425e3dcfcf"}, + {file = "scikit_learn-1.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:64381066f8aa63c2710e6b56edc9f0894cc7bf59bd71b8ce5613a4559b6145e0"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6c43290337f7a4b969d207e620658372ba3c1ffb611f8bc2b6f031dc5c6d1d03"}, + {file = "scikit_learn-1.3.2-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:dc9002fc200bed597d5d34e90c752b74df516d592db162f756cc52836b38fe0e"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d08ada33e955c54355d909b9c06a4789a729977f165b8bae6f225ff0a60ec4a"}, + {file = "scikit_learn-1.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:763f0ae4b79b0ff9cca0bf3716bcc9915bdacff3cebea15ec79652d1cc4fa5c9"}, + {file = "scikit_learn-1.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:ed932ea780517b00dae7431e031faae6b49b20eb6950918eb83bd043237950e0"}, +] + +[package.dependencies] +joblib = ">=1.1.1" +numpy = ">=1.17.3,<2.0" +scipy = ">=1.5.0" +threadpoolctl = ">=2.0.0" + +[package.extras] +benchmark = ["matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "pandas (>=1.0.5)"] +docs = ["Pillow (>=7.1.2)", "matplotlib (>=3.1.3)", "memory-profiler (>=0.57.0)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)", "sphinx (>=6.0.0)", "sphinx-copybutton (>=0.5.2)", "sphinx-gallery (>=0.10.1)", "sphinx-prompt (>=1.3.0)", "sphinxext-opengraph (>=0.4.2)"] +examples = ["matplotlib (>=3.1.3)", "pandas (>=1.0.5)", "plotly (>=5.14.0)", "pooch (>=1.6.0)", "scikit-image (>=0.16.2)", "seaborn (>=0.9.0)"] +tests = ["black (>=23.3.0)", "matplotlib (>=3.1.3)", "mypy (>=1.3)", "numpydoc (>=1.2.0)", "pandas (>=1.0.5)", "pooch (>=1.6.0)", "pyamg (>=4.0.0)", "pytest (>=7.1.2)", "pytest-cov (>=2.9.0)", "ruff (>=0.0.272)", "scikit-image (>=0.16.2)"] + +[[package]] +name = "scipy" +version = "1.9.3" +description = "Fundamental algorithms for scientific computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "scipy-1.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1884b66a54887e21addf9c16fb588720a8309a57b2e258ae1c7986d4444d3bc0"}, + {file = "scipy-1.9.3-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:83b89e9586c62e787f5012e8475fbb12185bafb996a03257e9675cd73d3736dd"}, + {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a72d885fa44247f92743fc20732ae55564ff2a519e8302fb7e18717c5355a8b"}, + {file = "scipy-1.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d01e1dd7b15bd2449c8bfc6b7cc67d630700ed655654f0dfcf121600bad205c9"}, + {file = "scipy-1.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:68239b6aa6f9c593da8be1509a05cb7f9efe98b80f43a5861cd24c7557e98523"}, + {file = "scipy-1.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b41bc822679ad1c9a5f023bc93f6d0543129ca0f37c1ce294dd9d386f0a21096"}, + {file = "scipy-1.9.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:90453d2b93ea82a9f434e4e1cba043e779ff67b92f7a0e85d05d286a3625df3c"}, + {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83c06e62a390a9167da60bedd4575a14c1f58ca9dfde59830fc42e5197283dab"}, + {file = "scipy-1.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:abaf921531b5aeaafced90157db505e10345e45038c39e5d9b6c7922d68085cb"}, + {file = "scipy-1.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:06d2e1b4c491dc7d8eacea139a1b0b295f74e1a1a0f704c375028f8320d16e31"}, + {file = "scipy-1.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5a04cd7d0d3eff6ea4719371cbc44df31411862b9646db617c99718ff68d4840"}, + {file = "scipy-1.9.3-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:545c83ffb518094d8c9d83cce216c0c32f8c04aaf28b92cc8283eda0685162d5"}, + {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d54222d7a3ba6022fdf5773931b5d7c56efe41ede7f7128c7b1637700409108"}, + {file = "scipy-1.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cff3a5295234037e39500d35316a4c5794739433528310e117b8a9a0c76d20fc"}, + {file = "scipy-1.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:2318bef588acc7a574f5bfdff9c172d0b1bf2c8143d9582e05f878e580a3781e"}, + {file = "scipy-1.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d644a64e174c16cb4b2e41dfea6af722053e83d066da7343f333a54dae9bc31c"}, + {file = "scipy-1.9.3-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:da8245491d73ed0a994ed9c2e380fd058ce2fa8a18da204681f2fe1f57f98f95"}, + {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4db5b30849606a95dcf519763dd3ab6fe9bd91df49eba517359e450a7d80ce2e"}, + {file = "scipy-1.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c68db6b290cbd4049012990d7fe71a2abd9ffbe82c0056ebe0f01df8be5436b0"}, + {file = "scipy-1.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:5b88e6d91ad9d59478fafe92a7c757d00c59e3bdc3331be8ada76a4f8d683f58"}, + {file = "scipy-1.9.3.tar.gz", hash = "sha256:fbc5c05c85c1a02be77b1ff591087c83bc44579c6d2bd9fb798bb64ea5e1a027"}, +] + +[package.dependencies] +numpy = ">=1.18.5,<1.26.0" + +[package.extras] +dev = ["flake8", "mypy", "pycodestyle", "typing_extensions"] +doc = ["matplotlib (>2)", "numpydoc", "pydata-sphinx-theme (==0.9.0)", "sphinx (!=4.1.0)", "sphinx-panels (>=0.5.2)", "sphinx-tabs"] +test = ["asv", "gmpy2", "mpmath", "pytest", "pytest-cov", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] + +[[package]] +name = "seaborn" +version = "0.12.2" +description = "Statistical data visualization" +optional = false +python-versions = ">=3.7" +files = [ + {file = "seaborn-0.12.2-py3-none-any.whl", hash = "sha256:ebf15355a4dba46037dfd65b7350f014ceb1f13c05e814eda2c9f5fd731afc08"}, + {file = "seaborn-0.12.2.tar.gz", hash = "sha256:374645f36509d0dcab895cba5b47daf0586f77bfe3b36c97c607db7da5be0139"}, +] + +[package.dependencies] +matplotlib = ">=3.1,<3.6.1 || >3.6.1" +numpy = ">=1.17,<1.24.0 || >1.24.0" +pandas = ">=0.25" + +[package.extras] +dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest-cov", "pytest-xdist"] +docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] +stats = ["scipy (>=1.3)", "statsmodels (>=0.10)"] + +[[package]] +name = "sentry-sdk" +version = "1.32.0" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = "*" +files = [ + {file = "sentry-sdk-1.32.0.tar.gz", hash = "sha256:935e8fbd7787a3702457393b74b13d89a5afb67185bc0af85c00cb27cbd42e7c"}, + {file = "sentry_sdk-1.32.0-py2.py3-none-any.whl", hash = "sha256:eeb0b3550536f3bbc05bb1c7e0feb3a78d74acb43b607159a606ed2ec0a33a4d"}, +] + +[package.dependencies] +certifi = "*" +urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +loguru = ["loguru (>=0.5)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure-eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] +name = "setproctitle" +version = "1.3.3" +description = "A Python module to customize the process title" +optional = false +python-versions = ">=3.7" +files = [ + {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:897a73208da48db41e687225f355ce993167079eda1260ba5e13c4e53be7f754"}, + {file = "setproctitle-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c331e91a14ba4076f88c29c777ad6b58639530ed5b24b5564b5ed2fd7a95452"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbbd6c7de0771c84b4aa30e70b409565eb1fc13627a723ca6be774ed6b9d9fa3"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c05ac48ef16ee013b8a326c63e4610e2430dbec037ec5c5b58fcced550382b74"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1342f4fdb37f89d3e3c1c0a59d6ddbedbde838fff5c51178a7982993d238fe4f"}, + {file = "setproctitle-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc74e84fdfa96821580fb5e9c0b0777c1c4779434ce16d3d62a9c4d8c710df39"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9617b676b95adb412bb69645d5b077d664b6882bb0d37bfdafbbb1b999568d85"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6a249415f5bb88b5e9e8c4db47f609e0bf0e20a75e8d744ea787f3092ba1f2d0"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:38da436a0aaace9add67b999eb6abe4b84397edf4a78ec28f264e5b4c9d53cd5"}, + {file = "setproctitle-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:da0d57edd4c95bf221b2ebbaa061e65b1788f1544977288bdf95831b6e44e44d"}, + {file = "setproctitle-1.3.3-cp310-cp310-win32.whl", hash = "sha256:a1fcac43918b836ace25f69b1dca8c9395253ad8152b625064415b1d2f9be4fb"}, + {file = "setproctitle-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:200620c3b15388d7f3f97e0ae26599c0c378fdf07ae9ac5a13616e933cbd2086"}, + {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:334f7ed39895d692f753a443102dd5fed180c571eb6a48b2a5b7f5b3564908c8"}, + {file = "setproctitle-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:950f6476d56ff7817a8fed4ab207727fc5260af83481b2a4b125f32844df513a"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:195c961f54a09eb2acabbfc90c413955cf16c6e2f8caa2adbf2237d1019c7dd8"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f05e66746bf9fe6a3397ec246fe481096664a9c97eb3fea6004735a4daf867fd"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5901a31012a40ec913265b64e48c2a4059278d9f4e6be628441482dd13fb8b5"}, + {file = "setproctitle-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64286f8a995f2cd934082b398fc63fca7d5ffe31f0e27e75b3ca6b4efda4e353"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:184239903bbc6b813b1a8fc86394dc6ca7d20e2ebe6f69f716bec301e4b0199d"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:664698ae0013f986118064b6676d7dcd28fefd0d7d5a5ae9497cbc10cba48fa5"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e5119a211c2e98ff18b9908ba62a3bd0e3fabb02a29277a7232a6fb4b2560aa0"}, + {file = "setproctitle-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:417de6b2e214e837827067048f61841f5d7fc27926f2e43954567094051aff18"}, + {file = "setproctitle-1.3.3-cp311-cp311-win32.whl", hash = "sha256:6a143b31d758296dc2f440175f6c8e0b5301ced3b0f477b84ca43cdcf7f2f476"}, + {file = "setproctitle-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a680d62c399fa4b44899094027ec9a1bdaf6f31c650e44183b50d4c4d0ccc085"}, + {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:d4460795a8a7a391e3567b902ec5bdf6c60a47d791c3b1d27080fc203d11c9dc"}, + {file = "setproctitle-1.3.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bdfd7254745bb737ca1384dee57e6523651892f0ea2a7344490e9caefcc35e64"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477d3da48e216d7fc04bddab67b0dcde633e19f484a146fd2a34bb0e9dbb4a1e"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab2900d111e93aff5df9fddc64cf51ca4ef2c9f98702ce26524f1acc5a786ae7"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:088b9efc62d5aa5d6edf6cba1cf0c81f4488b5ce1c0342a8b67ae39d64001120"}, + {file = "setproctitle-1.3.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6d50252377db62d6a0bb82cc898089916457f2db2041e1d03ce7fadd4a07381"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:87e668f9561fd3a457ba189edfc9e37709261287b52293c115ae3487a24b92f6"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:287490eb90e7a0ddd22e74c89a92cc922389daa95babc833c08cf80c84c4df0a"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe1c49486109f72d502f8be569972e27f385fe632bd8895f4730df3c87d5ac8"}, + {file = "setproctitle-1.3.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4a6ba2494a6449b1f477bd3e67935c2b7b0274f2f6dcd0f7c6aceae10c6c6ba3"}, + {file = "setproctitle-1.3.3-cp312-cp312-win32.whl", hash = "sha256:2df2b67e4b1d7498632e18c56722851ba4db5d6a0c91aaf0fd395111e51cdcf4"}, + {file = "setproctitle-1.3.3-cp312-cp312-win_amd64.whl", hash = "sha256:f38d48abc121263f3b62943f84cbaede05749047e428409c2c199664feb6abc7"}, + {file = "setproctitle-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:816330675e3504ae4d9a2185c46b573105d2310c20b19ea2b4596a9460a4f674"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68f960bc22d8d8e4ac886d1e2e21ccbd283adcf3c43136161c1ba0fa509088e0"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00e6e7adff74796ef12753ff399491b8827f84f6c77659d71bd0b35870a17d8f"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53bc0d2358507596c22b02db079618451f3bd720755d88e3cccd840bafb4c41c"}, + {file = "setproctitle-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6d20f9541f5f6ac63df553b6d7a04f313947f550eab6a61aa758b45f0d5657"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c1c84beab776b0becaa368254801e57692ed749d935469ac10e2b9b825dbdd8e"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:507e8dc2891021350eaea40a44ddd887c9f006e6b599af8d64a505c0f718f170"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:b1067647ac7aba0b44b591936118a22847bda3c507b0a42d74272256a7a798e9"}, + {file = "setproctitle-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2e71f6365744bf53714e8bd2522b3c9c1d83f52ffa6324bd7cbb4da707312cd8"}, + {file = "setproctitle-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:7f1d36a1e15a46e8ede4e953abb104fdbc0845a266ec0e99cc0492a4364f8c44"}, + {file = "setproctitle-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:c9a402881ec269d0cc9c354b149fc29f9ec1a1939a777f1c858cdb09c7a261df"}, + {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ff814dea1e5c492a4980e3e7d094286077054e7ea116cbeda138819db194b2cd"}, + {file = "setproctitle-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:accb66d7b3ccb00d5cd11d8c6e07055a4568a24c95cf86109894dcc0c134cc89"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:554eae5a5b28f02705b83a230e9d163d645c9a08914c0ad921df363a07cf39b1"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a911b26264dbe9e8066c7531c0591cfab27b464459c74385b276fe487ca91c12"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2982efe7640c4835f7355fdb4da313ad37fb3b40f5c69069912f8048f77b28c8"}, + {file = "setproctitle-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df3f4274b80709d8bcab2f9a862973d453b308b97a0b423a501bcd93582852e3"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:af2c67ae4c795d1674a8d3ac1988676fa306bcfa1e23fddb5e0bd5f5635309ca"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:af4061f67fd7ec01624c5e3c21f6b7af2ef0e6bab7fbb43f209e6506c9ce0092"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:37a62cbe16d4c6294e84670b59cf7adcc73faafe6af07f8cb9adaf1f0e775b19"}, + {file = "setproctitle-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:a83ca086fbb017f0d87f240a8f9bbcf0809f3b754ee01cec928fff926542c450"}, + {file = "setproctitle-1.3.3-cp38-cp38-win32.whl", hash = "sha256:059f4ce86f8cc92e5860abfc43a1dceb21137b26a02373618d88f6b4b86ba9b2"}, + {file = "setproctitle-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:ab92e51cd4a218208efee4c6d37db7368fdf182f6e7ff148fb295ecddf264287"}, + {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c7951820b77abe03d88b114b998867c0f99da03859e5ab2623d94690848d3e45"}, + {file = "setproctitle-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc94cf128676e8fac6503b37763adb378e2b6be1249d207630f83fc325d9b11"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f5d9027eeda64d353cf21a3ceb74bb1760bd534526c9214e19f052424b37e42"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e4a8104db15d3462e29d9946f26bed817a5b1d7a47eabca2d9dc2b995991503"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c32c41ace41f344d317399efff4cffb133e709cec2ef09c99e7a13e9f3b9483c"}, + {file = "setproctitle-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbf16381c7bf7f963b58fb4daaa65684e10966ee14d26f5cc90f07049bfd8c1e"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e18b7bd0898398cc97ce2dfc83bb192a13a087ef6b2d5a8a36460311cb09e775"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:69d565d20efe527bd8a9b92e7f299ae5e73b6c0470f3719bd66f3cd821e0d5bd"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:ddedd300cd690a3b06e7eac90ed4452348b1348635777ce23d460d913b5b63c3"}, + {file = "setproctitle-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:415bfcfd01d1fbf5cbd75004599ef167a533395955305f42220a585f64036081"}, + {file = "setproctitle-1.3.3-cp39-cp39-win32.whl", hash = "sha256:21112fcd2195d48f25760f0eafa7a76510871bbb3b750219310cf88b04456ae3"}, + {file = "setproctitle-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:5a740f05d0968a5a17da3d676ce6afefebeeeb5ce137510901bf6306ba8ee002"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6b9e62ddb3db4b5205c0321dd69a406d8af9ee1693529d144e86bd43bcb4b6c0"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e3b99b338598de0bd6b2643bf8c343cf5ff70db3627af3ca427a5e1a1a90dd9"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ae9a02766dad331deb06855fb7a6ca15daea333b3967e214de12cfae8f0ef5"}, + {file = "setproctitle-1.3.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:200ede6fd11233085ba9b764eb055a2a191fb4ffb950c68675ac53c874c22e20"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0d3a953c50776751e80fe755a380a64cb14d61e8762bd43041ab3f8cc436092f"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5e08e232b78ba3ac6bc0d23ce9e2bee8fad2be391b7e2da834fc9a45129eb87"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1da82c3e11284da4fcbf54957dafbf0655d2389cd3d54e4eaba636faf6d117a"}, + {file = "setproctitle-1.3.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:aeaa71fb9568ebe9b911ddb490c644fbd2006e8c940f21cb9a1e9425bd709574"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:59335d000c6250c35989394661eb6287187854e94ac79ea22315469ee4f4c244"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3ba57029c9c50ecaf0c92bb127224cc2ea9fda057b5d99d3f348c9ec2855ad3"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d876d355c53d975c2ef9c4f2487c8f83dad6aeaaee1b6571453cb0ee992f55f6"}, + {file = "setproctitle-1.3.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:224602f0939e6fb9d5dd881be1229d485f3257b540f8a900d4271a2c2aa4e5f4"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d7f27e0268af2d7503386e0e6be87fb9b6657afd96f5726b733837121146750d"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f5e7266498cd31a4572378c61920af9f6b4676a73c299fce8ba93afd694f8ae7"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33c5609ad51cd99d388e55651b19148ea99727516132fb44680e1f28dd0d1de9"}, + {file = "setproctitle-1.3.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:eae8988e78192fd1a3245a6f4f382390b61bce6cfcc93f3809726e4c885fa68d"}, + {file = "setproctitle-1.3.3.tar.gz", hash = "sha256:c913e151e7ea01567837ff037a23ca8740192880198b7fbb90b16d181607caae"}, +] + +[package.extras] +test = ["pytest"] + +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + +[[package]] +name = "setuptools-scm" +version = "8.0.4" +description = "the blessed package to manage your versions by scm tags" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-scm-8.0.4.tar.gz", hash = "sha256:b5f43ff6800669595193fd09891564ee9d1d7dcb196cab4b2506d53a2e1c95c7"}, + {file = "setuptools_scm-8.0.4-py3-none-any.whl", hash = "sha256:b47844cd2a84b83b3187a5782c71128c28b4c94cad8bfb871da2784a5cb54c4f"}, +] + +[package.dependencies] +packaging = ">=20" +setuptools = "*" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} +typing-extensions = "*" + +[package.extras] +docs = ["entangled-cli[rich]", "mkdocs", "mkdocs-entangled-plugin", "mkdocs-material", "mkdocstrings[python]", "pygments"] +rich = ["rich"] +test = ["build", "pytest", "rich", "wheel"] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "smmap" +version = "5.0.1" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +files = [ + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, +] + +[[package]] +name = "sqlalchemy" +version = "2.0.22" +description = "Database Abstraction Library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f146c61ae128ab43ea3a0955de1af7e1633942c2b2b4985ac51cc292daf33222"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:875de9414393e778b655a3d97d60465eb3fae7c919e88b70cc10b40b9f56042d"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13790cb42f917c45c9c850b39b9941539ca8ee7917dacf099cc0b569f3d40da7"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04ab55cf49daf1aeb8c622c54d23fa4bec91cb051a43cc24351ba97e1dd09f5"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a42c9fa3abcda0dcfad053e49c4f752eef71ecd8c155221e18b99d4224621176"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14cd3bcbb853379fef2cd01e7c64a5d6f1d005406d877ed9509afb7a05ff40a5"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-win32.whl", hash = "sha256:d143c5a9dada696bcfdb96ba2de4a47d5a89168e71d05a076e88a01386872f97"}, + {file = "SQLAlchemy-2.0.22-cp310-cp310-win_amd64.whl", hash = "sha256:ccd87c25e4c8559e1b918d46b4fa90b37f459c9b4566f1dfbce0eb8122571547"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f6ff392b27a743c1ad346d215655503cec64405d3b694228b3454878bf21590"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f776c2c30f0e5f4db45c3ee11a5f2a8d9de68e81eb73ec4237de1e32e04ae81c"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8f1792d20d2f4e875ce7a113f43c3561ad12b34ff796b84002a256f37ce9437"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80eeb5189d7d4b1af519fc3f148fe7521b9dfce8f4d6a0820e8f5769b005051"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69fd9e41cf9368afa034e1c81f3570afb96f30fcd2eb1ef29cb4d9371c6eece2"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54bcceaf4eebef07dadfde424f5c26b491e4a64e61761dea9459103ecd6ccc95"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-win32.whl", hash = "sha256:7ee7ccf47aa503033b6afd57efbac6b9e05180f492aeed9fcf70752556f95624"}, + {file = "SQLAlchemy-2.0.22-cp311-cp311-win_amd64.whl", hash = "sha256:b560f075c151900587ade06706b0c51d04b3277c111151997ea0813455378ae0"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2c9bac865ee06d27a1533471405ad240a6f5d83195eca481f9fc4a71d8b87df8"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:625b72d77ac8ac23da3b1622e2da88c4aedaee14df47c8432bf8f6495e655de2"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39a6e21110204a8c08d40ff56a73ba542ec60bab701c36ce721e7990df49fb9"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a766cb0b468223cafdf63e2d37f14a4757476157927b09300c8c5832d88560"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0e1ce8ebd2e040357dde01a3fb7d30d9b5736b3e54a94002641dfd0aa12ae6ce"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:505f503763a767556fa4deae5194b2be056b64ecca72ac65224381a0acab7ebe"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-win32.whl", hash = "sha256:154a32f3c7b00de3d090bc60ec8006a78149e221f1182e3edcf0376016be9396"}, + {file = "SQLAlchemy-2.0.22-cp312-cp312-win_amd64.whl", hash = "sha256:129415f89744b05741c6f0b04a84525f37fbabe5dc3774f7edf100e7458c48cd"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3940677d341f2b685a999bffe7078697b5848a40b5f6952794ffcf3af150c301"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55914d45a631b81a8a2cb1a54f03eea265cf1783241ac55396ec6d735be14883"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096d6b018d242a2bcc9e451618166f860bb0304f590d205173d317b69986c95"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:19c6986cf2fb4bc8e0e846f97f4135a8e753b57d2aaaa87c50f9acbe606bd1db"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ac28bd6888fe3c81fbe97584eb0b96804bd7032d6100b9701255d9441373ec1"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-win32.whl", hash = "sha256:cb9a758ad973e795267da334a92dd82bb7555cb36a0960dcabcf724d26299db8"}, + {file = "SQLAlchemy-2.0.22-cp37-cp37m-win_amd64.whl", hash = "sha256:40b1206a0d923e73aa54f0a6bd61419a96b914f1cd19900b6c8226899d9742ad"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3aa1472bf44f61dd27987cd051f1c893b7d3b17238bff8c23fceaef4f1133868"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:56a7e2bb639df9263bf6418231bc2a92a773f57886d371ddb7a869a24919face"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccca778c0737a773a1ad86b68bda52a71ad5950b25e120b6eb1330f0df54c3d0"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6c3e9350f9fb16de5b5e5fbf17b578811a52d71bb784cc5ff71acb7de2a7f9"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:564e9f9e4e6466273dbfab0e0a2e5fe819eec480c57b53a2cdee8e4fdae3ad5f"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af66001d7b76a3fab0d5e4c1ec9339ac45748bc4a399cbc2baa48c1980d3c1f4"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-win32.whl", hash = "sha256:9e55dff5ec115316dd7a083cdc1a52de63693695aecf72bc53a8e1468ce429e5"}, + {file = "SQLAlchemy-2.0.22-cp38-cp38-win_amd64.whl", hash = "sha256:4e869a8ff7ee7a833b74868a0887e8462445ec462432d8cbeff5e85f475186da"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9886a72c8e6371280cb247c5d32c9c8fa141dc560124348762db8a8b236f8692"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a571bc8ac092a3175a1d994794a8e7a1f2f651e7c744de24a19b4f740fe95034"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db5ba8b7da759b727faebc4289a9e6a51edadc7fc32207a30f7c6203a181592"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0b3f2686c3f162123adba3cb8b626ed7e9b8433ab528e36ed270b4f70d1cdb"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c1fea8c0abcb070ffe15311853abfda4e55bf7dc1d4889497b3403629f3bf00"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4bb062784f37b2d75fd9b074c8ec360ad5df71f933f927e9e95c50eb8e05323c"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-win32.whl", hash = "sha256:58a3aba1bfb32ae7af68da3f277ed91d9f57620cf7ce651db96636790a78b736"}, + {file = "SQLAlchemy-2.0.22-cp39-cp39-win_amd64.whl", hash = "sha256:92e512a6af769e4725fa5b25981ba790335d42c5977e94ded07db7d641490a85"}, + {file = "SQLAlchemy-2.0.22-py3-none-any.whl", hash = "sha256:3076740335e4aaadd7deb3fe6dcb96b3015f1613bd190a4e1634e1b99b02ec86"}, + {file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""} +typing-extensions = ">=4.2.0" + +[package.extras] +aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] +asyncio = ["greenlet (!=0.4.17)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx-oracle (>=7)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] +sqlcipher = ["sqlcipher3-binary"] + +[[package]] +name = "sympy" +version = "1.12" +description = "Computer algebra system (CAS) in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, + {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, +] + +[package.dependencies] +mpmath = ">=0.19" + +[[package]] +name = "tenacity" +version = "8.2.3" +description = "Retry code until it succeeds" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, + {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, +] + +[package.extras] +doc = ["reno", "sphinx", "tornado (>=4.5)"] + +[[package]] +name = "threadpoolctl" +version = "3.2.0" +description = "threadpoolctl" +optional = false +python-versions = ">=3.8" +files = [ + {file = "threadpoolctl-3.2.0-py3-none-any.whl", hash = "sha256:2b7818516e423bdaebb97c723f86a7c6b0a83d3f3b0970328d66f4d9104dc032"}, + {file = "threadpoolctl-3.2.0.tar.gz", hash = "sha256:c96a0ba3bdddeaca37dc4cc7344aafad41cdb8c313f74fdfe387a867bba93355"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "torch" +version = "2.1.0" +description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "torch-2.1.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:bf57f8184b2c317ef81fb33dc233ce4d850cd98ef3f4a38be59c7c1572d175db"}, + {file = "torch-2.1.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:a04a0296d47f28960f51c18c5489a8c3472f624ec3b5bcc8e2096314df8c3342"}, + {file = "torch-2.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:0bd691efea319b14ef239ede16d8a45c246916456fa3ed4f217d8af679433cc6"}, + {file = "torch-2.1.0-cp310-none-macosx_10_9_x86_64.whl", hash = "sha256:101c139152959cb20ab370fc192672c50093747906ee4ceace44d8dd703f29af"}, + {file = "torch-2.1.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:a6b7438a90a870e4cdeb15301519ae6c043c883fcd224d303c5b118082814767"}, + {file = "torch-2.1.0-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:2224622407ca52611cbc5b628106fde22ed8e679031f5a99ce286629fc696128"}, + {file = "torch-2.1.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:8132efb782cd181cc2dcca5e58effbe4217cdb2581206ac71466d535bf778867"}, + {file = "torch-2.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:5c3bfa91ce25ba10116c224c59d5b64cdcce07161321d978bd5a1f15e1ebce72"}, + {file = "torch-2.1.0-cp311-none-macosx_10_9_x86_64.whl", hash = "sha256:601b0a2a9d9233fb4b81f7d47dca9680d4f3a78ca3f781078b6ad1ced8a90523"}, + {file = "torch-2.1.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:3cd1dedff13884d890f18eea620184fb4cd8fd3c68ce3300498f427ae93aa962"}, + {file = "torch-2.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fb7bf0cc1a3db484eb5d713942a93172f3bac026fcb377a0cd107093d2eba777"}, + {file = "torch-2.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:761822761fffaa1c18a62c5deb13abaa780862577d3eadc428f1daa632536905"}, + {file = "torch-2.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:458a6d6d8f7d2ccc348ac4d62ea661b39a3592ad15be385bebd0a31ced7e00f4"}, + {file = "torch-2.1.0-cp38-none-macosx_10_9_x86_64.whl", hash = "sha256:c8bf7eaf9514465e5d9101e05195183470a6215bb50295c61b52302a04edb690"}, + {file = "torch-2.1.0-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:05661c32ec14bc3a157193d0f19a7b19d8e61eb787b33353cad30202c295e83b"}, + {file = "torch-2.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:556d8dd3e0c290ed9d4d7de598a213fb9f7c59135b4fee144364a8a887016a55"}, + {file = "torch-2.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:de7d63c6ecece118684415a3dbd4805af4a4c1ee1490cccf7405d8c240a481b4"}, + {file = "torch-2.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:2419cf49aaf3b2336c7aa7a54a1b949fa295b1ae36f77e2aecb3a74e3a947255"}, + {file = "torch-2.1.0-cp39-none-macosx_10_9_x86_64.whl", hash = "sha256:6ad491e70dbe4288d17fdbfc7fbfa766d66cbe219bc4871c7a8096f4a37c98df"}, + {file = "torch-2.1.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:421739685eba5e0beba42cb649740b15d44b0d565c04e6ed667b41148734a75b"}, +] + +[package.dependencies] +filelock = "*" +fsspec = "*" +jinja2 = "*" +networkx = "*" +sympy = "*" +typing-extensions = "*" + +[package.extras] +opt-einsum = ["opt-einsum (>=3.3)"] + +[[package]] +name = "tox" +version = "4.11.3" +description = "tox is a generic virtualenv management and test command line tool" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tox-4.11.3-py3-none-any.whl", hash = "sha256:599af5e5bb0cad0148ac1558a0b66f8fff219ef88363483b8d92a81e4246f28f"}, + {file = "tox-4.11.3.tar.gz", hash = "sha256:5039f68276461fae6a9452a3b2c7295798f00a0e92edcd9a3b78ba1a73577951"}, +] + +[package.dependencies] +cachetools = ">=5.3.1" +chardet = ">=5.2" +colorama = ">=0.4.6" +filelock = ">=3.12.3" +packaging = ">=23.1" +platformdirs = ">=3.10" +pluggy = ">=1.3" +pyproject-api = ">=1.6.1" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} +virtualenv = ">=20.24.3" + +[package.extras] +docs = ["furo (>=2023.8.19)", "sphinx (>=7.2.4)", "sphinx-argparse-cli (>=1.11.1)", "sphinx-autodoc-typehints (>=1.24)", "sphinx-copybutton (>=0.5.2)", "sphinx-inline-tabs (>=2023.4.21)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +testing = ["build[virtualenv] (>=0.10)", "covdefaults (>=2.3)", "detect-test-pollution (>=1.1.1)", "devpi-process (>=1)", "diff-cover (>=7.7)", "distlib (>=0.3.7)", "flaky (>=3.7)", "hatch-vcs (>=0.3)", "hatchling (>=1.18)", "psutil (>=5.9.5)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)", "pytest-xdist (>=3.3.1)", "re-assert (>=1.1)", "time-machine (>=2.12)", "wheel (>=0.41.2)"] + +[[package]] +name = "tqdm" +version = "4.66.1" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + +[[package]] +name = "typer" +version = "0.9.0" +description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +optional = false +python-versions = ">=3.6" +files = [ + {file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"}, + {file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"}, +] + +[package.dependencies] +click = ">=7.1.1,<9.0.0" +typing-extensions = ">=3.7.4.3" + +[package.extras] +all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] +dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] +doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] +test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"] + +[[package]] +name = "typing-extensions" +version = "4.8.0" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"}, + {file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"}, +] + +[[package]] +name = "urllib3" +version = "2.0.7" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, + {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "virtualenv" +version = "20.24.6" +description = "Virtual Python Environment builder" +optional = false +python-versions = ">=3.7" +files = [ + {file = "virtualenv-20.24.6-py3-none-any.whl", hash = "sha256:520d056652454c5098a00c0f073611ccbea4c79089331f60bf9d7ba247bb7381"}, + {file = "virtualenv-20.24.6.tar.gz", hash = "sha256:02ece4f56fbf939dbbc33c0715159951d6bf14aaf5457b092e4548e1382455af"}, +] + +[package.dependencies] +distlib = ">=0.3.7,<1" +filelock = ">=3.12.2,<4" +platformdirs = ">=3.9.1,<4" + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.2)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"] +test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.4)", "pytest-env (>=0.8.2)", "pytest-freezer (>=0.4.8)", "pytest-mock (>=3.11.1)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=68)", "time-machine (>=2.10)"] + +[[package]] +name = "wandb" +version = "0.13.11" +description = "A CLI and library for interacting with the Weights and Biases API." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wandb-0.13.11-py3-none-any.whl", hash = "sha256:e584ac7fb0097fba8a030d5aedc5fea157286aba69a2e6e6e689b794155fcc8f"}, + {file = "wandb-0.13.11.tar.gz", hash = "sha256:f2b065d1c732e8e1828fabe720dc82f12e6109d0d2bbfbcccc17eaefae0fd7c9"}, +] + +[package.dependencies] +appdirs = ">=1.4.3" +Click = ">=7.0,<8.0.0 || >8.0.0" +docker-pycreds = ">=0.4.0" +GitPython = ">=1.0.0,<3.1.29 || >3.1.29" +pathtools = "*" +protobuf = [ + {version = ">=3.12.0,<4.21.0 || >4.21.0,<5", markers = "python_version < \"3.9\" and sys_platform == \"linux\""}, + {version = ">=3.15.0,<4.21.0 || >4.21.0,<5", markers = "python_version == \"3.9\" and sys_platform == \"linux\""}, + {version = ">=3.19.0,<4.21.0 || >4.21.0,<5", markers = "python_version > \"3.9\" or sys_platform != \"linux\""}, +] +psutil = ">=5.0.0" +PyYAML = "*" +requests = ">=2.0.0,<3" +sentry-sdk = ">=1.0.0" +setproctitle = "*" +setuptools = "*" +typing-extensions = {version = "*", markers = "python_version < \"3.10\""} + +[package.extras] +aws = ["boto3"] +azure = ["azure-storage-blob"] +gcp = ["google-cloud-storage"] +grpc = ["grpcio (>=1.27.2)"] +kubeflow = ["google-cloud-storage", "kubernetes", "minio", "sh"] +launch = ["awscli", "boto3", "botocore", "chardet", "google-auth", "google-cloud-artifact-registry", "google-cloud-compute", "google-cloud-storage", "iso8601", "kubernetes", "nbconvert", "nbformat", "typing-extensions"] +media = ["bokeh", "moviepy", "numpy", "pillow", "plotly", "rdkit-pypi", "soundfile"] +models = ["cloudpickle"] +sweeps = ["sweeps (>=0.2.0)"] + +[[package]] +name = "yarl" +version = "1.9.2" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"}, + {file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"}, + {file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"}, + {file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"}, + {file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"}, + {file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"}, + {file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"}, + {file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"}, + {file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"}, + {file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"}, + {file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"}, + {file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"}, + {file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"}, + {file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"}, + {file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"}, + {file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"}, + {file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"}, + {file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"}, + {file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"}, + {file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"}, + {file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"}, + {file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"}, + {file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"}, + {file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"}, + {file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"}, + {file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"}, + {file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "f4cc056b5b1b118e3e8cc2602c279b46435ec94920ace022c9d4ceb9eeb10c47" diff --git a/pyproject.toml b/pyproject.toml index f336965c..86f29cd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,16 +43,14 @@ typer = "^0.9.0" wandb = "^0.13.5" -[project.optional-dependencies] -dev = [ - "mypy", - "pre-commit", - "pytest", - "coverage", - "ruff", - "sphinx", - "tox", -] +[tool.poetry.group.dev.dependencies] +pre-commit = "^3.5.0" +ruff = "^0.1.3" +pytest-cov = "^4.1.0" +mypy = "^1.6.1" +tox = "^4.11.3" +pytest = "^7.4.3" + [project.urls] "Homepage" = "https://github.com/KarelZe/thesis" @@ -85,15 +83,12 @@ omit = [ [tool.ruff] # See rules: https://beta.ruff.rs/docs/rules/ select = [ -# "A", # flake8-builtins - "B", # flake8-bugbear "C", # flake8-comprehensions "D", # pydocstyle "E", # pycodestyle errors "F", # pyflakes "I", # isort "N", # pep8-naming - "NPY", # numpy "PD", # pandas-vet "PT", # pytest "PTH", # flake8-use-pathlib @@ -101,7 +96,6 @@ select = [ "RET", # return "RUF", # ruff-specific rules "UP", # pyupgrade - "S", # flake8-bandit "SIM", # flake8-simplify "W", # pycodestyle warnings ] @@ -113,7 +107,6 @@ ignore = [ "N803", # argument name should be lowercase "N806", # variable name should be lowercase "C901", # too complex - "S101", # use of assert "D206", # indent with white space "W191", # tab identation ] diff --git a/references/obsidian/.obsidian/app.json b/references/obsidian/.obsidian/app.json index c1ea76c5..e7a5e79d 100644 --- a/references/obsidian/.obsidian/app.json +++ b/references/obsidian/.obsidian/app.json @@ -1,23 +1,23 @@ -{ - "alwaysUpdateLinks": true, - "promptDelete": false, - "pdfExportSettings": { - "includeName": true, - "pageSize": "A4", - "landscape": false, - "margin": "0", - "downscalePercent": 100 - }, - "spellcheck": true, - "spellcheckDictionary": [ - "backpropagation" - ], - "legacyEditor": false, - "livePreview": true, - "attachmentFolderPath": "πŸ–ΌοΈMedia", - "readableLineLength": false, - "spellcheckLanguages": [ - "de", - "en-GB-oxendict" - ] +{ + "alwaysUpdateLinks": true, + "promptDelete": false, + "pdfExportSettings": { + "includeName": true, + "pageSize": "A4", + "landscape": false, + "margin": "0", + "downscalePercent": 100 + }, + "spellcheck": true, + "spellcheckDictionary": [ + "backpropagation" + ], + "legacyEditor": false, + "livePreview": true, + "attachmentFolderPath": "πŸ–ΌοΈMedia", + "readableLineLength": false, + "spellcheckLanguages": [ + "de", + "en-GB-oxendict" + ] } \ No newline at end of file diff --git a/references/obsidian/.obsidian/core-plugins-migration.json b/references/obsidian/.obsidian/core-plugins-migration.json index 4e635ba2..3c7dce84 100644 --- a/references/obsidian/.obsidian/core-plugins-migration.json +++ b/references/obsidian/.obsidian/core-plugins-migration.json @@ -1,30 +1,30 @@ -{ - "file-explorer": true, - "global-search": true, - "switcher": true, - "graph": true, - "backlink": true, - "outgoing-link": false, - "tag-pane": true, - "page-preview": true, - "daily-notes": false, - "templates": false, - "note-composer": true, - "command-palette": true, - "slash-command": false, - "editor-status": false, - "starred": false, - "markdown-importer": true, - "zk-prefixer": false, - "random-note": false, - "outline": true, - "word-count": true, - "slides": false, - "audio-recorder": false, - "workspaces": false, - "file-recovery": true, - "publish": false, - "sync": false, - "canvas": true, - "bookmarks": true +{ + "file-explorer": true, + "global-search": true, + "switcher": true, + "graph": true, + "backlink": true, + "outgoing-link": false, + "tag-pane": true, + "page-preview": true, + "daily-notes": false, + "templates": false, + "note-composer": true, + "command-palette": true, + "slash-command": false, + "editor-status": false, + "starred": false, + "markdown-importer": true, + "zk-prefixer": false, + "random-note": false, + "outline": true, + "word-count": true, + "slides": false, + "audio-recorder": false, + "workspaces": false, + "file-recovery": true, + "publish": false, + "sync": false, + "canvas": true, + "bookmarks": true } \ No newline at end of file diff --git a/src/otc/data/make_dataset.py b/src/otc/data/make_dataset.py index 1ef830d8..28444173 100644 --- a/src/otc/data/make_dataset.py +++ b/src/otc/data/make_dataset.py @@ -27,7 +27,6 @@ def main(input_filepath: click.Path, output_filepath: click.Path) -> None: if __name__ == "__main__": - with Path("logging.yaml").open() as file: loaded_config = yaml.safe_load(file) logging.config.dictConfig(loaded_config) diff --git a/src/otc/models/activation.py b/src/otc/models/activation.py index ac04f677..3b4167fc 100644 --- a/src/otc/models/activation.py +++ b/src/otc/models/activation.py @@ -4,7 +4,7 @@ https://github.com/Yura52/rtdl/blob/main/rtdl/functional.py """ import torch -import torch.nn.functional as F +import torch.nn.functional as F # noqa: N812 from torch import nn diff --git a/src/otc/models/callback.py b/src/otc/models/callback.py index dbbbbaa3..9eb4205c 100644 --- a/src/otc/models/callback.py +++ b/src/otc/models/callback.py @@ -132,7 +132,6 @@ def on_train_end( name (str): name of study. """ if study.best_trial == trial: - prefix_file = f"{study.study_name}_" f"{model.__class__.__name__}_{name}" uri_model: str @@ -317,10 +316,9 @@ def on_train_end( """Call on_train_end for each callback in container. Args: - study (optuna.Study): optuna study. - trial (optuna.trial.Trial | optuna.trial.FrozenTrial): - optuna trial. - model (TransformerClassifier | CatBoostClassifier): model. + study (optuna.Study): optuna study + trial (optuna.trial.Trial | optuna.trial.FrozenTrial): optuna trial + model (TransformerClassifier | CatBoostClassifier): model name (str): name of study. """ for callback in self.callbacks: diff --git a/src/otc/models/fttransformer.py b/src/otc/models/fttransformer.py index 796a62c6..73bc6208 100644 --- a/src/otc/models/fttransformer.py +++ b/src/otc/models/fttransformer.py @@ -394,8 +394,7 @@ def __init__(self, d_token: int, initialization: str) -> None: initialization_.apply(self.weight, d_token) def expand(self, *leading_dimensions: int) -> torch.Tensor: - """Expand (repeat) the underlying [CLS]-token to a tensor with the given\ - leading dimensions. + """Expand (repeat) the underlying [CLS]-token to a tensor with the given leading dimensions. A possible use case is building a batch of [CLS]-tokens. See `CLSToken` for examples of usage. @@ -624,7 +623,7 @@ def __init__( """Initialize the module. Args: - d_token (int): dimensionality of token. + d_token (int): dimensionality of token. d_hidden (int): dimensionality of hidden layers. bias_first (bool): flag indicating whether to use bias in the first bias_second (bool): flag indicating whether to use bias in the second @@ -670,8 +669,8 @@ def __init__( """Initialize the module. Args: - d_in (int): dimension of the input - bias (bool): add bias to the linear layer + d_in (int): dimension of the input + bias (bool): bias in linear layer activation (Callable[..., nn.Module]): activation function normalization (Callable[..., nn.Module]): normalization layer d_out (int): dimension of the output @@ -727,8 +726,7 @@ def __init__( n_blocks (int): number of blocks. attention_n_heads (int): number of attention heads. attention_dropout (float): degree of attention dropout. - attention_initialization (str): initialization strategy for attention - weights. + attention_initialization (str): initialization strategy for attention weights. attention_normalization (nn.Module): attention normalization layer. ffn_d_hidden (int): capacity of the hidden layers in the FFN. ffn_dropout (float): dropout in the FFN. @@ -736,18 +734,15 @@ def __init__( ffn_normalization (nn.Module): normalization layer in the FFN. residual_dropout (float): degree of residual dropout. prenormalization (bool): flag to use prenormalization. - first_prenormalization (bool): flag to use prenormalization in the first - layer. - last_layer_query_idx (None | list[int] | slice): query index for the - last layer. + first_prenormalization (bool): flag to use prenormalization in the first layer. + last_layer_query_idx (None | list[int] | slice): query index for the last layer. n_tokens (int | None): number of tokens. - kv_compression_ratio (float | None): compression ratio for the key and - values. - kv_compression_sharing (str | None): strategy for sharing the key and - values of compression. - head_activation (Callable[..., nn.Module]): activation function in the - attention head. + kv_compression_ratio (float | None): compression ratio for the key and values. + kv_compression_sharing (str | None): strategy for sharing the key and values of compression. + head_activation (Callable[..., nn.Module]): activation function in the attention head. + head_normalization (Callable[..., nn.Module]): normalization layer in the attention head. d_out (int): dimensionality of the output + **kwargs: keyword arguments Raises: ValueError: value error @@ -773,7 +768,7 @@ def __init__( assert kv_compression_sharing in [None, "headwise", "key-value", "layerwise"] def make_kv_compression() -> nn.Module: - assert ( + assert ( # noqa: PT018 n_tokens and kv_compression_ratio ), _INTERNAL_ERROR_MESSAGE # for mypy # https://bit.ly/3h8RdO5 @@ -938,6 +933,7 @@ def __init__( Args: feature_tokenizer (FeatureTokenizer): feature tokenizer. transformer (Transformer): transformer. + **kwargs: keyword arguments """ super().__init__() self.feature_tokenizer = feature_tokenizer diff --git a/src/otc/models/objective.py b/src/otc/models/objective.py index 974a0e43..fbe40dd8 100644 --- a/src/otc/models/objective.py +++ b/src/otc/models/objective.py @@ -86,7 +86,12 @@ def __init__( pretrain (bool, optional): Whether to pretrain. Defaults to False. **kwargs: arguments """ - self.x_train, self.y_train, self.x_val, self.y_val, = ( + ( + self.x_train, + self.y_train, + self.x_val, + self.y_val, + ) = ( x_train, y_train, x_val, diff --git a/src/otc/models/selftraining.py b/src/otc/models/selftraining.py index 83c04c90..d50e5fd5 100644 --- a/src/otc/models/selftraining.py +++ b/src/otc/models/selftraining.py @@ -91,8 +91,8 @@ def fit( """Fit self-training classifier using `X`, `y` as training data. Args: - train_set (dict) dict with training data - eval_set (Pool): pool of validation data + train_set (dict): training set + eval_set (Pool): validation set **kwargs: keyword arguments Raises: diff --git a/src/otc/models/train_model.py b/src/otc/models/train_model.py index 2b9e6d90..7c59b9fb 100644 --- a/src/otc/models/train_model.py +++ b/src/otc/models/train_model.py @@ -252,7 +252,6 @@ def main( if __name__ == "__main__": - with Path.open("logging.yaml") as file: loaded_config = yaml.safe_load(file) logging.config.dictConfig(loaded_config) diff --git a/src/otc/models/transformer_classifier.py b/src/otc/models/transformer_classifier.py index 1136a2fd..2b6caa29 100644 --- a/src/otc/models/transformer_classifier.py +++ b/src/otc/models/transformer_classifier.py @@ -207,8 +207,7 @@ def fit( Args: X (npt.NDArray | pd.DataFrame): feature matrix y (npt.NDArray | pd.Series): target - eval_set (tuple[npt.NDArray, npt.NDArray] | - tuple[pd.DataFrame, pd.Series] | None): eval set. Defaults to None. + eval_set (tuple[npt.NDArray, npt.NDArray] | tuple[pd.DataFrame, pd.Series] | None): eval set. Defaults to None. If no eval set is passed, the training set is used. Returns: @@ -229,7 +228,6 @@ def fit( self._stats_pretrain_epoch = [] if self.pretrain: - print("start pre-training...") mask = y == 0 @@ -313,14 +311,12 @@ def fit( best_accuracy = -1.0 for epoch in range(self.epochs_pretrain): - # perform training loss_in_epoch_train = 0 batch = 0 for x_cat, x_cont, mask in train_loader_pretrain: - self.clf.train() optimizer.zero_grad() @@ -349,7 +345,6 @@ def fit( with torch.no_grad(): for x_cat, x_cont, mask in val_loader_pretrain: - # for my implementation logits = self.clf(x_cat, x_cont) val_loss = criterion(logits, mask.float()) @@ -470,7 +465,6 @@ def fit( self._stats_epoch = [] for epoch in range(self.epochs_finetune): - # perform training loss_in_epoch_train = 0 train_batch = 0 @@ -478,7 +472,6 @@ def fit( self.clf.train() for x_cat, x_cont, weights, targets in train_loader_finetune: - # reset the gradients back to zero self.clf.train() optimizer.zero_grad() diff --git a/src/otc/utils/check_formalia.py b/src/otc/utils/check_formalia.py index 1dafe10f..b9ab3c3a 100644 --- a/src/otc/utils/check_formalia.py +++ b/src/otc/utils/check_formalia.py @@ -187,7 +187,6 @@ def check_formalia(files: dict, vocabulary: list, acronyms: list) -> None: acronyms (list): list of acronyms """ for file_name, file_contents in files.items(): - if file_name not in [ ".\\expose.tex", ".\\presentation.tex", diff --git a/tests/templates.py b/tests/templates.py index a8877f45..e4935479 100644 --- a/tests/templates.py +++ b/tests/templates.py @@ -63,7 +63,6 @@ def test_convergence(self) -> None: # perform training for _ in range(512): - outputs = self.get_outputs() optimizer.zero_grad() diff --git a/tests/test_classical_classifier.py b/tests/test_classical_classifier.py index d8c21536..05a957a9 100644 --- a/tests/test_classical_classifier.py +++ b/tests/test_classical_classifier.py @@ -116,7 +116,7 @@ def test_invalid_col_length(self) -> None: classifier = ClassicalClassifier( layers=[("tick", "all")], random_state=42, features=["one"] ) - with pytest.raises(ValueError, math=r"Expected"): + with pytest.raises(ValueError, match=r"Expected"): classifier.fit(self.x_train.values, self.y_train.values) def test_override(self) -> None: diff --git a/tox.ini b/tox.ini index 2837cde2..946b2edf 100644 --- a/tox.ini +++ b/tox.ini @@ -38,4 +38,4 @@ commands = [testenv:test] commands = - poetry run pytest -m "not slow" \ No newline at end of file + poetry run pytest -m "not slow"