{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Portfolio Hierarchies\n",
        "\n",
        "**Prerequisites**\n",
        "* *Portfolios API* Tutorial\n",
        "* *Uploaders API* Tutorial\n",
        "\n",
        "In this tutorial we are going to demonstrate the usage of the Bayesline Portfolio Hierarchies API. The Portfolio Hierarchies API builds on the Portfolios API (see tutorial for an in depth walk through). It allows to combine portfolios with benchmarks and other groupings and by default applies forward filling and drift correction. This forms the foundation for portfolio analytics, where we can simply link a *Portfolio Hierarchy* and obtain analytics (e.g. a return attribution report) for different portfolios with optional benchmarks and other groupings.\n",
        "\n",
        "Specifically, we will introduce and explore:\n",
        "* *Portfolio Hierarchies*\n",
        "* Creating a new *Portfolio Hierarchy*\n",
        "    * Only portfolios\n",
        "    * With benchmarks\n",
        "    * Additional Groupings \n",
        "* Obtaining data\n",
        "* Housekeeping "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Imports & Setup\n",
        "\n",
        "For this tutorial notebook, you will need to import the following packages."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {},
      "outputs": [],
      "source": [
        "import datetime as dt\n",
        "\n",
        "import polars as pl\n",
        "\n",
        "from bayesline.apiclient import BayeslineApiClient\n",
        "\n",
        "from bayesline.api.equity import (\n",
        "    PortfolioHierarchySettings,\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We will also need to have a Bayesline API client configured."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "tags": [
          "skip-execution"
        ]
      },
      "outputs": [],
      "source": [
        "bln = BayeslineApiClient.new_client(\n",
        "    endpoint=\"https://[ENDPOINT]\",\n",
        "    api_key=\"[API-KEY]\",\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The main entrypoint for the Portfolios API sits on `bln.equity.portfoliohierarchies`. All portfolio hierarchies functionality can be reached from here on out.\n",
        "\n",
        "See here for relevant docs:\n",
        "* [Portfolio Hierarchies](https://docs.bayesline.com/0.12.1/_autosummary/bayesline.api.equity.AsyncPortfolioHierarchyApi.html)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [],
      "source": [
        "ph_loader = bln.equity.portfoliohierarchies"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Portfolio Hierarchies\n",
        "\n",
        "In its most plain form a *PortfolioHierarchy* solely consists of a list of portfolio ids and a source or schema that describes where to obtain the data from.\n",
        "\n",
        "Below we create some demo portfolio data and upload it to the system such that it can be used for this demo. See the *Uploaders API* tutorial for an in depth walk through on how to bring data into the Bayesline ecosystem. \n",
        "\n",
        "In this toy example we create four portfolios with 2 holdings prints, 2025-01-01 and 2025-01-31:\n",
        "1. `AGTHX` with two holdings\n",
        "2. `FCNTX` with one holding\n",
        "3. `VADGX` with three holdings\n",
        "3. `SPX` with four holdings"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [],
      "source": [
        "uploader = bln.equity.uploaders.get_data_type(\"portfolios\").get_or_create_dataset(\"portfolio-hierarchies-demo\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "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: (20, 7)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>portfolio_id</th><th>asset_id</th><th>asset_id_type</th><th>date</th><th>currency</th><th>share_qty</th><th>nav</th></tr><tr><td>str</td><td>str</td><td>str</td><td>date</td><td>str</td><td>f64</td><td>f64</td></tr></thead><tbody><tr><td>&quot;AGTHX&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>2026-01-01</td><td>null</td><td>null</td><td>0.5</td></tr><tr><td>&quot;AGTHX&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>2026-01-31</td><td>null</td><td>null</td><td>0.55</td></tr><tr><td>&quot;AGTHX&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>2026-01-01</td><td>null</td><td>null</td><td>0.5</td></tr><tr><td>&quot;AGTHX&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>2026-01-31</td><td>null</td><td>null</td><td>0.45</td></tr><tr><td>&quot;FCNTX&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>2026-01-01</td><td>null</td><td>null</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><td>&hellip;</td></tr><tr><td>&quot;SPX&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>2026-01-31</td><td>null</td><td>null</td><td>0.2</td></tr><tr><td>&quot;SPX&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>2026-01-01</td><td>null</td><td>null</td><td>0.3</td></tr><tr><td>&quot;SPX&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>2026-01-31</td><td>null</td><td>null</td><td>0.25</td></tr><tr><td>&quot;SPX&quot;</td><td>&quot;85371710&quot;</td><td>&quot;cusip8&quot;</td><td>2026-01-01</td><td>null</td><td>null</td><td>0.3</td></tr><tr><td>&quot;SPX&quot;</td><td>&quot;85371710&quot;</td><td>&quot;cusip8&quot;</td><td>2026-01-31</td><td>null</td><td>null</td><td>0.25</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (20, 7)\n",
              "┌──────────────┬───────────┬───────────────┬────────────┬──────────┬───────────┬──────┐\n",
              "│ portfolio_id ┆ asset_id  ┆ asset_id_type ┆ date       ┆ currency ┆ share_qty ┆ nav  │\n",
              "│ ---          ┆ ---       ┆ ---           ┆ ---        ┆ ---      ┆ ---       ┆ ---  │\n",
              "│ str          ┆ str       ┆ str           ┆ date       ┆ str      ┆ f64       ┆ f64  │\n",
              "╞══════════════╪═══════════╪═══════════════╪════════════╪══════════╪═══════════╪══════╡\n",
              "│ AGTHX        ┆ 02079K305 ┆ cusip9        ┆ 2026-01-01 ┆ null     ┆ null      ┆ 0.5  │\n",
              "│ AGTHX        ┆ 02079K305 ┆ cusip9        ┆ 2026-01-31 ┆ null     ┆ null      ┆ 0.55 │\n",
              "│ AGTHX        ┆ 2588173   ┆ sedol7        ┆ 2026-01-01 ┆ null     ┆ null      ┆ 0.5  │\n",
              "│ AGTHX        ┆ 2588173   ┆ sedol7        ┆ 2026-01-31 ┆ null     ┆ null      ┆ 0.45 │\n",
              "│ FCNTX        ┆ 67066G10  ┆ cusip8        ┆ 2026-01-01 ┆ null     ┆ null      ┆ 1.0  │\n",
              "│ …            ┆ …         ┆ …             ┆ …          ┆ …        ┆ …         ┆ …    │\n",
              "│ SPX          ┆ 2588173   ┆ sedol7        ┆ 2026-01-31 ┆ null     ┆ null      ┆ 0.2  │\n",
              "│ SPX          ┆ 67066G10  ┆ cusip8        ┆ 2026-01-01 ┆ null     ┆ null      ┆ 0.3  │\n",
              "│ SPX          ┆ 67066G10  ┆ cusip8        ┆ 2026-01-31 ┆ null     ┆ null      ┆ 0.25 │\n",
              "│ SPX          ┆ 85371710  ┆ cusip8        ┆ 2026-01-01 ┆ null     ┆ null      ┆ 0.3  │\n",
              "│ SPX          ┆ 85371710  ┆ cusip8        ┆ 2026-01-31 ┆ null     ┆ null      ┆ 0.25 │\n",
              "└──────────────┴───────────┴───────────────┴────────────┴──────────┴───────────┴──────┘"
            ]
          },
          "execution_count": 5,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolio_df = pl.DataFrame({\n",
        "    \"portfolio_id\": [\n",
        "        \"AGTHX\", \"AGTHX\", \"AGTHX\", \"AGTHX\",\n",
        "        \"FCNTX\", \"FCNTX\",\n",
        "        \"VADGX\", \"VADGX\", \"VADGX\", \"VADGX\", \"VADGX\", \"VADGX\",\n",
        "        \"SPX\", \"SPX\", \"SPX\", \"SPX\", \"SPX\", \"SPX\", \"SPX\", \"SPX\",\n",
        "    ],\n",
        "    \"asset_id\": [\n",
        "        # AGTHX\n",
        "        \"02079K305\", \"02079K305\", \n",
        "        \"2588173\", \"2588173\",\n",
        "\n",
        "        # FCNTX\n",
        "        \"67066G10\", \"67066G10\",\n",
        "\n",
        "        # VADGX\n",
        "        \"02079K305\", \"02079K305\", \n",
        "        \"2588173\", \"2588173\", \n",
        "        \"67066G10\", \"67066G10\",\n",
        "\n",
        "        # SPX\n",
        "        \"02079K305\", \"02079K305\", \n",
        "        \"2588173\", \"2588173\",\n",
        "        \"67066G10\", \"67066G10\",\n",
        "        \"85371710\", \"85371710\",\n",
        "\n",
        "    ],  \n",
        "    \"asset_id_type\": [\n",
        "        # AGTHX\n",
        "        \"cusip9\", \"cusip9\", \"sedol7\", \"sedol7\",\n",
        "\n",
        "        # FCNTX\n",
        "        \"cusip8\", \"cusip8\",\n",
        "\n",
        "        # VADGX\n",
        "        \"cusip9\", \"cusip9\", \"sedol7\", \"sedol7\", \"cusip8\", \"cusip8\",\n",
        "\n",
        "        # SPX\n",
        "        \"cusip9\", \"cusip9\", \"sedol7\", \"sedol7\", \"cusip8\", \"cusip8\", \"cusip8\", \"cusip8\",\n",
        "        \n",
        "    ],\n",
        "    \"date\": [\n",
        "        # AGTHX\n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31),\n",
        "\n",
        "        # FCNTX\n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31),\n",
        "\n",
        "        # VADGX\n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        \n",
        "        # SPX\n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "        dt.date(2026, 1, 1), dt.date(2026, 1, 31), \n",
        "    ],\n",
        "    \"currency\": [None] * 20,\n",
        "    \"share_qty\": [None] * 20,\n",
        "    \"nav\": [\n",
        "        # AGTHX\n",
        "        0.5, 0.55, \n",
        "        0.5, 0.45,\n",
        "\n",
        "        # FCNTX\n",
        "        1.0, 1.0,\n",
        "\n",
        "        # VADGX\n",
        "        0.3, 0.5, \n",
        "        0.4, 0.2,\n",
        "        0.3, 0.25,\n",
        "\n",
        "        # SPX\n",
        "        0.3, 0.3, \n",
        "        0.4, 0.2,\n",
        "        0.3, 0.25,\n",
        "        0.3, 0.25,\n",
        "    ],\n",
        "}).with_columns(pl.col(\"currency\").cast(pl.String), pl.col(\"share_qty\").cast(pl.Float64))\n",
        "\n",
        "portfolio_df"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "UploadCommitResult(version=1, committed_names=[])"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "uploader.fast_commit(portfolio_df, mode=\"append\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Hierarchy with only Portfolios \n",
        "\n",
        "Next up we create a portfolio hierarchy with only two of the portfolios we created. This is the first use case of the hierarchy, to subset a larger source of portfolios to only those that are relevant for a specific analysis.\n",
        "\n",
        "Note that the `portfolio_ids` must be unique for a hierarchy to be valid."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {},
      "outputs": [],
      "source": [
        "ph_settings = PortfolioHierarchySettings.from_source(\n",
        "    source=\"portfolio-hierarchies-demo\",\n",
        "    portfolio_ids=[\"AGTHX\", \"SPX\"],\n",
        ")\n",
        "\n",
        "ph_api = ph_loader.load(ph_settings)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Below we obtain holdings data for our setup and we find that:\n",
        "\n",
        "1. Only our two specified portfolios are present\n",
        "2. The values have been forward filled and drift corrected\n",
        "3. The benchmark is unset (as specified)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "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: (155, 8)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id_type</th><th>input_asset_id</th><th>currency</th><th>nav</th><th>nav_bench</th></tr><tr><td>date</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.4</td><td>null</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></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.55</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.45</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>0.25</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.2</td><td>null</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (155, 8)\n",
              "┌────────────┬─────────────┬─────────────┬─────────────┬─────────────┬──────────┬──────┬───────────┐\n",
              "│ date       ┆ portfolio_g ┆ portfolio_i ┆ input_asset ┆ input_asset ┆ currency ┆ nav  ┆ nav_bench │\n",
              "│ ---        ┆ roup        ┆ d           ┆ _id_type    ┆ _id         ┆ ---      ┆ ---  ┆ ---       │\n",
              "│ date       ┆ ---         ┆ ---         ┆ ---         ┆ ---         ┆ str      ┆ f32  ┆ f32       │\n",
              "│            ┆ str         ┆ str         ┆ str         ┆ str         ┆          ┆      ┆           │\n",
              "╞════════════╪═════════════╪═════════════╪═════════════╪═════════════╪══════════╪══════╪═══════════╡\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.5  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.5  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ SPX         ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ SPX         ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ SPX         ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.4  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ …          ┆ …           ┆ …           ┆ …           ┆ …           ┆ …        ┆ …    ┆ …         │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ AGTHX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.55 ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ AGTHX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.45 ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 0.25 ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.2  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "└────────────┴─────────────┴─────────────┴─────────────┴─────────────┴──────────┴──────┴───────────┘"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_api.get(start_date=dt.date(2026, 1, 1), end_date=dt.date(2026, 1, 31))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Adding Benchmarks\n",
        "\n",
        "We can add a benchmark to our hierarchy which will populate the benchmark column. Note that we can selectively specify a benchmark, for instance we could benchmark `AGTHX` against `SPX` but leave `SPX` itself unbenchmarked."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {},
      "outputs": [],
      "source": [
        "ph_settings = PortfolioHierarchySettings.from_source(\n",
        "    source=\"portfolio-hierarchies-demo\",\n",
        "    portfolio_ids=[\"AGTHX\", \"SPX\"],\n",
        "    benchmark_ids=[\"SPX\", None],\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {},
      "outputs": [],
      "source": [
        "ph_api = ph_loader.load(ph_settings)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note that the `null` observations are cases where either portfolio or benchmark as a holding but the other does not (in its respective id space)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "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: (186, 8)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id_type</th><th>input_asset_id</th><th>currency</th><th>nav</th><th>nav_bench</th></tr><tr><td>date</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.4</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</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></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.55</td><td>0.3</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.45</td><td>0.2</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>0.25</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.2</td><td>null</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (186, 8)\n",
              "┌────────────┬─────────────┬─────────────┬─────────────┬─────────────┬──────────┬──────┬───────────┐\n",
              "│ date       ┆ portfolio_g ┆ portfolio_i ┆ input_asset ┆ input_asset ┆ currency ┆ nav  ┆ nav_bench │\n",
              "│ ---        ┆ roup        ┆ d           ┆ _id_type    ┆ _id         ┆ ---      ┆ ---  ┆ ---       │\n",
              "│ date       ┆ ---         ┆ ---         ┆ ---         ┆ ---         ┆ str      ┆ f32  ┆ f32       │\n",
              "│            ┆ str         ┆ str         ┆ str         ┆ str         ┆          ┆      ┆           │\n",
              "╞════════════╪═════════════╪═════════════╪═════════════╪═════════════╪══════════╪══════╪═══════════╡\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ null ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.5  ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.5  ┆ 0.4       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ SPX         ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ SPX         ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ …          ┆ …           ┆ …           ┆ …           ┆ …           ┆ …        ┆ …    ┆ …         │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ AGTHX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.55 ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ AGTHX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.45 ┆ 0.2       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 0.25 ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ SPX         ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.2  ┆ null      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "└────────────┴─────────────┴─────────────┴─────────────┴─────────────┴──────────┴──────┴───────────┘"
            ]
          },
          "execution_count": 11,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_api.get(start_date=dt.date(2026, 1, 1), end_date=dt.date(2026, 1, 31))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can pass one of the supported output id types to map ids on the fly."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'AGTHX': ['bayesid'], 'SPX': ['bayesid']}"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_api.get_id_types()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "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: (186, 10)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id_type</th><th>input_asset_id</th><th>asset_id_type</th><th>asset_id</th><th>currency</th><th>nav</th><th>nav_bench</th></tr><tr><td>date</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;IC46D464E0&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICF982536B&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.4</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;IC46D464E0&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</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>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;USD&quot;</td><td>0.55</td><td>0.3</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICF982536B&quot;</td><td>&quot;USD&quot;</td><td>0.45</td><td>0.2</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;IC46D464E0&quot;</td><td>&quot;USD&quot;</td><td>0.25</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;USD&quot;</td><td>0.3</td><td>null</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;SPX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;bayesid&quot;</td><td>&quot;ICF982536B&quot;</td><td>&quot;USD&quot;</td><td>0.2</td><td>null</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (186, 10)\n",
              "┌────────────┬────────────┬────────────┬────────────┬───┬────────────┬──────────┬──────┬───────────┐\n",
              "│ date       ┆ portfolio_ ┆ portfolio_ ┆ input_asse ┆ … ┆ asset_id   ┆ currency ┆ nav  ┆ nav_bench │\n",
              "│ ---        ┆ group      ┆ id         ┆ t_id_type  ┆   ┆ ---        ┆ ---      ┆ ---  ┆ ---       │\n",
              "│ date       ┆ ---        ┆ ---        ┆ ---        ┆   ┆ str        ┆ str      ┆ f32  ┆ f32       │\n",
              "│            ┆ str        ┆ str        ┆ str        ┆   ┆            ┆          ┆      ┆           │\n",
              "╞════════════╪════════════╪════════════╪════════════╪═══╪════════════╪══════════╪══════╪═══════════╡\n",
              "│ 2026-01-01 ┆ portfolio- ┆ AGTHX      ┆ cusip8     ┆ … ┆ IC46D464E0 ┆ USD      ┆ null ┆ 0.3       │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio- ┆ AGTHX      ┆ cusip9     ┆ … ┆ ICA17F00B9 ┆ USD      ┆ 0.5  ┆ 0.3       │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio- ┆ AGTHX      ┆ sedol7     ┆ … ┆ ICF982536B ┆ USD      ┆ 0.5  ┆ 0.4       │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio- ┆ SPX        ┆ cusip8     ┆ … ┆ IC46D464E0 ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio- ┆ SPX        ┆ cusip9     ┆ … ┆ ICA17F00B9 ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ …          ┆ …          ┆ …          ┆ …          ┆ … ┆ …          ┆ …        ┆ …    ┆ …         │\n",
              "│ 2026-01-31 ┆ portfolio- ┆ AGTHX      ┆ cusip9     ┆ … ┆ ICA17F00B9 ┆ USD      ┆ 0.55 ┆ 0.3       │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio- ┆ AGTHX      ┆ sedol7     ┆ … ┆ ICF982536B ┆ USD      ┆ 0.45 ┆ 0.2       │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio- ┆ SPX        ┆ cusip8     ┆ … ┆ IC46D464E0 ┆ USD      ┆ 0.25 ┆ null      │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio- ┆ SPX        ┆ cusip9     ┆ … ┆ ICA17F00B9 ┆ USD      ┆ 0.3  ┆ null      │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio- ┆ SPX        ┆ sedol7     ┆ … ┆ ICF982536B ┆ USD      ┆ 0.2  ┆ null      │\n",
              "│            ┆ hierarchie ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "│            ┆ s-demo     ┆            ┆            ┆   ┆            ┆          ┆      ┆           │\n",
              "└────────────┴────────────┴────────────┴────────────┴───┴────────────┴──────────┴──────┴───────────┘"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_api.get(start_date=dt.date(2026, 1, 1), end_date=dt.date(2026, 1, 31), id_type=\"bayesid\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Adding Additional Groupings\n",
        "\n",
        "We can add additional groupings that downstream can be used to provide additional aggregations for these groupings. For instance we might assign portfolios to managers or a specific investment style.\n",
        "\n",
        "Below we're assigning hypothetical managers *Alex* and *Joanna*. Note that these groupings have no effect on the output of the `ph_loader.get` method but they are picked up downstream by the *Reports API*."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "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, 3)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>Manager</th><th>portfolio_id</th><th>benchmark_id</th></tr><tr><td>str</td><td>str</td><td>str</td></tr></thead><tbody><tr><td>&quot;Alice&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;SPX&quot;</td></tr><tr><td>&quot;Bob&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;SPX&quot;</td></tr><tr><td>&quot;Charlie&quot;</td><td>&quot;VADGX&quot;</td><td>&quot;VADGX&quot;</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (3, 3)\n",
              "┌─────────┬──────────────┬──────────────┐\n",
              "│ Manager ┆ portfolio_id ┆ benchmark_id │\n",
              "│ ---     ┆ ---          ┆ ---          │\n",
              "│ str     ┆ str          ┆ str          │\n",
              "╞═════════╪══════════════╪══════════════╡\n",
              "│ Alice   ┆ AGTHX        ┆ SPX          │\n",
              "│ Bob     ┆ FCNTX        ┆ SPX          │\n",
              "│ Charlie ┆ VADGX        ┆ VADGX        │\n",
              "└─────────┴──────────────┴──────────────┘"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_settings = PortfolioHierarchySettings.from_source(\n",
        "    source=\"portfolio-hierarchies-demo\",\n",
        "    portfolio_ids=[\"AGTHX\", \"FCNTX\", \"VADGX\"],\n",
        "    benchmark_ids=[\"SPX\", \"SPX\", \"VADGX\"],\n",
        "    groupings={\"Manager\": [\"Alice\", \"Bob\", \"Charlie\"]},\n",
        ")\n",
        "\n",
        "\n",
        "ph_settings.to_polars()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Creating from Polars\n",
        "\n",
        "As a shorthand it might be more convenient to create a hierarchy from a data frame instead of manually specifying the Pydantic object."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "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, 3)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>Manager</th><th>portfolio_id</th><th>benchmark_id</th></tr><tr><td>str</td><td>str</td><td>str</td></tr></thead><tbody><tr><td>&quot;Alice&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;SPX&quot;</td></tr><tr><td>&quot;Bob&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;SPX&quot;</td></tr><tr><td>&quot;Charlie&quot;</td><td>&quot;VADGX&quot;</td><td>&quot;VADGX&quot;</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (3, 3)\n",
              "┌─────────┬──────────────┬──────────────┐\n",
              "│ Manager ┆ portfolio_id ┆ benchmark_id │\n",
              "│ ---     ┆ ---          ┆ ---          │\n",
              "│ str     ┆ str          ┆ str          │\n",
              "╞═════════╪══════════════╪══════════════╡\n",
              "│ Alice   ┆ AGTHX        ┆ SPX          │\n",
              "│ Bob     ┆ FCNTX        ┆ SPX          │\n",
              "│ Charlie ┆ VADGX        ┆ VADGX        │\n",
              "└─────────┴──────────────┴──────────────┘"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_settings_df = ph_settings.to_polars()\n",
        "\n",
        "ph_settings_df"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [],
      "source": [
        "ph_settings = PortfolioHierarchySettings.from_polars(\n",
        "    ph_settings_df, \n",
        "    portfolio_source=\"portfolio-hierarchies-demo\"\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "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: (279, 8)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id_type</th><th>input_asset_id</th><th>currency</th><th>nav</th><th>nav_bench</th></tr><tr><td>date</td><td>str</td><td>str</td><td>str</td><td>str</td><td>str</td><td>f32</td><td>f32</td></tr></thead><tbody><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;AGTHX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.4</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>1.0</td><td>0.3</td></tr><tr><td>2026-01-01</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.3</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></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.3</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;FCNTX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>null</td><td>0.2</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;VADGX&quot;</td><td>&quot;cusip8&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;USD&quot;</td><td>0.25</td><td>0.25</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;VADGX&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;USD&quot;</td><td>0.5</td><td>0.5</td></tr><tr><td>2026-01-31</td><td>&quot;portfolio-hierarchies-demo&quot;</td><td>&quot;VADGX&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;2588173&quot;</td><td>&quot;USD&quot;</td><td>0.2</td><td>0.2</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (279, 8)\n",
              "┌────────────┬─────────────┬─────────────┬─────────────┬─────────────┬──────────┬──────┬───────────┐\n",
              "│ date       ┆ portfolio_g ┆ portfolio_i ┆ input_asset ┆ input_asset ┆ currency ┆ nav  ┆ nav_bench │\n",
              "│ ---        ┆ roup        ┆ d           ┆ _id_type    ┆ _id         ┆ ---      ┆ ---  ┆ ---       │\n",
              "│ date       ┆ ---         ┆ ---         ┆ ---         ┆ ---         ┆ str      ┆ f32  ┆ f32       │\n",
              "│            ┆ str         ┆ str         ┆ str         ┆ str         ┆          ┆      ┆           │\n",
              "╞════════════╪═════════════╪═════════════╪═════════════╪═════════════╪══════════╪══════╪═══════════╡\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ null ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.5  ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ AGTHX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.5  ┆ 0.4       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ FCNTX       ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 1.0  ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-01 ┆ portfolio-h ┆ FCNTX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ null ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ …          ┆ …           ┆ …           ┆ …           ┆ …           ┆ …        ┆ …    ┆ …         │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ FCNTX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ null ┆ 0.3       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ FCNTX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ null ┆ 0.2       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ VADGX       ┆ cusip8      ┆ 67066G10    ┆ USD      ┆ 0.25 ┆ 0.25      │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ VADGX       ┆ cusip9      ┆ 02079K305   ┆ USD      ┆ 0.5  ┆ 0.5       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│ 2026-01-31 ┆ portfolio-h ┆ VADGX       ┆ sedol7      ┆ 2588173     ┆ USD      ┆ 0.2  ┆ 0.2       │\n",
              "│            ┆ ierarchies- ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "│            ┆ demo        ┆             ┆             ┆             ┆          ┆      ┆           │\n",
              "└────────────┴─────────────┴─────────────┴─────────────┴─────────────┴──────────┴──────┴───────────┘"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "ph_api = ph_loader.load(ph_settings)\n",
        "\n",
        "ph_api.get(start_date=dt.date(2026, 1, 1), end_date=dt.date(2026, 1, 31))"
      ]
    }
  ],
  "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.15"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}