{ "cells": [ { "cell_type": "code", "execution_count": 1, "id": "GQ18Kd5F3uKe", "metadata": { "id": "GQ18Kd5F3uKe" }, "outputs": [], "source": [ "!pip install -q requests openseries" ] }, { "cell_type": "code", "execution_count": 2, "id": "1", "metadata": { "id": "1" }, "outputs": [], "source": [ "from IPython.display import HTML, display\n", "from requests import get as requests_get\n", "from os import environ as os_environ\n", "import plotly.io as pio\n", "from sys import modules as sys_modules\n", "\n", "from openseries import (\n", " OpenTimeSeries,\n", " OpenFrame,\n", " ReturnSimulation,\n", " report_html,\n", " ValueType,\n", " efficient_frontier,\n", " prepare_plot_data,\n", " sharpeplot,\n", " load_plotly_dict,\n", " get_previous_business_day_before_today,\n", ")\n", "\n", "figdict, _ = load_plotly_dict()\n", "seed = 55" ] }, { "cell_type": "code", "execution_count": 3, "id": "94d23409-1d85-47fe-bf32-772117fbb9f2", "metadata": {}, "outputs": [], "source": [ "if \"google.colab\" in sys_modules:\n", " pio.renderers.default = \"colab\"\n", "elif \"ipykernel\" in sys_modules and \"VSCODE_PID\" in os_environ:\n", " pio.renderers.default = \"vscode\"\n", "else:\n", " pio.renderers.default = \"notebook_connected\"" ] }, { "cell_type": "code", "execution_count": 4, "id": "2", "metadata": { "id": "2" }, "outputs": [], "source": [ "def make_fund_basket(positions: dict[str, float], timeout: int = 10) -> OpenFrame:\n", " response = requests_get(url=\"https://api.captor.se/public/api/nav\", timeout=timeout)\n", " response.raise_for_status()\n", "\n", " found, weights, series = set(), [], []\n", " result = response.json()\n", " for data in result:\n", " if data[\"isin\"] in positions:\n", " found.add(data[\"isin\"])\n", " weights.append(positions[data[\"isin\"]])\n", " series.append(\n", " OpenTimeSeries.from_arrays(\n", " name=data[\"longName\"],\n", " isin=data[\"isin\"],\n", " baseccy=data[\"currency\"],\n", " dates=data[\"dates\"],\n", " values=data[\"navPerUnit\"],\n", " valuetype=ValueType.PRICE,\n", " )\n", " )\n", "\n", " if len(set(positions.keys()) - found) != 0:\n", " raise ValueError(f\"Request for NAV series failed. Missing ISINs are: {set(positions.keys()) - found}\")\n", "\n", " return OpenFrame(constituents=series, weights=weights)" ] }, { "cell_type": "code", "execution_count": 5, "id": "3", "metadata": { "id": "3" }, "outputs": [], "source": [ "funds = {\n", " \"SE0015243886\": 0.2,\n", " \"SE0011337195\": 0.2,\n", " \"SE0011670843\": 0.2,\n", " \"SE0017832280\": 0.2,\n", " \"SE0017832330\": 0.2,\n", "}\n", "basket = make_fund_basket(positions=funds)\n", "basket = basket.value_nan_handle().trunc_frame().to_cumret()" ] }, { "cell_type": "code", "execution_count": 6, "id": "4", "metadata": { "id": "4" }, "outputs": [], "source": [ "portfolio = OpenTimeSeries.from_df(dframe=basket.make_portfolio(name=\"Portfolio\"))\n", "basket = basket.add_timeseries(new_series=portfolio)" ] }, { "cell_type": "code", "execution_count": 7, "id": "5", "metadata": { "id": "5" }, "outputs": [], "source": [ "figure, _ = basket.plot_series(tick_fmt=\".1%\", auto_open=False, output_type=\"div\", add_logo=False)\n", "figure = figure.update_layout(\n", " height=600,\n", " font_size=10,\n", " legend=dict(\n", " yanchor=\"bottom\",\n", " y=-0.3,\n", " xanchor=\"right\",\n", " x=0.98,\n", " orientation=\"h\"\n", " )\n", ")\n", "figure = figure.update_layout(font_size=14, width=1100, height=600)" ] }, { "cell_type": "code", "execution_count": 8, "id": "6", "metadata": { "id": "6", "outputId": "f32e4d12-d9b0-453b-bef9-712dcd98eda6" }, "outputs": [ { "data": { "text/html": [ " \n", " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
| \n", " | Captor Aster Global Credit Short-Term | \n", "Captor Aster Global High Yield | \n", "Captor Aster Global Credit | \n", "Captor Scilla Global Equity | \n", "Captor Dahlia Green Bond | \n", "Portfolio | \n", "
|---|---|---|---|---|---|---|
| Arithmetic return | \n", "5.08% | \n", "11.08% | \n", "5.61% | \n", "9.74% | \n", "4.39% | \n", "7.18% | \n", "
| Volatility | \n", "1.52% | \n", "6.22% | \n", "7.71% | \n", "9.93% | \n", "2.69% | \n", "3.98% | \n", "
| Return vol ratio | \n", "3.34 | \n", "1.78 | \n", "0.73 | \n", "0.98 | \n", "1.63 | \n", "1.80 | \n", "
| Sortino ratio | \n", "5.11 | \n", "2.70 | \n", "1.08 | \n", "1.37 | \n", "2.61 | \n", "2.65 | \n", "
| Worst month | \n", "-0.25% | \n", "-2.70% | \n", "-5.49% | \n", "-7.55% | \n", "-2.20% | \n", "-2.91% | \n", "
| CVaR 95.0% | \n", "-0.23% | \n", "-0.90% | \n", "-1.04% | \n", "-1.51% | \n", "-0.36% | \n", "-0.59% | \n", "
| first indices | \n", "2022-12-06 | \n", "2022-12-06 | \n", "2022-12-06 | \n", "2022-12-06 | \n", "2022-12-06 | \n", "2022-12-06 | \n", "
| last indices | \n", "2026-01-02 | \n", "2026-01-02 | \n", "2026-01-02 | \n", "2026-01-02 | \n", "2026-01-02 | \n", "2026-01-02 | \n", "