{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Portfolios\n",
        "\n",
        "**Prerequisites**\n",
        "* *Uploaders API* Tutorial\n",
        "\n",
        "\n",
        "In this tutorial we are going to demonstrate the usage of the Bayesline Portfolios API. The Portfolios API provides a unified access mechanism to bring portfolio holdings data into the system such that it can be used downstream (e.g. for risk analytics).\n",
        "\n",
        "Specifically, we will introduce and explore:\n",
        "* *Portfolio Sources*\n",
        "* Listing existing portfolio sources\n",
        "* Uploading new portfolio data (adding to a source, creating a new source) \n",
        "* Reading portfolio data\n",
        "* Forward filling holdings data with drift correction\n",
        "* Funds of funds structures\n",
        "* *Portfolio Schemas* (advanced)"
      ]
    },
    {
      "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",
        "    PortfolioSettings,\n",
        "    PortfolioOrganizerSettings,\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.portfolios`. All portfolios functionality can be reached from here on out.\n",
        "\n",
        "See here for relevant docs:\n",
        "* [Portfolios API Summary](https://docs.bayesline.com/0.9.2/_autosummary/bayesline.api.equity.AsyncPortfolioApi.html)\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {},
      "outputs": [],
      "source": [
        "portfolios_loader = bln.equity.portfolios"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Portfolio Sources\n",
        "\n",
        "A portfolio source is an isolated dataset that contains holdings information for different portfolios. This could be a system source (e.g. from a database) or user uploaded data.\n",
        "\n",
        "For each source it is guaranteed that the data is free of duplications and otherwise consistent.\n",
        "\n",
        "### Listing Available Portfolio Sources\n",
        "Below demonstrates how to obtain the list of available sources using the settings menu."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "PortfolioSettingsMenu(sources=[], schemas=[])"
            ]
          },
          "execution_count": 4,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_loader.settings.available_settings()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Uploading a Portfolio Source\n",
        "\n",
        "A new portfolio source can be added using the *portfolios* uploader, which can be obtained through the `uploader` property (note that this is a shortcut for using `bln.equity.uploaders.get_data_type(\"portfolios\")`, which yields the same uploader).\n",
        "\n",
        "Given above showed no existing portfolio sources we should find that the uploader has no datasets."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {},
      "outputs": [],
      "source": [
        "uploader = portfolios_loader.uploader"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[]"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "uploader.get_datasets()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Next let's create a new *portfolios* dataset and upload some sample data. For a more detailed walk through on the uploader infrastructure (including parsers, example inputs, versioning, etc.) see the **Bayesline Uploaders Tutorial**."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {},
      "outputs": [],
      "source": [
        "demo_portfolio_dataset = uploader.get_or_create_dataset(\"demo-portfolios\")"
      ]
    },
    {
      "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: (6, 5)</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>value</th></tr><tr><td>str</td><td>str</td><td>str</td><td>date</td><td>i64</td></tr></thead><tbody><tr><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>2025-01-01</td><td>100</td></tr><tr><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>2025-01-31</td><td>110</td></tr><tr><td>&quot;Test-Portfolio&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>2025-01-15</td><td>200</td></tr><tr><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;85371710&quot;</td><td>&quot;cusip8&quot;</td><td>2025-01-01</td><td>50</td></tr><tr><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;85371710&quot;</td><td>&quot;cusip8&quot;</td><td>2025-01-13</td><td>55</td></tr><tr><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;85371710&quot;</td><td>&quot;cusip8&quot;</td><td>2025-02-15</td><td>54</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (6, 5)\n",
              "┌──────────────────┬───────────┬───────────────┬────────────┬───────┐\n",
              "│ portfolio_id     ┆ asset_id  ┆ asset_id_type ┆ date       ┆ value │\n",
              "│ ---              ┆ ---       ┆ ---           ┆ ---        ┆ ---   │\n",
              "│ str              ┆ str       ┆ str           ┆ date       ┆ i64   │\n",
              "╞══════════════════╪═══════════╪═══════════════╪════════════╪═══════╡\n",
              "│ Test-Portfolio   ┆ 02079K305 ┆ cusip9        ┆ 2025-01-01 ┆ 100   │\n",
              "│ Test-Portfolio   ┆ 02079K305 ┆ cusip9        ┆ 2025-01-31 ┆ 110   │\n",
              "│ Test-Portfolio   ┆ 2588173   ┆ sedol7        ┆ 2025-01-15 ┆ 200   │\n",
              "│ Test-Portfolio-2 ┆ 85371710  ┆ cusip8        ┆ 2025-01-01 ┆ 50    │\n",
              "│ Test-Portfolio-2 ┆ 85371710  ┆ cusip8        ┆ 2025-01-13 ┆ 55    │\n",
              "│ Test-Portfolio-2 ┆ 85371710  ┆ cusip8        ┆ 2025-02-15 ┆ 54    │\n",
              "└──────────────────┴───────────┴───────────────┴────────────┴───────┘"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df = pl.DataFrame({\n",
        "    \"portfolio_id\": [\n",
        "        \"Test-Portfolio\", \"Test-Portfolio\", \"Test-Portfolio\",\n",
        "        \"Test-Portfolio-2\", \"Test-Portfolio-2\", \"Test-Portfolio-2\",\n",
        "    ],\n",
        "    \"asset_id\": [\n",
        "        \"02079K305\", \"02079K305\", \"2588173\",\n",
        "        \"85371710\", \"85371710\", \"85371710\"\n",
        "    ],\n",
        "    \"asset_id_type\": [\n",
        "        \"cusip9\", \"cusip9\", \"sedol7\",\n",
        "        \"cusip8\", \"cusip8\", \"cusip8\"\n",
        "    ],\n",
        "    \"date\": [\n",
        "        dt.date(2025, 1, 1), dt.date(2025, 1, 31), dt.date(2025, 1, 15),\n",
        "        dt.date(2025, 1, 1), dt.date(2025, 1, 13), dt.date(2025, 2, 15),\n",
        "    ],\n",
        "    \"value\": [\n",
        "        100, 110, 200,\n",
        "        50, 55, 54\n",
        "    ]\n",
        "})\n",
        "\n",
        "df"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "UploadCommitResult(version=1, committed_names=[])"
            ]
          },
          "execution_count": 9,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "demo_portfolio_dataset.fast_commit(df, mode=\"append\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Reading Portfolio Data\n",
        "\n",
        "Having uploaded a portfolio source we can now use the portfolio loader to obtain the portfolio."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "PortfolioSettingsMenu(sources=['demo-portfolios'], schemas=[])"
            ]
          },
          "execution_count": 10,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_loader.settings.available_settings()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {},
      "outputs": [],
      "source": [
        "portfolios_api = portfolios_loader.load(PortfolioSettings.from_source(\"demo-portfolios\"))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Why use a separate *Portfolios API* to obtain this data, as opposed to just using the uploader infrastructure to read the data back? \n",
        "The *Portfolios API* adds plenty of functionality that is specific to the domain of portfolios, e.g. coverage statistics, forward filling and drifting, etc.\n",
        "\n",
        "Below demonstrates this functionality."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['Test-Portfolio', 'Test-Portfolio-2']"
            ]
          },
          "execution_count": 12,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio_names()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'Test-Portfolio': [datetime.date(2025, 1, 1),\n",
              "  datetime.date(2025, 1, 15),\n",
              "  datetime.date(2025, 1, 31)],\n",
              " 'Test-Portfolio-2': [datetime.date(2025, 1, 1),\n",
              "  datetime.date(2025, 1, 13),\n",
              "  datetime.date(2025, 2, 15)]}"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_dates()"
      ]
    },
    {
      "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: (6, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>portfolio_group</th><th>portfolio_id</th><th>date</th><th>asset_id_type</th><th>input</th><th>bayesid</th></tr><tr><td>str</td><td>str</td><td>date</td><td>str</td><td>u32</td><td>u32</td></tr></thead><tbody><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>2025-01-13</td><td>&quot;cusip8&quot;</td><td>1</td><td>0</td></tr><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>2025-02-15</td><td>&quot;cusip8&quot;</td><td>1</td><td>0</td></tr><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>2025-01-15</td><td>&quot;sedol7&quot;</td><td>1</td><td>1</td></tr><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>2025-01-01</td><td>&quot;cusip8&quot;</td><td>1</td><td>0</td></tr><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>2025-01-01</td><td>&quot;cusip9&quot;</td><td>1</td><td>1</td></tr><tr><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>2025-01-31</td><td>&quot;cusip9&quot;</td><td>1</td><td>1</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (6, 6)\n",
              "┌─────────────────┬──────────────────┬────────────┬───────────────┬───────┬─────────┐\n",
              "│ portfolio_group ┆ portfolio_id     ┆ date       ┆ asset_id_type ┆ input ┆ bayesid │\n",
              "│ ---             ┆ ---              ┆ ---        ┆ ---           ┆ ---   ┆ ---     │\n",
              "│ str             ┆ str              ┆ date       ┆ str           ┆ u32   ┆ u32     │\n",
              "╞═════════════════╪══════════════════╪════════════╪═══════════════╪═══════╪═════════╡\n",
              "│ demo-portfolios ┆ Test-Portfolio-2 ┆ 2025-01-13 ┆ cusip8        ┆ 1     ┆ 0       │\n",
              "│ demo-portfolios ┆ Test-Portfolio-2 ┆ 2025-02-15 ┆ cusip8        ┆ 1     ┆ 0       │\n",
              "│ demo-portfolios ┆ Test-Portfolio   ┆ 2025-01-15 ┆ sedol7        ┆ 1     ┆ 1       │\n",
              "│ demo-portfolios ┆ Test-Portfolio-2 ┆ 2025-01-01 ┆ cusip8        ┆ 1     ┆ 0       │\n",
              "│ demo-portfolios ┆ Test-Portfolio   ┆ 2025-01-01 ┆ cusip9        ┆ 1     ┆ 1       │\n",
              "│ demo-portfolios ┆ Test-Portfolio   ┆ 2025-01-31 ┆ cusip9        ┆ 1     ┆ 1       │\n",
              "└─────────────────┴──────────────────┴────────────┴───────────────┴───────┴─────────┘"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_coverage()"
      ]
    },
    {
      "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, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>value</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-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>100.0</td></tr><tr><td>2025-01-15</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>200.0</td></tr><tr><td>2025-01-31</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>110.0</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (3, 6)\n",
              "┌────────────┬─────────────────┬────────────────┬────────────────┬─────────────────────┬───────┐\n",
              "│ date       ┆ portfolio_group ┆ portfolio_id   ┆ input_asset_id ┆ input_asset_id_type ┆ value │\n",
              "│ ---        ┆ ---             ┆ ---            ┆ ---            ┆ ---                 ┆ ---   │\n",
              "│ date       ┆ str             ┆ str            ┆ str            ┆ str                 ┆ f32   │\n",
              "╞════════════╪═════════════════╪════════════════╪════════════════╪═════════════════════╪═══════╡\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9              ┆ 100.0 │\n",
              "│ 2025-01-15 ┆ demo-portfolios ┆ Test-Portfolio ┆ 2588173        ┆ sedol7              ┆ 200.0 │\n",
              "│ 2025-01-31 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9              ┆ 110.0 │\n",
              "└────────────┴─────────────────┴────────────────┴────────────────┴─────────────────────┴───────┘"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio(names=[\"Test-Portfolio\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note how above the ID space is the input ID space, i.e. the IDs that were uploaded. These IDs can be mapped to one of the supported target ID spaces. Note that if IDs cannot be mapped to output values will be `None`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "{'Test-Portfolio-2': ['bayesid'], 'Test-Portfolio': ['bayesid']}"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_id_types()"
      ]
    },
    {
      "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: (3, 8)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>asset_id</th><th>asset_id_type</th><th>value</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>f32</td></tr></thead><tbody><tr><td>2025-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;bayesid&quot;</td><td>100.0</td></tr><tr><td>2025-01-15</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;2588173&quot;</td><td>&quot;sedol7&quot;</td><td>&quot;ICF982536B&quot;</td><td>&quot;bayesid&quot;</td><td>200.0</td></tr><tr><td>2025-01-31</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>&quot;ICA17F00B9&quot;</td><td>&quot;bayesid&quot;</td><td>110.0</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (3, 8)\n",
              "┌────────────┬────────────┬────────────┬────────────┬────────────┬────────────┬────────────┬───────┐\n",
              "│ date       ┆ portfolio_ ┆ portfolio_ ┆ input_asse ┆ input_asse ┆ asset_id   ┆ asset_id_t ┆ value │\n",
              "│ ---        ┆ group      ┆ id         ┆ t_id       ┆ t_id_type  ┆ ---        ┆ ype        ┆ ---   │\n",
              "│ date       ┆ ---        ┆ ---        ┆ ---        ┆ ---        ┆ str        ┆ ---        ┆ f32   │\n",
              "│            ┆ str        ┆ str        ┆ str        ┆ str        ┆            ┆ str        ┆       │\n",
              "╞════════════╪════════════╪════════════╪════════════╪════════════╪════════════╪════════════╪═══════╡\n",
              "│ 2025-01-01 ┆ demo-portf ┆ Test-Portf ┆ 02079K305  ┆ cusip9     ┆ ICA17F00B9 ┆ bayesid    ┆ 100.0 │\n",
              "│            ┆ olios      ┆ olio       ┆            ┆            ┆            ┆            ┆       │\n",
              "│ 2025-01-15 ┆ demo-portf ┆ Test-Portf ┆ 2588173    ┆ sedol7     ┆ ICF982536B ┆ bayesid    ┆ 200.0 │\n",
              "│            ┆ olios      ┆ olio       ┆            ┆            ┆            ┆            ┆       │\n",
              "│ 2025-01-31 ┆ demo-portf ┆ Test-Portf ┆ 02079K305  ┆ cusip9     ┆ ICA17F00B9 ┆ bayesid    ┆ 110.0 │\n",
              "│            ┆ olios      ┆ olio       ┆            ┆            ┆            ┆            ┆       │\n",
              "└────────────┴────────────┴────────────┴────────────┴────────────┴────────────┴────────────┴───────┘"
            ]
          },
          "execution_count": 17,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio(names=[\"Test-Portfolio\"], id_type=\"bayesid\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Forward Filling and Drift Correction\n",
        "\n",
        "The demo portfolio data was uploaded with a monthly frequency. Obtaining them back will yield the data unaltered. We can pass settings to automatically forward fill and drift correct the data. We do this at top level by passing the relevant settings to the `PortfolioSettings` object."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {},
      "outputs": [],
      "source": [
        "portfolios_api = portfolios_loader.load(\n",
        "    PortfolioSettings.from_source(\"demo-portfolios\", ffill=\"ffill-with-drift\")\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "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: (237, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>value</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-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>100.0</td></tr><tr><td>2025-01-02</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>100.068649</td></tr><tr><td>2025-01-03</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>101.315361</td></tr><tr><td>2025-01-04</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>101.315361</td></tr><tr><td>2025-01-05</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>101.315361</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-08-21</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>107.956406</td></tr><tr><td>2025-08-22</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>111.382881</td></tr><tr><td>2025-08-23</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>111.382881</td></tr><tr><td>2025-08-24</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>111.382881</td></tr><tr><td>2025-08-25</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>112.680031</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (237, 6)\n",
              "┌────────────┬─────────────────┬────────────────┬────────────────┬────────────────────┬────────────┐\n",
              "│ date       ┆ portfolio_group ┆ portfolio_id   ┆ input_asset_id ┆ input_asset_id_typ ┆ value      │\n",
              "│ ---        ┆ ---             ┆ ---            ┆ ---            ┆ e                  ┆ ---        │\n",
              "│ date       ┆ str             ┆ str            ┆ str            ┆ ---                ┆ f32        │\n",
              "│            ┆                 ┆                ┆                ┆ str                ┆            │\n",
              "╞════════════╪═════════════════╪════════════════╪════════════════╪════════════════════╪════════════╡\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 100.0      │\n",
              "│ 2025-01-02 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 100.068649 │\n",
              "│ 2025-01-03 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 101.315361 │\n",
              "│ 2025-01-04 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 101.315361 │\n",
              "│ 2025-01-05 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 101.315361 │\n",
              "│ …          ┆ …               ┆ …              ┆ …              ┆ …                  ┆ …          │\n",
              "│ 2025-08-21 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 107.956406 │\n",
              "│ 2025-08-22 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 111.382881 │\n",
              "│ 2025-08-23 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 111.382881 │\n",
              "│ 2025-08-24 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 111.382881 │\n",
              "│ 2025-08-25 ┆ demo-portfolios ┆ Test-Portfolio ┆ 02079K305      ┆ cusip9             ┆ 112.680031 │\n",
              "└────────────┴─────────────────┴────────────────┴────────────────┴────────────────────┴────────────┘"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio(names=[\"Test-Portfolio\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Funds of Funds\n",
        "\n",
        "We can represent fund of funds structures easily by using the portfolio-id as the respective asset ids and `portfolio_id` as the asset id type.\n",
        "\n",
        "Below we're uploading a fund of funds portfolios to our existing dataset by *appending* it to the existing data."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "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, 5)</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>value</th></tr><tr><td>str</td><td>str</td><td>str</td><td>date</td><td>f64</td></tr></thead><tbody><tr><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;portfolio_id&quot;</td><td>2025-01-01</td><td>0.5</td></tr><tr><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;portfolio_id&quot;</td><td>2025-01-31</td><td>0.55</td></tr><tr><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;portfolio_id&quot;</td><td>2025-01-01</td><td>0.5</td></tr><tr><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;portfolio_id&quot;</td><td>2025-01-31</td><td>0.45</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (4, 5)\n",
              "┌──────────────┬──────────────────┬───────────────┬────────────┬───────┐\n",
              "│ portfolio_id ┆ asset_id         ┆ asset_id_type ┆ date       ┆ value │\n",
              "│ ---          ┆ ---              ┆ ---           ┆ ---        ┆ ---   │\n",
              "│ str          ┆ str              ┆ str           ┆ date       ┆ f64   │\n",
              "╞══════════════╪══════════════════╪═══════════════╪════════════╪═══════╡\n",
              "│ My-FOF       ┆ Test-Portfolio   ┆ portfolio_id  ┆ 2025-01-01 ┆ 0.5   │\n",
              "│ My-FOF       ┆ Test-Portfolio   ┆ portfolio_id  ┆ 2025-01-31 ┆ 0.55  │\n",
              "│ My-FOF       ┆ Test-Portfolio-2 ┆ portfolio_id  ┆ 2025-01-01 ┆ 0.5   │\n",
              "│ My-FOF       ┆ Test-Portfolio-2 ┆ portfolio_id  ┆ 2025-01-31 ┆ 0.45  │\n",
              "└──────────────┴──────────────────┴───────────────┴────────────┴───────┘"
            ]
          },
          "execution_count": 20,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "fof_portfolio_df = pl.DataFrame({\n",
        "    \"portfolio_id\": [\n",
        "        \"My-FOF\", \"My-FOF\", \"My-FOF\", \"My-FOF\"\n",
        "    ],\n",
        "    \"asset_id\": [\n",
        "        \"Test-Portfolio\", \"Test-Portfolio\", \"Test-Portfolio-2\", \"Test-Portfolio-2\"\n",
        "    ],\n",
        "    \"asset_id_type\": [\n",
        "        \"portfolio_id\", \"portfolio_id\", \"portfolio_id\", \"portfolio_id\"\n",
        "    ],\n",
        "    \"date\": [\n",
        "        dt.date(2025, 1, 1), dt.date(2025, 1, 31), dt.date(2025, 1, 1), dt.date(2025, 1, 31)\n",
        "    ],\n",
        "    \"value\": [\n",
        "        .5, .55, .5, .45\n",
        "    ]\n",
        "})\n",
        "\n",
        "fof_portfolio_df"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "UploadCommitResult(version=2, committed_names=[])"
            ]
          },
          "execution_count": 21,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "demo_portfolio_dataset.fast_commit(fof_portfolio_df, mode=\"append\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Below we're obtaining the fund of funds portfolio without any alterations."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "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, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>value</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-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;portfolio_id&quot;</td><td>0.5</td></tr><tr><td>2025-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;portfolio_id&quot;</td><td>0.5</td></tr><tr><td>2025-01-31</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;portfolio_id&quot;</td><td>0.55</td></tr><tr><td>2025-01-31</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;portfolio_id&quot;</td><td>0.45</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (4, 6)\n",
              "┌────────────┬─────────────────┬──────────────┬──────────────────┬─────────────────────┬───────┐\n",
              "│ date       ┆ portfolio_group ┆ portfolio_id ┆ input_asset_id   ┆ input_asset_id_type ┆ value │\n",
              "│ ---        ┆ ---             ┆ ---          ┆ ---              ┆ ---                 ┆ ---   │\n",
              "│ date       ┆ str             ┆ str          ┆ str              ┆ str                 ┆ f32   │\n",
              "╞════════════╪═════════════════╪══════════════╪══════════════════╪═════════════════════╪═══════╡\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ My-FOF       ┆ Test-Portfolio   ┆ portfolio_id        ┆ 0.5   │\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ My-FOF       ┆ Test-Portfolio-2 ┆ portfolio_id        ┆ 0.5   │\n",
              "│ 2025-01-31 ┆ demo-portfolios ┆ My-FOF       ┆ Test-Portfolio   ┆ portfolio_id        ┆ 0.55  │\n",
              "│ 2025-01-31 ┆ demo-portfolios ┆ My-FOF       ┆ Test-Portfolio-2 ┆ portfolio_id        ┆ 0.45  │\n",
              "└────────────┴─────────────────┴──────────────┴──────────────────┴─────────────────────┴───────┘"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api = portfolios_loader.load(\n",
        "    PortfolioSettings.from_source(\"demo-portfolios\")\n",
        ")\n",
        "portfolios_api.get_portfolio(names=[\"My-FOF\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We can also configure to unpack the fund of funds structure and forward fill with drift. This is an essential piece of functioanlity to provide fund of fund level analytics."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "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: (237, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>value</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-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>50.0</td></tr><tr><td>2025-01-02</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>50.034325</td></tr><tr><td>2025-01-03</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>50.657681</td></tr><tr><td>2025-01-04</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>50.657681</td></tr><tr><td>2025-01-05</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>50.657681</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-08-21</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>59.376026</td></tr><tr><td>2025-08-22</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>61.260582</td></tr><tr><td>2025-08-23</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>61.260582</td></tr><tr><td>2025-08-24</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>61.260582</td></tr><tr><td>2025-08-25</td><td>&quot;demo-portfolios&quot;</td><td>&quot;My-FOF&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>61.974018</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (237, 6)\n",
              "┌────────────┬─────────────────┬──────────────┬────────────────┬─────────────────────┬───────────┐\n",
              "│ date       ┆ portfolio_group ┆ portfolio_id ┆ input_asset_id ┆ input_asset_id_type ┆ value     │\n",
              "│ ---        ┆ ---             ┆ ---          ┆ ---            ┆ ---                 ┆ ---       │\n",
              "│ date       ┆ str             ┆ str          ┆ str            ┆ str                 ┆ f32       │\n",
              "╞════════════╪═════════════════╪══════════════╪════════════════╪═════════════════════╪═══════════╡\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 50.0      │\n",
              "│ 2025-01-02 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 50.034325 │\n",
              "│ 2025-01-03 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 50.657681 │\n",
              "│ 2025-01-04 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 50.657681 │\n",
              "│ 2025-01-05 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 50.657681 │\n",
              "│ …          ┆ …               ┆ …            ┆ …              ┆ …                   ┆ …         │\n",
              "│ 2025-08-21 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 59.376026 │\n",
              "│ 2025-08-22 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 61.260582 │\n",
              "│ 2025-08-23 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 61.260582 │\n",
              "│ 2025-08-24 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 61.260582 │\n",
              "│ 2025-08-25 ┆ demo-portfolios ┆ My-FOF       ┆ 02079K305      ┆ cusip9              ┆ 61.974018 │\n",
              "└────────────┴─────────────────┴──────────────┴────────────────┴─────────────────────┴───────────┘"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api = portfolios_loader.load(\n",
        "    PortfolioSettings.from_source(\n",
        "        \"demo-portfolios\", ffill=\"ffill-with-drift\", unpack=\"unpack\"\n",
        "    )\n",
        ")\n",
        "portfolios_api.get_portfolio(names=[\"My-FOF\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Portfolio Schemas\n",
        "\n",
        "*Portfolio Schemas* are an advanced topic that sit on top of the *Portfolio Sources* we previously explored. \n",
        "\n",
        "Using *Portfolio Schemas* we can cherry-pick which portfolios should be sourced from what underlying portfolio source. We do this by providing a mapping from `portfolio id -> portfolio source`. This flexibility allows for a powerful means to arbitrarily override portfolio holdings while keeping everything else the same, e.g. to perform what-if analyses.\n",
        "\n",
        "Below we are creating a new `what-if` portfolio dataset where we override holdings for our `Test-Portfolio-2`. We then create a *Portfolio Schema* where we source `Test-Portfolio-2` from our new dataset, keeping the rest the same. "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {},
      "outputs": [],
      "source": [
        "what_if_dataset = uploader.create_dataset(\"what-if\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 25,
      "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: (2, 5)</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>value</th></tr><tr><td>str</td><td>str</td><td>str</td><td>date</td><td>i64</td></tr></thead><tbody><tr><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>2025-01-01</td><td>100</td></tr><tr><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>2025-01-31</td><td>125</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (2, 5)\n",
              "┌──────────────────┬──────────┬───────────────┬────────────┬───────┐\n",
              "│ portfolio_id     ┆ asset_id ┆ asset_id_type ┆ date       ┆ value │\n",
              "│ ---              ┆ ---      ┆ ---           ┆ ---        ┆ ---   │\n",
              "│ str              ┆ str      ┆ str           ┆ date       ┆ i64   │\n",
              "╞══════════════════╪══════════╪═══════════════╪════════════╪═══════╡\n",
              "│ Test-Portfolio-2 ┆ 67066G10 ┆ cusip8        ┆ 2025-01-01 ┆ 100   │\n",
              "│ Test-Portfolio-2 ┆ 67066G10 ┆ cusip8        ┆ 2025-01-31 ┆ 125   │\n",
              "└──────────────────┴──────────┴───────────────┴────────────┴───────┘"
            ]
          },
          "execution_count": 25,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "what_if_portfolio_df = pl.DataFrame({\n",
        "    \"portfolio_id\": [\"Test-Portfolio-2\", \"Test-Portfolio-2\"],\n",
        "    \"asset_id\": [\"67066G10\", \"67066G10\"],\n",
        "    \"asset_id_type\": [\"cusip8\", \"cusip8\"],\n",
        "    \"date\": [dt.date(2025, 1, 1), dt.date(2025, 1, 31)],\n",
        "    \"value\": [100, 125]\n",
        "})\n",
        "\n",
        "what_if_portfolio_df"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "UploadCommitResult(version=1, committed_names=[])"
            ]
          },
          "execution_count": 26,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "what_if_dataset.fast_commit(what_if_portfolio_df, mode=\"append\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 27,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "PortfolioSettingsMenu(sources=['demo-portfolios', 'what-if'], schemas=[])"
            ]
          },
          "execution_count": 27,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_loader.settings.available_settings()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 28,
      "metadata": {},
      "outputs": [],
      "source": [
        "schema = PortfolioOrganizerSettings(\n",
        "    enabled_portfolios={\n",
        "        \"Test-Portfolio\": \"demo-portfolios\",\n",
        "        \"Test-Portfolio-2\": \"what-if\"\n",
        "    }\n",
        ")\n",
        "\n",
        "portfolios_api = portfolios_loader.load(\n",
        "    PortfolioSettings(portfolio_schema=schema, ffill=\"ffill-with-drift\")\n",
        ")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 29,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['Test-Portfolio', 'Test-Portfolio-2']"
            ]
          },
          "execution_count": 29,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio_names()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Note below how `Test-Portfolio-2` has the updated values."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 30,
      "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: (474, 6)</small><table border=\"1\" class=\"dataframe\"><thead><tr><th>date</th><th>portfolio_group</th><th>portfolio_id</th><th>input_asset_id</th><th>input_asset_id_type</th><th>value</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-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>100.0</td></tr><tr><td>2025-01-01</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>100.0</td></tr><tr><td>2025-01-02</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>100.068649</td></tr><tr><td>2025-01-02</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>102.993538</td></tr><tr><td>2025-01-03</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>101.315361</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-08-23</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>185.327362</td></tr><tr><td>2025-08-24</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>111.382881</td></tr><tr><td>2025-08-24</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>185.327362</td></tr><tr><td>2025-08-25</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio&quot;</td><td>&quot;02079K305&quot;</td><td>&quot;cusip9&quot;</td><td>112.680031</td></tr><tr><td>2025-08-25</td><td>&quot;demo-portfolios&quot;</td><td>&quot;Test-Portfolio-2&quot;</td><td>&quot;67066G10&quot;</td><td>&quot;cusip8&quot;</td><td>187.222397</td></tr></tbody></table></div>"
            ],
            "text/plain": [
              "shape: (474, 6)\n",
              "┌────────────┬─────────────────┬──────────────────┬────────────────┬──────────────────┬────────────┐\n",
              "│ date       ┆ portfolio_group ┆ portfolio_id     ┆ input_asset_id ┆ input_asset_id_t ┆ value      │\n",
              "│ ---        ┆ ---             ┆ ---              ┆ ---            ┆ ype              ┆ ---        │\n",
              "│ date       ┆ str             ┆ str              ┆ str            ┆ ---              ┆ f32        │\n",
              "│            ┆                 ┆                  ┆                ┆ str              ┆            │\n",
              "╞════════════╪═════════════════╪══════════════════╪════════════════╪══════════════════╪════════════╡\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ Test-Portfolio   ┆ 02079K305      ┆ cusip9           ┆ 100.0      │\n",
              "│ 2025-01-01 ┆ demo-portfolios ┆ Test-Portfolio-2 ┆ 67066G10       ┆ cusip8           ┆ 100.0      │\n",
              "│ 2025-01-02 ┆ demo-portfolios ┆ Test-Portfolio   ┆ 02079K305      ┆ cusip9           ┆ 100.068649 │\n",
              "│ 2025-01-02 ┆ demo-portfolios ┆ Test-Portfolio-2 ┆ 67066G10       ┆ cusip8           ┆ 102.993538 │\n",
              "│ 2025-01-03 ┆ demo-portfolios ┆ Test-Portfolio   ┆ 02079K305      ┆ cusip9           ┆ 101.315361 │\n",
              "│ …          ┆ …               ┆ …                ┆ …              ┆ …                ┆ …          │\n",
              "│ 2025-08-23 ┆ demo-portfolios ┆ Test-Portfolio-2 ┆ 67066G10       ┆ cusip8           ┆ 185.327362 │\n",
              "│ 2025-08-24 ┆ demo-portfolios ┆ Test-Portfolio   ┆ 02079K305      ┆ cusip9           ┆ 111.382881 │\n",
              "│ 2025-08-24 ┆ demo-portfolios ┆ Test-Portfolio-2 ┆ 67066G10       ┆ cusip8           ┆ 185.327362 │\n",
              "│ 2025-08-25 ┆ demo-portfolios ┆ Test-Portfolio   ┆ 02079K305      ┆ cusip9           ┆ 112.680031 │\n",
              "│ 2025-08-25 ┆ demo-portfolios ┆ Test-Portfolio-2 ┆ 67066G10       ┆ cusip8           ┆ 187.222397 │\n",
              "└────────────┴─────────────────┴──────────────────┴────────────────┴──────────────────┴────────────┘"
            ]
          },
          "execution_count": 30,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api.get_portfolio(names=['Test-Portfolio', \"Test-Portfolio-2\"])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "### Saving the Schema\n",
        "\n",
        "We can also save a portfolio schema for later use. \n",
        "\n",
        "Below we demonstrate how to save the schema we previosly created and then use downstream."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 31,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "1"
            ]
          },
          "execution_count": 31,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_loader.organizer_settings.save(\"my-schema\", schema)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "metadata": {},
      "outputs": [
        {
          "data": {
            "text/plain": [
              "['Test-Portfolio', 'Test-Portfolio-2']"
            ]
          },
          "execution_count": 32,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "portfolios_api = portfolios_loader.load(\n",
        "    PortfolioSettings(portfolio_schema=\"my-schema\")\n",
        ")\n",
        "\n",
        "portfolios_api.get_portfolio_names()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## Housekeeping\n",
        "\n",
        "Lastly, we clean up by deleting our portfolio datasets."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 33,
      "metadata": {},
      "outputs": [],
      "source": [
        "portfolios_loader.organizer_settings.delete(\"my-schema\")\n",
        "uploader.get_dataset(\"demo-portfolios\").destroy()\n",
        "uploader.get_dataset(\"what-if\").destroy()"
      ]
    }
  ],
  "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": 2
}