Inspiration
I invest the way most individual investors do - based on intuition and belief in companies I follow. But the tools for pressure-testing a pick are either overwhelming (Bloomberg, premium platforms), shallow (most free tools), or one-sided (a single buy/sell signal with no reasoning). I wanted something calm and opinionated that actually argues with itself: here's the case for buying, here's the case for holding, here's the case for selling - now make your own call.
What it does
You type a ticker. TickerLens streams back:
- A company header with essential context (price, market cap, P/E, 52-week range, dividend yield) - enough to orient, not enough to overwhelm.
- Three perspective cards - Buy, Hold, and Sell - each a reasoned argument grounded in real fundamentals and current news. Each card tags its evidence as strong, moderate, or thin, and expands to reveal full reasoning and linked sources.
- The most interesting stuff shows up as implicit connections: not "Apple reported earnings," but "new EU digital-payments regulation threatens Services margin just as hardware cost pressure is rising - a dual squeeze on Apple's two margin pillars."
How I built it
The architecture is a small multi-agent system orchestrated with LangGraph:
- A validate node confirms the ticker exists (via yfinance) before any LLM spend happens.
- A fundamentals agent (Claude Sonnet 4.6) pulls yfinance data, builds the header metrics, and writes an editorial posture summary. The header is emitted to the UI mid-stream via LangGraph's custom stream channel — it arrives while the news agent is still working, so the page never feels empty.
- A news agent (Sonnet 4.6 with Anthropic's web_search tool) pulls company headlines from yfinance and expands context via live search. Its job is strictly evidence-gathering — direct news, macro context, and the implicit-connection list.
- A synthesis agent (Claude Opus 4.6) reads both dossiers and produces all three arguments in a single call, using a forced emit_briefing tool so the output is structured and type-safe. One call, not three parallel calls - because the cases need to disagree with each other coherently, and that only happens when the same model writes all three.
- Streaming uses Server-Sent Events over FastAPI, with a pacing wrapper that enforces a minimum gap between progress messages so the UI feels considered rather than machine-gun.
The frontend is Next.js with Tailwind. Editorial typography (Source Serif 4), warm off-white palette, muted teal accent, no dark mode. The "no hard cuts" rule drove a lot of the feel: cross-fading progress messages, the header fading in mid-stream to replace the loading state, cards fading in as progress fades out, even the error state fading smoothly back to landing.
Challenges I ran into
- Early emit in LangGraph. The initial design shipped the header event via plain updates-mode state diffs, which meant the header arrived after the fundamentals summary finished — defeating the whole point. Caught during verification; switched to LangGraph's custom stream channel (get_stream_writer() + multi-mode streaming), which delivers the header mid-node, before the Sonnet summary even starts.
- Web search latency. The original spec budgeted 30 seconds for the news agent; real web_search + Sonnet reasoning on a rich ticker runs 60-90s cold. Bumped the timeout, added per-iteration logging so slow runs are debuggable instead of mysterious, and built a yfinance-only fallback for when search genuinely fails.
- Confidence calibration. Opus tends to settle at "moderate" even when evidence is clearly strong. Prompting and schema work helped, but it's a real reminder that structured outputs aren't magic — the model still has to be coached to use the full range.
Accomplishments that I am proud of
- Built an agentic workflow that surfaces the kind of stock insight you normally only get from paid research — implicit connections across fundamentals, news, and macro context, not just restated headlines.
- Designed a clean application architecture with a clear separation of concerns on the backend — dedicated agents for validation, fundamentals, news, and synthesis, orchestrated through LangGraph — paired with a smooth, calm UX where every state transition is considered.
What I learned
Mostly about agent orchestration: how to shape a graph so nodes have clear responsibilities, how to separate evidence-gathering from reasoning (news vs. synthesis), how to force structured output with tool calls, how to handle partial failures without killing a run. Also: streaming is where UX lives in agent apps - most of the polish work was about giving the user something to watch while the graph runs.
What's next for TickerLens
Portfolio-level analysis (one ticker is great; a watchlist view with the same three-perspective framing would be more useful). Sector comparisons. A "follow-up questions" mode that lets you drill into a specific argument. And calibration work on the confidence tags.
Built With
- anthropic
- claude-opus
- fastapi
- langgraph
- next.js
- pnpm
- python
- react
- server-sent-events
- tailwind
- typescript
- uv
- yfinance
Log in or sign up for Devpost to join the conversation.