{
  "cells": [
    {
      "cell_type": "markdown",
      "id": "d7143989",
      "metadata": {},
      "source": [
        "# Model Onboarding\n",
        "\n",
        "Use this notebook for the exposure initial upload and risk dataset creation of a set of factor exposures using daily CSV files.\n",
        "\n",
        "The notebook contains a section that obtains coverage statistics of the created risk dataset against the uploaded exposures."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "8c171e70",
      "metadata": {},
      "outputs": [],
      "source": [
        "import datetime as dt\n",
        "import itertools as it\n",
        "import shutil\n",
        "import tempfile\n",
        "\n",
        "from pathlib import Path\n",
        "\n",
        "import polars as pl\n",
        "from tqdm import tqdm\n",
        "\n",
        "from bayesline.apiclient import BayeslineApiClient\n",
        "from bayesline.api.equity import (\n",
        "    ContinuousExposureGroupSettings,\n",
        "    ExposureSettings, \n",
        "    RiskDatasetSettings,\n",
        "    RiskDatasetReferencedExposureSettings,\n",
        "    RiskDatasetUploadedExposureSettings,\n",
        "    UniverseSettings,\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "id": "f9df046c",
      "metadata": {
        "tags": [
          "skip-execution"
        ]
      },
      "outputs": [],
      "source": [
        "bln = BayeslineApiClient.new_client(\n",
        "    endpoint=\"https://[ENDPOINT]\",\n",
        "    api_key=\"[API-KEY]\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "a10c5e5b",
      "metadata": {},
      "source": [
        "## Exposure Upload"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "ff3976a2",
      "metadata": {
        "tags": [
          "skip-execution"
        ]
      },
      "outputs": [
        {
          "ename": "AssertionError",
          "evalue": "",
          "output_type": "error",
          "traceback": [
            "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
            "\u001b[31mAssertionError\u001b[39m                            Traceback (most recent call last)",
            "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 2\u001b[39m\n\u001b[32m      1\u001b[39m exposure_dir = Path(\u001b[33m\"\u001b[39m\u001b[33m/PATH/TO/EXPOSURES\u001b[39m\u001b[33m\"\u001b[39m)\n\u001b[32m----> \u001b[39m\u001b[32m2\u001b[39m \u001b[38;5;28;01massert\u001b[39;00m exposure_dir.exists()\n",
            "\u001b[31mAssertionError\u001b[39m: "
          ]
        }
      ],
      "source": [
        "exposure_dir = Path(\"/PATH/TO/EXPOSURES\")\n",
        "assert exposure_dir.exists()\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "id": "bd81cd30",
      "metadata": {},
      "outputs": [],
      "source": [
        "exposure_dataset_name = \"My-Exposures\""
      ]
    },