AI & AutomationAI-generated

Mijn aandelenportefeuille gecoacht door AI: hoe ik een multi-agent systeem bouwde met Claude Code

Ik beleg al een aantal jaren, en sinds oktober 2025 specifiek in Amerikaanse hoog-dividend aandelen. Preferred stocks, BDC's, baby bonds — posities waarbij je elke dag even wil checken: dividendwijzigingen? Naderende call-dates? Posities die een spelregel triggeren? Dat bijhouden kost tijd. Dus bouwde ik een dagelijkse coaching sessie in Claude Code.

Het groeide uit tot drie onderling verbonden skills, met een vierde rol die ik later weer heb opgegeten in de hoofdskill. Dit is hoe het technisch werkt.

Drie skills, één ecosysteem

/portfolio-briefing  — dagelijks, centrale sessie
/standby-review      — wekelijks, kandidatenlijst bijwerken
/scan-clipping       — na elke community-post, signalen extraheren

Ze hangen zo samen:

/portfolio-briefing
  ├── absorbeert /standby-review als die >7 dagen oud is
  ├── draait een ingebouwde macro-analyse-agent voor Fed/recessie/sector-context
  └── leest signaalmatrix die /scan-clipping produceert

De dc-signalen.md is de lijm: een tabel met trade-signalen uit community-posts die door de briefing en de standby-review wordt opgepikt. Als die tabel verouderd raakt, merkt de briefing dat en waarschuwt.

Een eerdere versie had macro-analyse als losse skill (/bravos-briefing). In de laatste release heb ik die geconsolideerd in /portfolio-briefing als een interne agent-stap. Reden: ik draaide hem toch altijd in dezelfde flow, en een aparte slash-command was overhead zonder waarde. Minder skills, dezelfde functionaliteit.

Het juiste model per taak

De /portfolio-briefing skill heeft vijftien stappen. Elke stap draait op het goedkoopste model dat de taak aankan. In de praktijk scheelt dat 38–62% aan tokenkosten t.o.v. alles op Sonnet draaien.

De logica is simpel: mechanische taken naar Haiku, redeneren naar Sonnet, beslissingen met financieel gevolg naar Opus.

| Stap | Model | Waarom | |------|-------|--------| | Context laden + datum | Haiku agent | Shell-call + bestanden lezen | | Portfolio ophalen + parsen | Haiku agent | API-call + XML, deterministisch | | Nieuws (EDGAR + RSS) | Haiku agents parallel | Mechanische HTTP-batch | | Analyst ratings | Sonnet agent | Tekst classificeren met nuance | | YouTube transcript-analyse | Sonnet agent | Domeinkennis vereist | | Live koersen | Hoofdsessie direct | TradingView MCP werkt alleen hier | | Spelregel-toets per positie | Opus | Financieel risico, multi-type routing | | Volledige briefing + coaching | Opus | Holistisch oordeel + prioritering | | Sessie-log schrijven | Haiku agent | Deterministisch markdown-append |

Agents worden gespawnd via:

Agent(subagent_type="claude", model="haiku", description="...", prompt="...")

Één technisch detail dat me tijd heeft gekost: de TradingView MCP tool werkt alleen in de hoofdsessie, niet vanuit agent-spawns. Live koersen ophalen via een agent faalt stilletjes. Stap 4 draait dus altijd direct.

Cache: data en analyse gescheiden

De briefing heeft twee modi:

/portfolio-briefing --background haalt alle externe data op — IBKR portfolio, nieuws, koersen, YouTube transcripts — en schrijft die naar een dagelijkse cache. Geen analyse, geen Opus, geen output.

/portfolio-briefing leest die cache en doet de analyse. Als er geen cache is, haalt hij alles inline op.

De cache heeft vier leeftijdsbuckets:

| Leeftijd | Wat er gebeurt | |----------|---------------| | Niet gevonden | Alles opnieuw ophalen | | > 1 dag | Cache negeren, inline modus | | 30 min – 1 dag | Cache gebruiken, maar koersen opnieuw ophalen | | < 30 min | Volledig uit cache, data-stappen overslaan |

