Skip to content

Commit 9f08ed4

Browse files
committed
docs: add tagging and retagging documentation to tutorial notebook
1 parent 8e00f2e commit 9f08ed4

1 file changed

Lines changed: 130 additions & 13 deletions

File tree

examples/tutorial/notebooks/09_report_and_llm_workflow.ipynb

Lines changed: 130 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,114 @@
7575
"cell_type": "markdown",
7676
"id": "3",
7777
"metadata": {},
78+
"source": [
79+
"## Step 1b — Tag Your Backtests\n",
80+
"\n",
81+
"Tags let you label and group strategies — for example by batch name, experiment,\n",
82+
"or configuration variant. Tags are **persisted** in a `tag.json` file inside\n",
83+
"each backtest directory, so they survive across subsequent loads.\n",
84+
"\n",
85+
"### How tags get assigned\n",
86+
"\n",
87+
"There are three ways a backtest gets a tag:\n",
88+
"\n",
89+
"**1. During the backtest run** — Set `tag` in the strategy metadata:\n",
90+
"```python\n",
91+
"strategy = TradingStrategy(\n",
92+
" algorithm_id=\"momentum_v3\",\n",
93+
" metadata={\"tag\": \"experiment_A\"},\n",
94+
" ...\n",
95+
")\n",
96+
"```\n",
97+
"The tag is automatically extracted and saved with the backtest.\n",
98+
"\n",
99+
"**2. After the fact with `retag_backtests()`** — Retag all backtests in a\n",
100+
"directory (or filter by strategy_id):\n",
101+
"```python\n",
102+
"from investing_algorithm_framework import retag_backtests\n",
103+
"\n",
104+
"# Tag everything in a directory\n",
105+
"retag_backtests(\"experiment_A\", directory_path=\"my_batch\")\n",
106+
"\n",
107+
"# Tag only a specific strategy\n",
108+
"retag_backtests(\"experiment_B\", directory_path=\"my_batch\", strategy_id=\"momentum_v3\")\n",
109+
"```\n",
110+
"\n",
111+
"**3. Multi-directory loading** — When you load from multiple directories,\n",
112+
"each directory name is used as the default tag (unless a persisted tag exists):\n",
113+
"```python\n",
114+
"report = BacktestReport.open(directory_path=[\"batch_A\", \"batch_B\"])\n",
115+
"# Strategies from batch_A get tag \"batch_A\", etc.\n",
116+
"```\n",
117+
"\n",
118+
"### What tags do in the dashboard\n",
119+
"\n",
120+
"- **Filter bar** — When 2+ tags exist, a chip-based filter bar appears at the top\n",
121+
"- **Tag badges** — Every strategy name shows its tag badge in all tables\n",
122+
"- **Collapsible sidebar groups** — Strategies are grouped by tag with collapsible headers\n",
123+
"- **MCP server** — The `list_strategies` and `get_strategy_details` tools include tag info"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": null,
129+
"id": "4",
130+
"metadata": {},
131+
"outputs": [],
132+
"source": [
133+
"from investing_algorithm_framework import retag_backtests\n",
134+
"\n",
135+
"# Retag all backtests in a directory\n",
136+
"count = retag_backtests(\"experiment_A\", directory_path=batch_dir)\n",
137+
"print(f\"Retagged {count} backtests with tag 'experiment_A'\")\n",
138+
"\n",
139+
"# Retag a single strategy by its algorithm_id\n",
140+
"count = retag_backtests(\n",
141+
" \"experiment_B\",\n",
142+
" directory_path=batch_dir,\n",
143+
" strategy_id=\"momentum_v3\"\n",
144+
")\n",
145+
"print(f\"Retagged {count} backtests with tag 'experiment_B'\")\n",
146+
"\n",
147+
"# Reload to see the tags\n",
148+
"report = BacktestReport.open(directory_path=batch_dir)\n",
149+
"for bt in report.backtests:\n",
150+
" print(f\" • {bt.algorithm_id}: tag={bt.tag}\")"
151+
]
152+
},
153+
{
154+
"cell_type": "markdown",
155+
"id": "5",
156+
"metadata": {},
157+
"source": [
158+
"### Multi-directory loading\n",
159+
"\n",
160+
"You can also load backtests from **multiple directories** at once by passing a list.\n",
161+
"Each directory name becomes the default tag for its strategies (unless they already\n",
162+
"have a persisted tag)."
163+
]
164+
},
165+
{
166+
"cell_type": "code",
167+
"execution_count": null,
168+
"id": "6",
169+
"metadata": {},
170+
"outputs": [],
171+
"source": [
172+
"# Load from multiple directories — each dir name becomes the tag\n",
173+
"report = BacktestReport.open(directory_path=[\"batch_A\", \"batch_B\"])\n",
174+
"\n",
175+
"for bt in report.backtests:\n",
176+
" print(f\" • {bt.algorithm_id}: tag={bt.tag}\")\n",
177+
"\n",
178+
"# Open the dashboard — strategies will be grouped by tag in the sidebar\n",
179+
"report.show()"
180+
]
181+
},
182+
{
183+
"cell_type": "markdown",
184+
"id": "7",
185+
"metadata": {},
78186
"source": [
79187
"## Step 2 — Open the Interactive Dashboard\n",
80188
"\n",
@@ -91,15 +199,15 @@
91199
{
92200
"cell_type": "code",
93201
"execution_count": null,
94-
"id": "4",
202+
"id": "8",
95203
"metadata": {},
96204
"outputs": [],
97205
"source": []
98206
},
99207
{
100208
"cell_type": "code",
101209
"execution_count": null,
102-
"id": "5",
210+
"id": "9",
103211
"metadata": {},
104212
"outputs": [],
105213
"source": [
@@ -109,7 +217,7 @@
109217
},
110218
{
111219
"cell_type": "markdown",
112-
"id": "6",
220+
"id": "10",
113221
"metadata": {},
114222
"source": [
115223
"## Step 3 — Start the MCP Server (Connect Your LLM)\n",
@@ -155,7 +263,7 @@
155263
},
156264
{
157265
"cell_type": "markdown",
158-
"id": "7",
266+
"id": "11",
159267
"metadata": {},
160268
"source": [
161269
"## Step 4 — The LLM Toolkit (23 MCP Tools)\n",
@@ -204,7 +312,7 @@
204312
},
205313
{
206314
"cell_type": "markdown",
207-
"id": "8",
315+
"id": "12",
208316
"metadata": {},
209317
"source": [
210318
"## Step 5 — Ask the LLM to Analyze Your Strategies\n",
@@ -265,7 +373,7 @@
265373
},
266374
{
267375
"cell_type": "markdown",
268-
"id": "9",
376+
"id": "13",
269377
"metadata": {},
270378
"source": [
271379
"## Step 6 — The Iterative Workflow\n",
@@ -320,7 +428,7 @@
320428
},
321429
{
322430
"cell_type": "markdown",
323-
"id": "10",
431+
"id": "14",
324432
"metadata": {},
325433
"source": [
326434
"## Step 7 — Notes as Self-Contained Analysis Documents\n",
@@ -360,7 +468,7 @@
360468
},
361469
{
362470
"cell_type": "markdown",
363-
"id": "11",
471+
"id": "15",
364472
"metadata": {},
365473
"source": [
366474
"## Step 8 — Example Conversation with the LLM\n",
@@ -419,7 +527,7 @@
419527
},
420528
{
421529
"cell_type": "markdown",
422-
"id": "12",
530+
"id": "16",
423531
"metadata": {},
424532
"source": [
425533
"## Step 9 — Apply Selections & Export\n",
@@ -456,7 +564,7 @@
456564
},
457565
{
458566
"cell_type": "markdown",
459-
"id": "13",
567+
"id": "17",
460568
"metadata": {},
461569
"source": [
462570
"## Step 10 — You Can Also Save / Reload Programmatically\n",
@@ -469,7 +577,7 @@
469577
{
470578
"cell_type": "code",
471579
"execution_count": null,
472-
"id": "14",
580+
"id": "18",
473581
"metadata": {},
474582
"outputs": [],
475583
"source": [
@@ -480,18 +588,26 @@
480588
},
481589
{
482590
"cell_type": "markdown",
483-
"id": "15",
591+
"id": "19",
484592
"metadata": {},
485593
"source": [
486594
"## TL;DR — The Complete Workflow\n",
487595
"\n",
488596
"```python\n",
489-
"from investing_algorithm_framework import BacktestReport, recalculate_backtests\n",
597+
"from investing_algorithm_framework import (\n",
598+
" BacktestReport, recalculate_backtests, retag_backtests\n",
599+
")\n",
490600
"\n",
491601
"# 1. Load all backtests\n",
492602
"report = BacktestReport.open(directory_path=\"my_batch\")\n",
493603
"recalculate_backtests(report.backtests)\n",
494604
"\n",
605+
"# 1b. (Optional) Tag your backtests\n",
606+
"retag_backtests(\"experiment_A\", directory_path=\"my_batch\")\n",
607+
"\n",
608+
"# 1c. (Optional) Load from multiple directories (auto-tagged by dir name)\n",
609+
"report = BacktestReport.open(directory_path=[\"batch_A\", \"batch_B\"])\n",
610+
"\n",
495611
"# 2. Open the dashboard\n",
496612
"report.show()\n",
497613
"```\n",
@@ -510,6 +626,7 @@
510626
"# 5. On the dashboard:\n",
511627
"- Read the LLM's notes\n",
512628
"- Click \"Apply Selection\" to filter\n",
629+
"- Use the tag filter bar to show/hide batches\n",
513630
"- Capture more snapshots\n",
514631
"- Export the final report\n",
515632
"```\n",

0 commit comments

Comments
 (0)