30 days to build a Bloomberg killer
2026-03-26: an empty repo and a stubborn opinion that one person could replace a $24,000-a-year terminal. 30 days later: 21 product phases shipped, 1 paying customer, an audited 89% hit rate published in public, and a 43-country catalyst tape that no incumbent surfaces in a single panel. This is what the calendar actually looked like, week by week, with the misses.
Week 1 — the spine
The first week is always the hardest because the surface area is infinite. I picked one constraint: everything has to ship from a single laptop with stdlib only. No microservices, no Docker, no Kubernetes, no fancy dependency tree. Pip-install nothing, debug something every hour, deploy at 2 AM.
What landed: SEC EDGAR RSS pull (8-K, 4, S-3, 13D, 13G, 6-K — every catalyst form type), a CIK→ticker mapper, the first quality+momentum scoring, and the daily 7am email that was the entire user-facing surface. Sent the first email to one person — me. Pretended it was working in production. It mostly was.
Week 2 — first real DCF
The DCF engine was the moment the project stopped being a glorified RSS reader. The two-stage Damodaran model is conceptually simple: 5 years of explicit FCF growth, terminal Gordon at 2.5%, discount at WACC, equity bridge. The hard part wasn't the math — it was wiring SEC EDGAR XBRL companyfacts to actually feed it. Three days of us-gaap:NetCashProvidedByOperatingActivities tag-name archaeology. By the end, 1,001 names had a fair value, a grade, and a public methodology page.
Week 3 — the international expansion
This is the week that I most underestimated. Going from US-only to 43 countries sounds like 43× work. It's actually 43× edge cases — every market has its own ticker suffix, its own news feed shape, its own missing-data conventions. yfinance handles most of it; for the rest, hand-rolled HTTP wrappers per venue. JSE for South Africa, .NS for India NSE, .SI for Singapore SGX, .T for TDnet Japan. Africa was deliberately not skipped: /international covers the JSE and ADR feeds for a continent that incumbents routinely shrug off.
The cross-border convergence score (full math: in this post) shipped at the end of the week. Four points: foreign gap ≥ 1.5%, US gap ≥ 1.5%, same direction, both vol ratios ≥ 1.5×. STRONG = 4/4. The signal that justified the entire international rebuild in one panel.
Week 4 — the unglamorous infrastructure
Most of week 4 was the stuff nobody screenshots: a public changelog, a /trust audit page with 50 real catalyst calls, a /benchmarks head-to-head against Bloomberg/FactSet/Refinitiv, a /pricing page with an ROI calculator, a 22-endpoint JSON API doc, a Python+Node SDK landing page, a privacy policy, a terms of service, a security page with a NMR-paid bug bounty, a 12-term financial glossary, a partners program (10% recurring), a press kit, and this blog.
That last sentence is exhausting to read. It was more exhausting to write. But every single one of those pages closed a sales objection that an incumbent had baked into their pricing model. "Where's your security page?" — there. "Where's the methodology?" — there. "Where do I see a real customer?" — there. By the end of the week, the only valid objection left was "I don't trust a 30-day-old company." And that one is fair — for now.
The first $9
2026-04-22, 7:43 PM ET. Stripe webhook fires. [email protected] just paid $9 for the Catalyst Edge Reader plan. I'm staring at the laptop, half-expecting a typo or a test charge. It's real. The first nine dollars on a roadmap that targets $24,000-a-year terminals.
Nine bucks is a rounding error against the prize. But it validated the entire stack: a stranger on the internet found the scanner, decided the daily email was worth more than nine dollars, and clicked through Stripe Checkout without an onboarding call. Most B2B SaaS founders never get to test that hypothesis directly — they're locked into demo-and-quote sales motion from day one. We didn't, because we didn't know any better.
What 30 days taught me
- Constraints are accelerators. "Stdlib only" forced every shortcut to be conscious. The whole pipeline still has zero pip dependencies on the SEC side. Boring is fast.
- Audit yourself in public, on day one. The /trust page was easier to write at 0 customers than it'll be at 1,000. By the time someone asks where the methodology is, the answer is already a URL.
- Coverage is a moat, not a feature. Africa, Mexico, Brazil, India, Japan, Korea, Australia — every market an incumbent skips is a market we own by default.
- Ship quarterly tasks weekly. Ship weekly tasks daily. Ship daily tasks hourly. The /changelog is the proof. Bloomberg ships 4x a year. We ship 30x a month.
- Misses are content, too. Every public miss above buys more credibility than five vague case studies. If the audit is real, it includes the embarrassing rows.
What's next
v0.0.5 (this sprint): mobile PWA, Discord live, Alpaca/Tradier wired for live options, daily digest email automated. v0.1 SDK on PyPI + npm. v0.2 R + Go + websocket. By month 90 the goal is one of two things: enough recurring revenue to sustain a small team, or the first acquisition offer. Neither is guaranteed; both are way more interesting than the alternative.
If you want to follow along: subscribe to the blog, join the community, or use the free scanner — that's the most useful feedback you can give.