
    {
      "cell_type": "markdown",
      "id": "3a9b7f55",
      "metadata": {},
      "source": [
        "Below creates a new exposure uploader for the chosen dataset name `My-Exposures`. See the [Uploaders Tutorial](https://docs.bayesline.com/0.9.2/notebooks/tutorial_uploaders.html) for a deep dive into the `Uploaders API`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "cdbba084",
      "metadata": {},
      "outputs": [],
      "source": [
        "exposure_uploader = bln.equity.uploaders.get_data_type(\"exposures\")\n",
        "uploader = exposure_uploader.get_or_create_dataset(exposure_dataset_name)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "19f12a05",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Found 31 files.\n",
            "Years: 2025\n"
          ]
        }
      ],
      "source": [
        "# list all csv files and group them by year\n",
        "# expects file pattern \"*_YYYY-MM-DD.csv\"\n",
        "\n",
        "all_files = sorted(exposure_dir.glob(\"*.csv\"))\n",
        "existing_files = uploader.get_staging_results().keys()\n",
        "\n",
        "files_by_year = {\n",
        "    k: list(v) \n",
        "    for k, v in \n",
        "    it.groupby(all_files, lambda x: int(x.name.split(\"_\")[1].split(\".\")[0].split(\"-\")[0]))\n",
        "}\n",
        "files_by_year.keys()\n",
        "\n",
        "print(f\"Found {len(all_files)} files.\")\n",
        "print(\"Years:\", \", \".join(map(str, files_by_year)))"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "8dec97fe",
      "metadata": {},
      "source": [
        "Below we batch the daily CSV files into annual Parquet files. Creating batched Parquet files is recommended as it will be much faster to upload and process compared to individually uploading daily files."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "id": "00fdb93b",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Created temp directory: /tmp/tmp_62br1z2\n"
          ]
        }
      ],
      "source": [
        "temp_dir = Path(tempfile.mkdtemp())\n",
        "print(f\"Created temp directory: {temp_dir}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "id": "712bc6ae",
      "metadata": {
        "tags": [
          "remove-output"
        ]
      },
      "outputs": [
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\r",
            "  0%|          | 0/1 [00:00<?, ?it/s]"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\r",
            "100%|██████████| 1/1 [00:02<00:00,  2.97s/it]"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\r",
            "100%|██████████| 1/1 [00:02<00:00,  2.97s/it]"
          ]
        },
        {
          "name": "stderr",
          "output_type": "stream",
          "text": [
            "\n"
          ]
        }
      ],
      "source": [
        "for year, files in tqdm(files_by_year.items()):\n",
        "    parquet_path = temp_dir / f\"exposures_{year}.parquet\"\n",
        "    df = pl.scan_csv(files, try_parse_dates=True)\n",
        "    df.sink_parquet(parquet_path)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "fce0eb74",
      "metadata": {},
      "source": [
        "As a next step we iterate over the annual Parquet files and stage them in the uploader. See the [Uploaders Tutorial](https://docs.bayesline.com/0.9.2/notebooks/tutorial_uploaders.html#staging-data) for more details on the *staging* and *commit* concepts."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "id": "4451beea",
      "metadata": {},
      "outputs": [],
      "source": [
        "for year in files_by_year.keys():\n",
        "    parquet = temp_dir / f\"exposures_{year}.parquet\"\n",
        "    result = uploader.stage_file(parquet)\n",
        "    assert result.success"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "id": "af0518bf",
      "metadata": {},
      "outputs": [],
      "source": [
        "shutil.rmtree(temp_dir)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "698baf54",
      "metadata": {},
      "source": [
        "### Data Commit\n",
        "\n",
        "Next up we commit the data into versioned storage."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "id": "452cfd2f",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "UploadCommitResult(version=1, committed_names=['exposures_2025'])"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "uploader.commit(mode=\"append\")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "609b4a90",
      "metadata": {},
      "source": [
        "## Risk Dataset Creation\n",
        "\n",
        "Below creates a new *Risk Dataset* using above uploaded exposures. See the [Risk Datasets Tutorial](https://docs.bayesline.com/0.9.2/notebooks/tutorial_datasets.html) for a deep dive into the `Risk Datasets API`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "id": "087f2205",
      "metadata": {},
      "outputs": [],
      "source": [
        "risk_datasets = bln.equity.riskdatasets"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "66e8be64",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['Bayesline-US-500-1y', 'Bayesline-US-All-1y']"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# exisint datasets which can be used as reference datasets\n",
        "risk_datasets.get_dataset_names()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "id": "137d023d",
      "metadata": {},
      "outputs": [],
      "source": [
        "risk_dataset_name = \"My-Risk-Dataset\""
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "id": "6b766822",
      "metadata": {},
      "outputs": [],
      "source": [
        "risk_datasets.delete_dataset_if_exists(risk_dataset_name)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "b5f8400f",
      "metadata": {},
      "source": [
        "We need to specify an assignment of which exposures are *style*, *region*, etc. Below lists those *factor groups* as they were extracted from the uploaded exposures."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "id": "d73f4b80",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><style>\n",
              ".dataframe > thead > tr,\n",
              ".dataframe > tbody > tr {\n",
              "  text-align: right;\n",
              "  white-space: pre-wrap;\n",
              "}\n",
              "</style>\n",
              "<small>shape: (4, 1)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>factor_group</th></tr><tr><td>str</td></tr></thead><tbody><tr><td>&quot;market&quot;</td></tr><tr><td>&quot;industry&quot;</td></tr><tr><td>&quot;style&quot;</td></tr><tr><td>&quot;region&quot;</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (4, 1)\n",
              "┌──────────────┐\n",
              "│ factor_group │\n",
              "│ ---          │\n",
              "│ str          │\n",
              "╞══════════════╡\n",
              "│ market       │\n",
              "│ industry     │\n",
              "│ style        │\n",
              "│ region       │\n",
              "└──────────────┘"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "uploader.get_data(columns=[\"factor_group\"], unique=True).collect()"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9742bf9c",
      "metadata": {},
      "source": [
        "See API docs for [`RiskDatasetSettings`](https://docs.bayesline.com/0.9.2/_autosummary/bayesline.api.equity.RiskDatasetSettings.html) and [`RiskDatasetUploadedExposureSettings`](https://docs.bayesline.com/0.9.2/_autosummary/bayesline.api.equity.RiskDatasetUploadedExposureSettings.html) for other potential settings.\n",
        "\n",
        "In this recipe we pass through the industry hierarchy from the reference risk dataset, choose that our uploaded exposures make up the estimation universe and that we take the union of all assets across all of our exposures as the overall asset filter."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "id": "69808839",
      "metadata": {},
      "outputs": [],
      "source": [
        "settings = RiskDatasetSettings(\n",
        "    reference_dataset=\"Bayesline-US-All-1y\",\n",
        "    exposures=[\n",
        "        RiskDatasetReferencedExposureSettings(\n",
        "            categorical_factor_groups=[\"trbc\"],\n",
        "            continuous_factor_groups=[],\n",
        "        ),\n",
        "        RiskDatasetUploadedExposureSettings(\n",
        "            exposure_source=exposure_dataset_name,\n",
        "            continuous_factor_groups=[\"market\", \"style\"],\n",
        "            categorical_factor_groups=[\"industry\", \"region\"],\n",
        "        ),\n",
        "    ],\n",
        "    trim_start_date=dt.date(2025, 5, 1),\n",
        "    trim_assets=\"asset_union\",\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "id": "f13db242",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><style>\n",
              ".dataframe > thead > tr,\n",
              ".dataframe > tbody > tr {\n",
              "  text-align: right;\n",
              "  white-space: pre-wrap;\n",
              "}\n",
              "</style>\n",
              "<small>shape: (3_358_577, 10)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>bayesid</th><th>market.Market</th><th>style.Size</th><th>style.Value</th><th>style.Growth</th><th>style.Volatility</th><th>style.Momentum</th><th>style.Dividend</th><th>style.Leverage</th></tr><tr><td>date</td><td>str</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2024-08-25</td><td>&quot;IC0007D96F&quot;</td><td>1.0</td><td>-0.24231</td><td>0.247192</td><td>0.119263</td><td>-2.34375</td><td>0.630859</td><td>-0.007622</td><td>-0.070557</td></tr><tr><td>2024-08-25</td><td>&quot;IC000B1557&quot;</td><td>1.0</td><td>0.413818</td><td>2.455078</td><td>0.048309</td><td>-0.230103</td><td>1.365234</td><td>-0.832031</td><td>1.030273</td></tr><tr><td>2024-08-25</td><td>&quot;IC0010CEFE&quot;</td><td>1.0</td><td>-1.341797</td><td>-1.788086</td><td>-0.33667</td><td>1.767578</td><td>-0.585938</td><td>-0.832031</td><td>0.18457</td></tr><tr><td>2024-08-25</td><td>&quot;IC0021AFB7&quot;</td><td>1.0</td><td>-0.200439</td><td>0.250488</td><td>0.146606</td><td>-1.527344</td><td>1.001953</td><td>0.011353</td><td>-0.053986</td></tr><tr><td>2024-08-25</td><td>&quot;IC002CE8B9&quot;</td><td>1.0</td><td>0.111633</td><td>2.488281</td><td>-0.178955</td><td>0.304443</td><td>0.221313</td><td>-0.037445</td><td>0.034546</td></tr><tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr><tr><td>2025-08-25</td><td>&quot;ICFFE54368&quot;</td><td>1.0</td><td>0.969238</td><td>-2.460938</td><td>-0.713379</td><td>0.515625</td><td>-1.004883</td><td>-0.861328</td><td>0.088562</td></tr><tr><td>2025-08-25</td><td>&quot;ICFFE60191&quot;</td><td>1.0</td><td>-0.777832</td><td>-1.983398</td><td>-0.250244</td><td>0.325439</td><td>2.4765625</td><td>-0.052338</td><td>0.229004</td></tr><tr><td>2025-08-25</td><td>&quot;ICFFE94AED&quot;</td><td>1.0</td><td>0.172974</td><td>1.003906</td><td>0.37915</td><td>-1.589844</td><td>0.252197</td><td>1.206055</td><td>1.147461</td></tr><tr><td>2025-08-25</td><td>&quot;ICFFEBBB38&quot;</td><td>1.0</td><td>0.642578</td><td>0.35791</td><td>0.681152</td><td>-1.454102</td><td>1.233398</td><td>0.367432</td><td>0.286621</td></tr><tr><td>2025-08-25</td><td>&quot;ICFFF2F5AD&quot;</td><td>1.0</td><td>-0.353027</td><td>0.259521</td><td>0.036865</td><td>0.395508</td><td>0.572754</td><td>-0.043518</td><td>-0.100891</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (3_358_577, 10)\n",
              "┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐\n",
              "│ date      ┆ bayesid   ┆ market.Ma ┆ style.Siz ┆ … ┆ style.Vol ┆ style.Mom ┆ style.Div ┆ style.Le │\n",
              "│ ---       ┆ ---       ┆ rket      ┆ e         ┆   ┆ atility   ┆ entum     ┆ idend     ┆ verage   │\n",
              "│ date      ┆ str       ┆ ---       ┆ ---       ┆   ┆ ---       ┆ ---       ┆ ---       ┆ ---      │\n",
              "│           ┆           ┆ f32       ┆ f32       ┆   ┆ f32       ┆ f32       ┆ f32       ┆ f32      │\n",
              "╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡\n",
              "│ 2024-08-2 ┆ IC0007D96 ┆ 1.0       ┆ -0.24231  ┆ … ┆ -2.34375  ┆ 0.630859  ┆ -0.007622 ┆ -0.07055 │\n",
              "│ 5         ┆ F         ┆           ┆           ┆   ┆           ┆           ┆           ┆ 7        │\n",
              "│ 2024-08-2 ┆ IC000B155 ┆ 1.0       ┆ 0.413818  ┆ … ┆ -0.230103 ┆ 1.365234  ┆ -0.832031 ┆ 1.030273 │\n",
              "│ 5         ┆ 7         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2024-08-2 ┆ IC0010CEF ┆ 1.0       ┆ -1.341797 ┆ … ┆ 1.767578  ┆ -0.585938 ┆ -0.832031 ┆ 0.18457  │\n",
              "│ 5         ┆ E         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2024-08-2 ┆ IC0021AFB ┆ 1.0       ┆ -0.200439 ┆ … ┆ -1.527344 ┆ 1.001953  ┆ 0.011353  ┆ -0.05398 │\n",
              "│ 5         ┆ 7         ┆           ┆           ┆   ┆           ┆           ┆           ┆ 6        │\n",
              "│ 2024-08-2 ┆ IC002CE8B ┆ 1.0       ┆ 0.111633  ┆ … ┆ 0.304443  ┆ 0.221313  ┆ -0.037445 ┆ 0.034546 │\n",
              "│ 5         ┆ 9         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ …         ┆ …         ┆ …         ┆ …         ┆ … ┆ …         ┆ …         ┆ …         ┆ …        │\n",
              "│ 2025-08-2 ┆ ICFFE5436 ┆ 1.0       ┆ 0.969238  ┆ … ┆ 0.515625  ┆ -1.004883 ┆ -0.861328 ┆ 0.088562 │\n",
              "│ 5         ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-08-2 ┆ ICFFE6019 ┆ 1.0       ┆ -0.777832 ┆ … ┆ 0.325439  ┆ 2.4765625 ┆ -0.052338 ┆ 0.229004 │\n",
              "│ 5         ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-08-2 ┆ ICFFE94AE ┆ 1.0       ┆ 0.172974  ┆ … ┆ -1.589844 ┆ 0.252197  ┆ 1.206055  ┆ 1.147461 │\n",
              "│ 5         ┆ D         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-08-2 ┆ ICFFEBBB3 ┆ 1.0       ┆ 0.642578  ┆ … ┆ -1.454102 ┆ 1.233398  ┆ 0.367432  ┆ 0.286621 │\n",
              "│ 5         ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-08-2 ┆ ICFFF2F5A ┆ 1.0       ┆ -0.353027 ┆ … ┆ 0.395508  ┆ 0.572754  ┆ -0.043518 ┆ -0.10089 │\n",
              "│ 5         ┆ D         ┆           ┆           ┆   ┆           ┆           ┆           ┆ 1        │\n",
              "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "exposures_api = bln.equity.exposures.load(\n",
        "    ExposureSettings(\n",
        "        exposures=[\n",
        "            ContinuousExposureGroupSettings(hierarchy=\"market\"),\n",
        "            ContinuousExposureGroupSettings(hierarchy=\"style\", standardize_method=\"equal_weighted\"),\n",
        "        ],\n",
        "    )\n",
        ")\n",
        "exposures_api.get(UniverseSettings(dataset=\"Bayesline-US-All-1y\"), standardize_universe=None)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "e24b59f1",
      "metadata": {},
      "source": [
        "Lastly we create the new dataset followed by describing its properties after creation."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "id": "77962366",
      "metadata": {},
      "outputs": [],
      "source": [
        "my_risk_dataset = risk_datasets.create_dataset(risk_dataset_name, settings)"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "c23d53a1",
      "metadata": {},
      "source": [
        "### Data Coverage\n",
        "\n",
        "As a first step after the risk dataset creation we cross check the asset coverage compared to our raw exposure upload."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "id": "0564a0a0",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><style>\n",
              ".dataframe > thead > tr,\n",
              ".dataframe > tbody > tr {\n",
              "  text-align: right;\n",
              "  white-space: pre-wrap;\n",
              "}\n",
              "</style>\n",
              "<small>shape: (5, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>n_assets</th><th>min_exposure</th><th>max_exposure</th><th>mean_exposure</th><th>std_exposure</th></tr><tr><td>date</td><td>i64</td><td>f32</td><td>f32</td><td>f64</td><td>f64</td></tr></thead><tbody><tr><td>2025-05-01</td><td>46773</td><td>-4.171875</td><td>4.28125</td><td>0.23534</td><td>1.023091</td></tr><tr><td>2025-05-02</td><td>46766</td><td>-4.171875</td><td>4.277344</td><td>0.235877</td><td>1.022765</td></tr><tr><td>2025-05-03</td><td>46763</td><td>-4.171875</td><td>4.277344</td><td>0.235797</td><td>1.022699</td></tr><tr><td>2025-05-04</td><td>46763</td><td>-4.171875</td><td>4.277344</td><td>0.235795</td><td>1.022698</td></tr><tr><td>2025-05-05</td><td>46766</td><td>-4.171875</td><td>4.277344</td><td>0.236549</td><td>1.022354</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (5, 6)\n",
              "┌────────────┬──────────┬──────────────┬──────────────┬───────────────┬──────────────┐\n",
              "│ date       ┆ n_assets ┆ min_exposure ┆ max_exposure ┆ mean_exposure ┆ std_exposure │\n",
              "│ ---        ┆ ---      ┆ ---          ┆ ---          ┆ ---           ┆ ---          │\n",
              "│ date       ┆ i64      ┆ f32          ┆ f32          ┆ f64           ┆ f64          │\n",
              "╞════════════╪══════════╪══════════════╪══════════════╪═══════════════╪══════════════╡\n",
              "│ 2025-05-01 ┆ 46773    ┆ -4.171875    ┆ 4.28125      ┆ 0.23534       ┆ 1.023091     │\n",
              "│ 2025-05-02 ┆ 46766    ┆ -4.171875    ┆ 4.277344     ┆ 0.235877      ┆ 1.022765     │\n",
              "│ 2025-05-03 ┆ 46763    ┆ -4.171875    ┆ 4.277344     ┆ 0.235797      ┆ 1.022699     │\n",
              "│ 2025-05-04 ┆ 46763    ┆ -4.171875    ┆ 4.277344     ┆ 0.235795      ┆ 1.022698     │\n",
              "│ 2025-05-05 ┆ 46766    ┆ -4.171875    ┆ 4.277344     ┆ 0.236549      ┆ 1.022354     │\n",
              "└────────────┴──────────┴──────────────┴──────────────┴───────────────┴──────────────┘"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "upload_stats_df = uploader.get_data_detail_summary()\n",
        "upload_stats_df.head()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "350c984e",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><style>\n",
              ".dataframe > thead > tr,\n",
              ".dataframe > tbody > tr {\n",
              "  text-align: right;\n",
              "  white-space: pre-wrap;\n",
              "}\n",
              "</style>\n",
              "<small>shape: (14_485_600, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>asset_id</th><th>asset_id_type</th><th>factor_group</th><th>factor</th><th>exposure</th></tr><tr><td>date</td><td>str</td><td>str</td><td>str</td><td>str</td><td>f32</td></tr></thead><tbody><tr><td>2025-05-01</td><td>&quot;IC00009602&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;market&quot;</td><td>&quot;Market&quot;</td><td>1.0</td></tr><tr><td>2025-05-01</td><td>&quot;IC00056DA0&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;market&quot;</td><td>&quot;Market&quot;</td><td>1.0</td></tr><tr><td>2025-05-01</td><td>&quot;IC0007243E&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;market&quot;</td><td>&quot;Market&quot;</td><td>1.0</td></tr><tr><td>2025-05-01</td><td>&quot;IC0007E6E3&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;market&quot;</td><td>&quot;Market&quot;</td><td>1.0</td></tr><tr><td>2025-05-01</td><td>&quot;IC00098715&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;market&quot;</td><td>&quot;Market&quot;</td><td>1.0</td></tr><tr><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td><td>&hellip;</td></tr><tr><td>2025-05-31</td><td>&quot;IC8C349DE9&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;style&quot;</td><td>&quot;Dividend&quot;</td><td>-0.997559</td></tr><tr><td>2025-05-31</td><td>&quot;IC8C356E02&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;style&quot;</td><td>&quot;Dividend&quot;</td><td>1.438477</td></tr><tr><td>2025-05-31</td><td>&quot;IC8C36399F&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;style&quot;</td><td>&quot;Dividend&quot;</td><td>0.129395</td></tr><tr><td>2025-05-31</td><td>&quot;IC8C38B75E&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;style&quot;</td><td>&quot;Dividend&quot;</td><td>-0.997559</td></tr><tr><td>2025-05-31</td><td>&quot;IC8C3BF346&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;style&quot;</td><td>&quot;Dividend&quot;</td><td>-0.997559</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (14_485_600, 6)\n",
              "┌────────────┬────────────┬───────────────┬──────────────┬──────────┬───────────┐\n",
              "│ date       ┆ asset_id   ┆ asset_id_type ┆ factor_group ┆ factor   ┆ exposure  │\n",
              "│ ---        ┆ ---        ┆ ---           ┆ ---          ┆ ---      ┆ ---       │\n",
              "│ date       ┆ str        ┆ str           ┆ str          ┆ str      ┆ f32       │\n",
              "╞════════════╪════════════╪═══════════════╪══════════════╪══════════╪═══════════╡\n",
              "│ 2025-05-01 ┆ IC00009602 ┆ bayesid       ┆ market       ┆ Market   ┆ 1.0       │\n",
              "│ 2025-05-01 ┆ IC00056DA0 ┆ bayesid       ┆ market       ┆ Market   ┆ 1.0       │\n",
              "│ 2025-05-01 ┆ IC0007243E ┆ bayesid       ┆ market       ┆ Market   ┆ 1.0       │\n",
              "│ 2025-05-01 ┆ IC0007E6E3 ┆ bayesid       ┆ market       ┆ Market   ┆ 1.0       │\n",
              "│ 2025-05-01 ┆ IC00098715 ┆ bayesid       ┆ market       ┆ Market   ┆ 1.0       │\n",
              "│ …          ┆ …          ┆ …             ┆ …            ┆ …        ┆ …         │\n",
              "│ 2025-05-31 ┆ IC8C349DE9 ┆ bayesid       ┆ style        ┆ Dividend ┆ -0.997559 │\n",
              "│ 2025-05-31 ┆ IC8C356E02 ┆ bayesid       ┆ style        ┆ Dividend ┆ 1.438477  │\n",
              "│ 2025-05-31 ┆ IC8C36399F ┆ bayesid       ┆ style        ┆ Dividend ┆ 0.129395  │\n",
              "│ 2025-05-31 ┆ IC8C38B75E ┆ bayesid       ┆ style        ┆ Dividend ┆ -0.997559 │\n",
              "│ 2025-05-31 ┆ IC8C3BF346 ┆ bayesid       ┆ style        ┆ Dividend ┆ -0.997559 │\n",
              "└────────────┴────────────┴───────────────┴──────────────┴──────────┴───────────┘"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "uploader.get_data().collect()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "id": "7e996f64",
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Categorical Hierarchies ['trbc', 'industry', 'region']\n"
          ]
        }
      ],
      "source": [
        "# note that the industry and region hierarchy names tie out with the factor groups we specified above\n",
        "print(f\"Categorical Hierarchies {list(my_risk_dataset.describe().universe_settings_menu.categorical_hierarchies.keys())}\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "id": "9854d32d",
      "metadata": {},
      "outputs": [],
      "source": [
        "universe_settings = UniverseSettings(dataset=risk_dataset_name)\n",
        "\n",
        "universe_api = bln.equity.universes.load(universe_settings)\n",
        "universe_counts = universe_api.counts()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "id": "0e88cd72",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "<Axes: xlabel='date'>"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "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8UZ17dpVklRYWCi3262WLVv61MbGxqqwsNCpOTngVI9Xj52upqSkRMeOHdO///1vVVZW1lpTPUdtMjIyFBER4VwSEhIavuEAAOCicNYhJy0tTVu2bNGCBQuasp9zatq0afJ6vc5l7969/m4JAACcI83O5kbp6elavHixPvvsM7Vt29ZZHhcXp/LychUXF/vszSkqKlJcXJxTc+pZUNVnX51cc+oZWUVFRfJ4PAoNDVVgYKACAwNrrameozbBwcEKDg5u+AYDAICLToP25BhjlJ6ervfee0/Lly9Xhw4dfMZ79eqloKAgZWVlOcvy8/NVUFCgpKQkSVJSUpI2b97scxbUsmXL5PF41KVLF6fm5Dmqa6rncLvd6tWrl09NVVWVsrKynBoAAHCJa8jRzA8++KCJiIgwK1euNPv373cuR48edWomTJhgEhMTzfLly82GDRtMUlKSSUpKcsZPnDhhunbtagYPHmzy8vLM0qVLTXR0tJk2bZpT849//MOEhYWZKVOmmO3bt5u5c+eawMBAs3TpUqdmwYIFJjg42GRmZppt27aZ8ePHm5YtW/qctXUmnF0FAMDFp77v3w0KOZJqvcybN8+pOXbsmHnooYdMq1atTFhYmLnjjjvM/v37febZs2ePufXWW01oaKi57LLLzKOPPmoqKip8alasWGF69Ohh3G63ufzyy33WUe3FF180iYmJxu12mz59+pg1a9Y0ZHMIOQAAXITq+/7tMsYYf+1F8reSkhJFRETI6/XK4/H4ux0AAFAP9X3/5rOrAACAlQg5AADASoQcAABgJUIOAACwEiEHAABYiZADAACsRMgBAABWIuQAAAArEXIAAICVCDkAAMBKhBwAAGAlQg4AALASIQcAAFiJkAMAAKxEyAEAAFYi5AAAACsRcgAAgJUIOQAAwEqEHAAAYCVCDgAAsBIhBwAAWImQAwAArETIAQAAViLkAAAAKxFyAACAlQg5AADASoQcAABgJUIOAACwEiEHAABYiZADAACsRMgBAABWIuQAAAArEXIAAICVCDkAAMBKhBwAAGAlQg4AALASIQcAAFiJkAMAAKxEyAEAAFYi5AAAACsRcgAAgJUIOQAAwEqEHAAAYCVCDgAAsBIhBwAAWImQAwAArETIAQAAViLkAAAAKxFyAACAlQg5AADASoQcAABgJUIOAACwEiEHAABYiZADAACsRMgBAABWIuQAAAArEXIAAICVCDkAAMBKhBwAAGAlQg4AALASIQcAAFiJkAMAAKxEyAEAAFYi5AAAACsRcgAAgJUIOQAAwEqEHAAAYCVCDgAAsBIhBwAAWImQAwAArNTgkPPZZ5/p9ttvV3x8vFwul95//32fcWOMZsyYodatWys0NFTJycnauXOnT80333yje+65Rx6PRy1bttTYsWN15MgRn5ovvvhCN998s0JCQpSQkKBZs2bV6GXhwoW6+uqrFRISom7duumjjz5q6OYAAABLNTjklJaWqnv37po7d26t47NmzdJvf/tbvfzyy1q7dq2aN2+ulJQUHT9+3Km55557tHXrVi1btkyLFy/WZ599pvHjxzvjJSUlGjx4sNq1a6fc3Fw999xzevLJJ/XKK684NatXr9aIESM0duxY/e1vf9OwYcM0bNgwbdmypaGbBAAAbGQaQZJ57733nOtVVVUmLi7OPPfcc86y4uJiExwcbN5++21jjDHbtm0zksz69eudmr/+9a/G5XKZf/3rX8YYY373u9+ZVq1ambKyMqfm8ccfN506dXKu//CHPzSpqak+/fTt29f8+Mc/rnf/Xq/XSDJer7fetwEAAP5V3/fvJj0mZ/fu3SosLFRycrKzLCIiQn379lVOTo4kKScnRy1btlTv3r2dmuTkZAUEBGjt2rVOzS233CK32+3UpKSkKD8/X4cOHXJqTl5PdU31empTVlamkpISnwsAALBTk4acwsJCSVJsbKzP8tjYWGessLBQMTExPuPNmjVTZGSkT01tc5y8jrpqqsdrk5GRoYiICOeSkJDQ0E0EAAAXiUvq7Kpp06bJ6/U6l7179/q7JQAAcI40aciJi4uTJBUVFfksLyoqcsbi4uJ04MABn/ETJ07om2++8ampbY6T11FXTfV4bYKDg+XxeHwuAADATk0acjp06KC4uDhlZWU5y0pKSrR27VolJSVJkpKSklRcXKzc3FynZvny5aqqqlLfvn2dms8++0wVFRVOzbJly9SpUye1atXKqTl5PdU11esBAACXtgaHnCNHjigvL095eXmSvj3YOC8vTwUFBXK5XJo4caJ+8Ytf6C9/+Ys2b96skSNHKj4+XsOGDZMkde7cWUOGDNEDDzygdevWadWqVUpPT9f//M//KD4+XpL0ox/9SG63W2PHjtXWrVv1zjvvaPbs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e/bUoEGDOM7qHLikP7sKvsaPH+98361bN7Vu3VqDBg3Srl27dMUVV/ixM5ytiooK/fCHP5QxRi+99JK/28FZCAoK0qJFizR27FhFRkYqMDBQycnJuvXWW2X4N2cXtLS0NG3ZssVnL01VVZUk6cc//rHuv/9+SdJ1112nrKwsvf7668rIyPBLr7ZiT84l4rLLLlNgYKCKiop8lhcVFSkuLq7W2/Tt21eS9Pe///2c94emVx1wvvrqKy1btoy9OBexXr16KS8vT8XFxdq/f7+WLl2qgwcP6vLLL/d3a6hDenq6Fi9erBUrVqht27bO8tatW0uSunTp4lPfuXNnFRQUnNceLwWEnEuE2+1Wr169lJWV5SyrqqpSVlaWkpKSar1NXl6epP++KHHxqA44O3fu1KeffqqoqCh/t4QmEBERoejoaO3cuVMbNmzQ0KFD/d0STmGMUXp6ut577z0tX75cHTp08Blv37694uPja5xW/uWXX6pdu3bns9VLAn+uuoRMnjxZo0aNUu/evdWnTx+98MILKi0t1f33369du3Zp/vz5uu222xQVFaUvvvhCkyZN0i233KJrr73W363jFEeOHPHZw7Z7927l5eUpMjJSrVu31t13362NGzdq8eLFqqysdI67ioyMlNvt9lfbqMPpHs/ExEQtXLhQ0dHRSkxM1ObNm/XII49o2LBhGjx4sB+7Rm3S0tI0f/58ffDBB2rRooXz2ouIiFBoaKhcLpemTJmimTNnqnv37urRo4feeOMN7dixQ3/+85/93L2F/Hx2F86zF1980SQmJhq322369Olj1qxZY4wxpqCgwNxyyy0mMjLSBAcHm44dO5opU6YYr9fr545RmxUrVhhJNS6jRo0yu3fvrnVMklmxYoW/W0ctTvd4GmPM7NmzTdu2bU1QUJBJTEw006dPN2VlZf5tGrWq67U3b948n7qMjAzTtm1bExYWZpKSksz/+3//zz8NW44P6AQAAFbimBwAAGAlQg4AALASIQcAAFiJkAMAAKxEyAEAAFYi5AAAACsRcgAAgJUIOQAAwEqEHAAAYCVCDgAAsBIhBwAAWImQAwAArETIAQAAViLkAAAAKxFyAACAlQg5AADASoQcAABgJUIOAACwEiEHAABYiZADAACsRMgBAABWIuQAAAArEXIAAICVCDkAAMBKVoWc0aNHy+VyacKECTXG0tLS5HK5NHr06PPfGAAAOO+sCjmSlJCQoAULFujYsWPOsuPHj2v+/PlKTEz0Y2cAAOB8si7k9OzZUwkJCVq0aJGzbNGiRUpMTNR1113nLFu6dKluuukmtWzZUlFRUfre976nXbt2OeMDBw5Uenq6z9xff/213G63srKyzv2GAACARrEu5EjSmDFjNG/ePOf666+/rvvvv9+nprS0VJMnT9aGDRuUlZWlgIAA3XHHHaqqqpIkjRs3TvPnz1dZWZlzmzfffFNt2rTRwIEDz8+GAACAs2ZlyLn33nv1+eef66uvvtJXX32lVatW6d577/Wpueuuu3TnnXeqY8eO6tGjh15//XVt3rxZ27ZtkyTdeeedkqQPPvjAuU1mZqZz3A8AALiwWRlyoqOjlZqaqszMTM2bN0+pqam67LLLfGp27typESNG6PLLL5fH41H79u0lSQUFBZKkkJAQ3XfffXr99dclSRs3btSWLVs4cBkAgItEM383cK6MGTPGOaZm7ty5NcZvv/12tWvXTq+++qri4+NVVVWlrl27qry83KkZN26cevTooX/+85+aN2+eBg4cqHbt2p23bQAAAGfP2pAzZMgQlZeXy+VyKSUlxWfs4MGDys/P16uvvqqbb75ZkvT555/XmKNbt27q3bu3Xn31Vc2fP19z5sw5L70DAIDGszbkBAYGavv27c73J2vVqpWioqL0yiuvqHXr1iooKNBPf/rTWucZN26c0tPT1bx5c91xxx3nvG8AANA0rDwmp5rH45HH46mxPCAgQAsWLFBubq66du2qSZMm6bnnnqt1jhEjRqhZs2YaMWKEQkJCznXLAACgibiMMcbfTVzI9uzZoyuuuELr169Xz549/d0OAACoJ0JOHSoqKnTw4EE99thj2r17t1atWuXvlgAAQANY/eeqxli1apVat26t9evX6+WXX/Z3OwAAoIHYkwMAAKzEnhwAAGAlQg4AALDSRR1yMjIydP3116tFixaKiYnRsGHDlJ+f71Nz/PhxpaWlKSoqSuHh4brrrrtUVFTkjG/atEkjRoxQQkKCQkND1blzZ82ePdtnjpUrV8rlctW4FBYWnpftBAAADXdRh5zs7GylpaVpzZo1WrZsmSoqKjR48GCVlpY6NZMmTdKHH36ohQsXKjs7W/v27XM+fFOScnNzFRMTozfffFNbt27Vz372M02bNq3W/26cn5+v/fv3O5eYmJjzsp0AAKDhrDrw+Ouvv1ZMTIyys7N1yy23yOv1Kjo6WvPnz9fdd98tSdqxY4c6d+6snJwc3XDDDbXOk5aWpu3bt2v58uWSvt2TM2DAAB06dEgtW7Y8X5sDAAAa4aLek3Mqr9crSYqMjJT07V6aiooKJScnOzVXX321EhMTlZOTc9p5quc4WY8ePdS6dWt997vf5f/mAABwgbPms6uqqqo0ceJE3XjjjerataskqbCwUG63u8bel9jY2DqPp1m9erXeeecdLVmyxFnWunVrvfzyy+rdu7fKysr02muvqX///lq7di3/BRkAgAuUNSEnLS1NW7ZsqfXTxOtry5YtGjp0qGbOnKnBgwc7yzt16qROnTo517/zne9o165d+s1vfqM//elPjeobAACcG1b8uSo9PV2LFy/WihUr1LZtW2d5XFycysvLVVxc7FNfVFSkuLg4n2Xbtm3ToEGDNH78eE2fPv2M6+zTp4/+/ve/N0n/AACg6V3UIccYo/T0dL333ntavny5OnTo4DPeq1cvBQUFKSsry1mWn5+vgoICJSUlOcu2bt2qAQMGaNSoUfrlL39Zr3Xn5eWpdevWTbMhAACgyV3Uf65KS0vT/Pnz9cEHH6hFixbOcTYREREKDQ1VRESExo4dq8mTJysyMlIej0cPP/ywkpKSnDOrtmzZooEDByolJUWTJ0925ggMDFR0dLQk6YUXXlCHDh10zTXX6Pjx43rttde0fPlyffLJJ/7ZcAAAcEYX9SnkLper1uXz5s3T6NGjJX37zwAfffRRvf322yorK1NKSop+97vfOX+uevLJJ/XUU0/VmKNdu3bas2ePJGnWrFl65ZVX9K9//UthYWG69tprNWPGDA0YMOCcbBcAAGi8izrkAAAA1OWiPiYHAACgLoQcAABgJUIOAACwEiEHAABYiZADAACsRMgBAABWIuQAAAArEXIAXJT69++viRMn+rsNABcwQg4A661cuVIul6vGh/UCsBshBwAAWImQA+CCV1paqpEjRyo8PFytW7fW888/7zP+pz/9Sb1791aLFi0UFxenH/3oRzpw4IAkac+ePc7nzLVq1Uoul8v5bLuqqiplZGSoQ4cOCg0NVffu3fXnP//5vG4bgHOHkAPggjdlyhRlZ2frgw8+0CeffKKVK1dq48aNznhFRYWefvppbdq0Se+//7727NnjBJmEhAT93//9nyQpPz9f+/fv1+zZsyVJGRkZ+uMf/6iXX35ZW7du1aRJk3TvvfcqOzv7vG8jgKbHB3QCuKAdOXJEUVFRevPNN/WDH/xAkvTNN9+obdu2Gj9+vF544YUat9mwYYOuv/56HT58WOHh4Vq5cqUGDBigQ4cOqWXLlpKksrIyRUZG6tNPP1VSUpJz23Hjxuno0aOaP3/++dg8AOdQM383AACns2vXLpWXl6tv377OssjISHXq1Mm5npubqyeffFKbNm3SoUOHVFVVJUkqKChQly5dap3373//u44eParvfve7PsvLy8t13XXXnYMtAXC+EXIAXNRKS0uVkpKilJQUvfXWW4qOjlZBQYFSUlJUXl5e5+2OHDkiSVqyZInatGnjMxYcHHxOewZwfhByAFzQrrjiCgUFBWnt2rVKTEyUJB06dEhffvml+vXrpx07dujgwYN69tlnlZCQIOnbP1edzO12S5IqKyudZV26dFFwcLAKCgrUr1+/87Q1AM4nQg6AC1p4eLjGjh2rKVOmKCoqSjExMfrZz36mgIBvz5tITEyU2+3Wiy++qAkTJmjLli16+umnfeZo166dXC6XFi9erNtuu02hoaFq0aKFHnvsMU2aNElVVVW66aab5PV6tWrVKnk8Ho0aNcofmwugCXF2FYAL3nPPPaebb75Zt99+u5KTk3XTTTepV69ekqTo6GhlZmZq4cKF6tKli5599ln9+te/9rl9mzZt9NRTT+mnP/2pYmNjlZ6eLkl6+umn9cQTTygjI0OdO3fWkCFDtGTJEnXo0OG8byOApsfZVQAAwErsyQEAAFYi5AAAACsRcgAAgJUIOQAAwEqEHAAAYCVCDgAAsBIhBwAAWImQAwAArETIAQAAViLkAAAAKxFyAACAlQg5AADASv8/Tu25wbfF1N4AAAAASUVORK5CYII=",
            "text/plain": [
              "<Figure size 640x480 with 1 Axes>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "(\n",
        "    universe_counts\n",
        "    .join(\n",
        "        upload_stats_df.select(\"date\", \"n_assets\").rename({\"n_assets\": \"Uploaded\"}),\n",
        "        on=\"date\",\n",
        "        how=\"left\",\n",
        "    )\n",
        "    .sort(\"date\")\n",
        "    .to_pandas()\n",
        "    .set_index(\"date\")\n",
        "    .plot()\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "461ee52f",
      "metadata": {},
      "source": [
        "We can pull some exposures from the new risk dataset to verify."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "id": "f6b61958",
      "metadata": {},
      "outputs": [],
      "source": [
        "exposures_api = bln.equity.exposures.load(\n",
        "    ExposureSettings(\n",
        "        exposures=[\n",
        "            ContinuousExposureGroupSettings(hierarchy=\"market\"),\n",
        "            ContinuousExposureGroupSettings(hierarchy=\"style\", standardize_method=\"equal_weighted\"),\n",
        "        ],\n",
        "    )\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "id": "e7b460da",
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/html": [
              "<div><style>\n",
              ".dataframe > thead > tr,\n",
              ".dataframe > tbody > tr {\n",
              "  text-align: right;\n",
              "  white-space: pre-wrap;\n",
              "}\n",
              "</style>\n",
              "<small>shape: (5, 10)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>bayesid</th><th>market.Market</th><th>style.Dividend</th><th>style.Growth</th><th>style.Leverage</th><th>style.Momentum</th><th>style.Size</th><th>style.Value</th><th>style.Volatility</th></tr><tr><td>date</td><td>str</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2025-05-31</td><td>&quot;ICFFD2AC11&quot;</td><td>1.0</td><td>-0.128174</td><td>-0.615723</td><td>2.275391</td><td>1.486328</td><td>0.090576</td><td>1.849609</td><td>1.155273</td></tr><tr><td>2025-05-31</td><td>&quot;ICFFD5F0F1&quot;</td><td>1.0</td><td>-0.064819</td><td>0.046844</td><td>-0.096985</td><td>-0.65918</td><td>-0.683105</td><td>0.282715</td><td>-1.557617</td></tr><tr><td>2025-05-31</td><td>&quot;ICFFE39A3E&quot;</td><td>1.0</td><td>-0.958008</td><td>-0.464111</td><td>-1.137695</td><td>-0.312256</td><td>-1.629883</td><td>1.832031</td><td>0.97998</td></tr><tr><td>2025-05-31</td><td>&quot;ICFFE54368&quot;</td><td>1.0</td><td>-0.958008</td><td>-0.869629</td><td>0.074036</td><td>-1.070312</td><td>0.495361</td><td>-2.464844</td><td>0.652832</td></tr><tr><td>2025-05-31</td><td>&quot;ICFFEBBB38&quot;</td><td>1.0</td><td>0.159424</td><td>0.405518</td><td>0.124329</td><td>0.418701</td><td>0.081116</td><td>0.270264</td><td>-1.135742</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (5, 10)\n",
              "┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐\n",
              "│ date      ┆ bayesid   ┆ market.Ma ┆ style.Div ┆ … ┆ style.Mom ┆ style.Siz ┆ style.Val ┆ style.Vo │\n",
              "│ ---       ┆ ---       ┆ rket      ┆ idend     ┆   ┆ entum     ┆ e         ┆ ue        ┆ latility │\n",
              "│ date      ┆ str       ┆ ---       ┆ ---       ┆   ┆ ---       ┆ ---       ┆ ---       ┆ ---      │\n",
              "│           ┆           ┆ f32       ┆ f32       ┆   ┆ f32       ┆ f32       ┆ f32       ┆ f32      │\n",
              "╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡\n",
              "│ 2025-05-3 ┆ ICFFD2AC1 ┆ 1.0       ┆ -0.128174 ┆ … ┆ 1.486328  ┆ 0.090576  ┆ 1.849609  ┆ 1.155273 │\n",
              "│ 1         ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-05-3 ┆ ICFFD5F0F ┆ 1.0       ┆ -0.064819 ┆ … ┆ -0.65918  ┆ -0.683105 ┆ 0.282715  ┆ -1.55761 │\n",
              "│ 1         ┆ 1         ┆           ┆           ┆   ┆           ┆           ┆           ┆ 7        │\n",
              "│ 2025-05-3 ┆ ICFFE39A3 ┆ 1.0       ┆ -0.958008 ┆ … ┆ -0.312256 ┆ -1.629883 ┆ 1.832031  ┆ 0.97998  │\n",
              "│ 1         ┆ E         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-05-3 ┆ ICFFE5436 ┆ 1.0       ┆ -0.958008 ┆ … ┆ -1.070312 ┆ 0.495361  ┆ -2.464844 ┆ 0.652832 │\n",
              "│ 1         ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆          │\n",
              "│ 2025-05-3 ┆ ICFFEBBB3 ┆ 1.0       ┆ 0.159424  ┆ … ┆ 0.418701  ┆ 0.081116  ┆ 0.270264  ┆ -1.13574 │\n",
              "│ 1         ┆ 8         ┆           ┆           ┆   ┆           ┆           ┆           ┆ 2        │\n",
              "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df = exposures_api.get(universe_settings, standardize_universe=None)\n",
        "\n",
        "df.tail()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": ".venv",
      "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.11.14"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}