nghia dang · software engineer
← back to work

/ project

signal-tracker

Thesis-based change detection for an investment portfolio.

stack shared core · GitHub Actions cron · Turso · Resend · Vercel
scope solo build
status live, daily

ProblemMost investing tools tell you what happened. Very few tell you when something has changed relative to why you invested in the first place. I wanted to write down my actual theses for each holding and be alerted only when new information genuinely tests them.

What it doesI encode a thesis per position: the kind of claim that, if it broke, would change my mind. A daily job watches for new filings, transcripts, and signals, uses an LLM to judge whether anything materially moves a thesis, and sends a concise email digest. A remote trigger lets me kick off a run from my phone.

OutcomeIt converts a vague intention to "keep up with my positions" into a specific, low-noise feed of thesis-relevant change. It also shares its core infrastructure with stock-vetter, so the two compound.

/ architecture

Architecture

signal-tracker is a thesis-change detector that runs unattended on a daily schedule. It shares the packages/core infrastructure with stock-vetter — the same SEC-filing fetchers, transcript ingestion, and Turso persistence — and adds a thesis layer and a change-detection pass on top.

  [GitHub Actions cron — daily]
            │
            ▼
  [packages/core] ── fetch latest filings / transcripts ──► [Turso]
            │
            ▼
  [thesis engine] ── per-position thesis + new evidence ──► [LLM judge]
            │                                                    │
            │              materially moves a thesis? ───────────┘
            ▼
  [digest builder] ──► [Resend email] + [web viewer]
            ▲
  [remote trigger] (phone) ──► on-demand run

Each holding has a written thesis — a falsifiable claim that, if broken, would change the decision. The daily job diffs the latest primary-source material against each thesis and asks an LLM to classify whether anything materially confirms or challenges it, then emits a low-noise digest rather than a raw news feed.

/ technical decisions

Technical decisions

Shared core over a separate codebase

reusing stock-vetter's packages/core meant filing-fetch, parsing, and persistence were already battle-tested, so signal-tracker is mostly the thesis + diff logic. The two tools compound instead of duplicating.

Thesis as falsifiable text, not a rule engine

encoding a thesis as a plain-language claim the LLM evaluates (vs hardcoded numeric triggers) captures qualitative shifts — a changed risk factor, a softened guidance tone — that threshold rules miss.

Change-detection, not summarization

the job's job is to stay silent. It only surfaces material thesis movement, which is what makes a daily email survivable long-term.

Cron + remote trigger

GitHub Actions runs the daily pass for free and verifiably; a remote trigger lets me force a run from my phone when news breaks.

/ what broke

What broke / what I learned

The hard part wasn't detection, it was noise. Early versions flagged too much — every minor filing change read as "movement." Tightening the judge toward materiality (and giving it the thesis as explicit context) is what turned it from a firehose into something I actually read. Sharing infrastructure with stock-vetter also meant its data-plumbing bugs were my bugs; fixing them once fixed both.

The signal-tracker thesis dashboard listing watched positions, each a falsifiable thesis with a status badge (Watch / On track), tickers, and last-run date
The thesis dashboard: one falsifiable thesis per position, each with its latest status.
A thesis opened up, showing each new signal scored as strengthens or neutral with magnitude and confidence, the model's reasoning, and SEC filing / earnings-call citations
Inside a thesis: each new signal scored strengthens or neutral, with the model's reasoning and primary-source citations.
A reverse-DCF priced-in check showing a market-implied-growth sensitivity grid, plus a recent-activity log of signals the run considered and dismissed
The reverse-DCF priced-in check, and the audit trail of signals considered and dismissed.
← back to work