Het idee: --background 's ochtends draaien, zodat de eigenlijke briefing snel start als de beurs opengaat. Data ophalen is duur en langzaam. Analyse is goedkoop als de data er al is.

Data-bronnen

IBKR Flex API — portfolio-posities, cash en trades via een XML web service. Flow: stuur request → wacht 10 seconden → haal rapport op met referentiecode. Beperking: de Flex is een dagelijkse snapshot. Trades van dezelfde dag ontbreken bij een tweede run.

TradingView MCP — live koersen voor alle posities en kandidaten. Alleen in de hoofdsessie beschikbaar.

EDGAR 8-K + Seeking Alpha RSS — materiële events per ticker: dividendwijzigingen, earnings, credit events. Loopt als Python-batch in een Haiku agent.

YouTube via yt-dlp — transcripts van community-videos voor trade-signalen, en macro-analyse voor Fed/recessie/sector-context. Yt-dlp hangt als je het via de context-mode sandbox draait — altijd Bash gebruiken.

Context-bestanden — Markdown-bestanden met spelregels, kandidatenlijst, alerts en eerdere briefing-logs. Een Haiku agent leest die in stap 0.

Spelregel-routing per instrument-type

Niet elke positie verdient dezelfde check. De XML-parser classificeert elk instrument als STOCK, PREF (preferred share) of BOND:

if assetCategory == "BOND" or "NOTE" in description:
    type = "BOND"
elif "PREFERRED" or "PFD" or "PRD" in description:
    type = "PREF"
else:
    type = "STOCK"

Dat type bepaalt welke checks van toepassing zijn:

| Type | Instap-check | +10% exit | Payout-monitoring | Recessie-exit | |------|-------------|-----------|-------------------|---------------| | STOCK | ✅ | ✅ | ✅ | ✅ | | PREF | ✅ | — | ✅ (common dividend) | — | | BOND | — | — | ✅ (emittent-credit) | — |

De spelregels zelf staan in een apart Markdown-bestand. Bij conflict met de skill-instructies wint dat bestand altijd.

De skill verbetert zichzelf

Elke skill heeft een 2-laagse feedback-loop die na elke run draait.

Laag 1 kijkt naar de output: was de briefing volledig? Waren coaching-vragen scherp? Waren acties concreet genoeg — limietprijzen, aantallen?

Laag 2 kijkt naar de skill-instructies zelf: waren er stappen onduidelijk? Zijn er edge cases die nog niet worden afgedekt?

Elke voorgestelde wijziging aan een skill-bestand vereist expliciete goedkeuring voordat er iets wordt geschreven. De skill toont het voorstel en wacht.

Dingen die mis gingen

IBKR Flex stale data. Bij een tweede run op dezelfde dag ontbreken ochtend-trades. Oplossing: als ik zelf meld dat een order gevuld is, wordt dat direct geaccepteerd en in het open-orders-bestand geschreven. De Flex bevestigt dat later wel.

Open orders. IBKR Flex levert geen working orders — het is post-trade only. Een apart Markdown-bestand is de enige bron voor open orders. Briefing-logs worden nooit als orderstatus-bron gebruikt; die beschrijven intenties, geen feiten.

TradingView in agents. Elke keer dat ik probeerde koersen via een agent-spawn op te halen, faalde het stilletjes. De MCP-tool is sessie-gebonden. Dat kostte me een paar sessies om te begrijpen.

yt-dlp in de sandbox. Zware processen hangen als je ze via de context-mode sandbox draait. Altijd Bash gebruiken voor yt-dlp.

Tot slot

Het systeem is over een paar weken organisch gegroeid. Elke run leert iets nieuws: een edge case die nog niet was afgedekt, een coaching-vraag die scherper kon, een stap die goedkoper kon met Haiku. De feedback-loop vangt dat op.

De splitsing van data-fetch (--background) en analyse (normale run) was de grootste verbetering. Twee aparte stappen, twee aparte kosten-profielen. Klinkt voor de hand liggend achteraf.


Dit ecosysteem draait op Claude Code met de Anthropic Agent SDK. De skills zijn Markdown-bestanden in ~/.claude/commands/ — elk bestand is de volledige instructieset voor één slash-command.