portfolio-snapshot
Export/publish the live portfolio tracker as a static, stripped snapshot into the "Portfolio Snapshot" folder — an empty Trades section (first), the holdings table, and the 1-month-return bar chart ba
SKILL.md.claude/skills/portfolio-snapshot/SKILL.md
GitHubExport the live portfolio tracker (Live Portfolio.md) as a static, publishable snapshot in the Portfolio Snapshot/ folder. The snapshot keeps only the deliverable content; every instruction/engine/log element is stripped.
This is a mechanical/export skill — NOT investment analysis. It produces no conviction or status judgement, so it is in the same load tier as /numbers, /graph, /clean: do NOT read the /Mental Models folder.
Engine: .claude/skills/portfolio-snapshot/build_snapshot.py (deterministic, pure stdlib). It parses the Holdings table, bakes the bar chart to SVG by porting the exact math in the tracker's dataviewjs block (90th-percentile cap; diverging-from-center bars sorted high→low), assembles the note, and writes the files directly. Following the /graph pattern, the large SVG never streams through a model response.
What the snapshot contains (the contract)
Section order is Trades first, then Holdings, then Charts.
| Kept | Dropped (instruction / engine / log) |
|---|---|
## Trades (empty, FIRST — for the user to fill in) |
[]() stub, > [!tip] How this works |
## Holdings table (verbatim, markers stripped) |
the FMP-refresh dataviewjs engine block |
## Charts → one static SVG embed: the 1-month-return bar (scatter opt-in) |
both chart > [!tip] callouts + their dataviewjs code |
Frontmatter: Publish_Snapshot: true + provenance |
## Upcoming Earnings, ## Column Legend, ## Notes, ## Log |
Publish_Snapshot: trueleads the frontmatter — a YAML boolean renders as a ticked ("filled") checkbox property in Obsidian. Also carriesdate,snapshot_of: "[[Live Portfolio]]",tags: [portfolio, snapshot],status: active.- Charts are baked from the CURRENT Holdings table — click Refresh in the live tracker first if you want fresh numbers.
- Default chart: the
Return 1Mbar only. The scatter is omitted by default; pass--scatterto also emit it (defaultsRev Gr CFYx vsEV/EBIT NTMy). Re-running without--scatterdeletes any stale scatter asset from an earlier run of the same snapshot. - SVGs are theme-independent (white card, baked hex colors — CSS variables would not resolve in a static export) and preserve
<title>hover tooltips.
Naming
- Default mode
dated: files are named by date in DD-MM-YYYY form —Portfolio Snapshot/04-08-2026.md, plus04-08-2026 - bar.svg(and- scatter.svgonly when--scatter). Re-running on the same day overwrites that day's files (idempotent per day); different days accumulate an archive. - Mode
single(--mode single): writesPortfolio Snapshot.md+Portfolio Snapshot - bar.svg, overwritten every run (no history).
Step 0: Pre-flight
Lock posture is read-only (per .claude/skills/_shared/preflight.md): this skill reads only Live Portfolio.md (no analytical skill writes it) and writes only into the isolated Portfolio Snapshot/ folder (no other skill touches it), so the contention surface is nil and no vault lock is taken. Still verify:
- Source exists —
Live Portfolio.mdat vault root. Abort if missing. - Table markers present (section-existence probe) —
<!--TABLE-START-->/<!--TABLE-END-->. The engine aborts loudly if absent; do not fabricate a table.
test -f "Live Portfolio.md" && grep -q "TABLE-START" "Live Portfolio.md" \
&& echo "PREFLIGHT_OK" || echo "PREFLIGHT_FAIL"
Step 1: Generate
Pass today's date explicitly so the filename tracks the vault clock (do not rely on the machine clock):
python3 ".claude/skills/portfolio-snapshot/build_snapshot.py" \
--date "$(date +%F)" --time "$(date +%H:%M)"
Default output is the Return 1M bar only. Optional overrides: --bar-metric "Return 3M" (any key in the script's BAR_METRICS: Returns 1W/1M/3M/1Y, P/E, EV/EBIT, Rev/EPS growth), --scatter to also emit the scatter (with --scatter-x / --scatter-y), --mode single.
Step 2: Verify & report
The script prints a summary (rows parsed, chart metric, output paths). Confirm holdings rows matches the live table and the files exist, then report to the user — link the note as a wikilink (e.g. [[Portfolio Snapshot/04-08-2026.md]]) and name each SVG asset. Per CLAUDE.md Rule #8, list every file written.
Safety
- Read-only on the source — never modifies
Live Portfolio.md(its refreshdataviewjsand Log stay intact). - Never creates content at vault root; all output lands in
Portfolio Snapshot/. - Archive, don't delete — old dated snapshots accumulate; removing them is the user's call (or a future
/clean-style sweep), never automatic here. (The one exception is a same-date stale- scatter.svgwhen scatter is toggled off — that orphan is removed so the folder stays consistent with the note.) - The
Publish_Snapshotflag is distinct from thepublish: truewebsite-sync flag used by Theses/Sectors/Macro — this skill does not touch that pipeline.