Case study · Personal project
Installous
A private web app for researching stocks: live market data, a five-factor score you can read, and an AI analyst that knows your portfolio and investor profile.
The problem
Researching a stock usually means moving between a quote page, a table of fundamentals, a chart, the news and other people's opinions, and none of them know what you already own or how much risk you want to take. Installous brings those into one place, scores every stock the same way, and lets you ask questions about it in plain English.
What it does
- Dashboard: portfolio value, today's change, total gain or loss, a watchlist with one-day sparklines, and the day's top-ranked stocks.
- Top Picks: ranks about 50 large-cap US stocks plus your watchlist by the Installous score, with prices that update live, sortable by any factor and filterable by sector.
- Stock pages: a Robinhood-style chart with a live intraday view (a dotted previous-close line, green or red for up or down, and a price that rolls digit by digit as you follow it with your cursor), a price that ticks every second while the market is open, ranges from one week to five years, the factor breakdown, key metrics, news, and a one-click AI investment thesis.
- AI Advisor: a chat with an analyst that calls live tools and gives buy, hold or avoid views tailored to your risk tolerance, time horizon and goals.
- Portfolio: positions with average cost, live value, gain or loss, and weight.
- AI Fund: a $100,000 paper-money portfolio that picks stocks by itself from the Installous score, started September 29, 2026. It shows its holdings, its track record against the S&P 500, a five-year backtest of its rules, and a trade log that gives the reason for every buy and sell.
- Options Lab: a live paper bot that trades one SPX (S&P 500 index) iron condor at a time, started October 12, 2026. Right after each close it settles the condor expiring that day, sets the next size from a level ladder (1, 3 or 6 contracts: a loss moves up a level, any win goes back to 1), and sells the next one, expiring the next trading day. The page shows the order as it's placed and the open condor marked live off the index: profit or loss, a payoff chart and each leg's estimated price, plus the full trade history.
- Compare: up to four stocks side by side, with performance from the same starting day and their scores and fundamentals in one table.
- Earnings & dividends: the next earnings date and estimates, the last four quarters' beats and misses, and yearly dividend history on every stock page.
- Alerts: a GitHub issue assigned to the owner (which GitHub emails) whenever the fund trades, plus a weekly digest, and a short phone notification for each condor trade or skipped day.
- Built like a phone app: it installs to the home screen and opens full screen with a bottom tab bar, a "More" sheet for the less-used pages, and a market clock in the header that shows whether the market is open and when it next opens or closes.
How it's built
Next.js with the App Router and TypeScript, styled with Tailwind CSS. The charts are plain SVG drawn by the app's own code rather than a chart library, which keeps each page to about 180 to 190 KB of compressed JavaScript; the AI chat and its markdown renderer only load when used. Server-side API routes (stock, history, sparklines, picks, news, search, portfolio, watchlist, profile and chat) sit between the browser and the data. Market data comes from Yahoo Finance through yahoo-finance2 and needs no API key; the advisor uses the Anthropic SDK and streams its answer back. Live prices come from Yahoo's free streaming feed: the browser opens one shared WebSocket, decodes its protobuf messages itself, subscribes only to the tickers on screen, and reconnects with backoff, so it works in the static demo too.
Your watchlist, holdings and profile are saved to a local JSON file in a git-ignored folder, so positions never get committed.
Key decisions
A score you can read
Every stock gets 0 to 100 on five factors: value (20%), quality (25%), growth (20%), momentum (20%) and analyst sentiment (15%). They blend into one number with a rating from Strong Buy (72 and up) to Avoid (below 33). When the factors that have data cover less than 45% of the weight, there's no overall score at all rather than a misleading one. The weights and thresholds live in one file, so they're easy to tune.
An advisor that looks things up
The advisor doesn't answer from memory. It has tools for stock analysis, price history, ticker search, your portfolio, the top picks, news and adding to your watchlist, plus web search (up to five searches per answer), and each tool's input is checked with a Zod schema before it runs. Its instructions treat the score as one input and ask it to explain where its judgment differs. The chat shows each tool call as it happens, so you can see what it looked at.
Caching by how fast data changes
A small in-memory cache sits in front of Yahoo Finance, with a lifetime per kind of data: quotes and intraday prices for 1 minute, fundamentals for 10, longer price history for 15, news for 30, and ticker search for 60. Page loads and the advisor's tool calls share it, so asking about a stock you're looking at doesn't fetch it all again.
An AI Fund that follows its own rules
The fund answers a simple question: would you beat the market by just buying what the score likes? So it runs on rules alone, with no human picks and no model making judgment calls. Every 7 days it holds the top 10 stocks at equal 10% weights. It keeps a stock while it stays in the top 15 and scores at least 45 (Hold), which stops it from trading on small changes in rank, and it only trims or tops up a position once it drifts more than 2 points from its target. Every fill pays a 0.05% simulated trading cost, so the results aren't flattered.
The fund's logic is a set of pure functions with no network or file access, so it's covered by an automated test suite that runs on every pull request. The tests step it through weeks of made-up data: a stock falls below Hold and gets sold, an overweight winner gets trimmed, a quiet week makes no trades, and cash never goes negative. A GitHub Action runs it every 30 minutes during market hours and saves its state (cash, positions, trade log and daily values) to a separate data branch. That makes the fund's whole history a public, auditable record, and it costs nothing to run: no broker account and no API keys.
It's benchmarked against the same $100,000 put into SPY, the S&P 500 fund, on the same day, because beating the index, not just making money, is the bar that matters.
A backtest that doesn't flatter itself
A backtest replays the fund's rules over the last five years so there's something to judge them by before the live record matures. Free data only has today's company fundamentals, and scoring 2021 with 2026's numbers would quietly use the future, so the backtest ranks stocks by momentum alone, the part of the score that can be rebuilt from past prices. Each day's decisions use only prices up to the day before, and a test checks this: it fails if the backtest is changed to peek at the same day's price.
The first result looked too good: about +274% against +80% for the S&P 500. So the page also shows a control, the same 50 stocks bought equally and held. That control returned about +152%, which means roughly half the gap came from the stock list itself (today's large caps, picked with hindsight), not from the rules. The rules still came out ahead overall but trailed buy-and-hold in 2023 and 2025, and the page says all of this next to the chart. (Figures from October 2026; the backtest re-runs with the live data.)
A condor bot that trades like a person would
An iron condor sells a call spread above the market and a put spread below it, and keeps the money it collected if the index finishes between them. The bot trades the S&P 500 index itself (SPX), whose options settle in cash at the 4pm close, with 5-point wings and short strikes placed so it collects about $2.50 a share: roughly +$250 on a win and -$250 on a full loss, per contract. Its sizing is a gentler martingale: three levels of 1, 3 and 6 contracts, where a loss moves up a level, any win goes back to the first, and a loss on the last level starts over instead of doubling into ruin. It skips a day when a Fed decision, a CPI report or a jobs report would land while the condor is open, or when the condor would pay under $1.50 a share.
The first version opened the next condor at 3:27pm and sized it from a guess at how the expiring one would finish. One afternoon the index closed 16 cents on the wrong side of a short strike, the guess was wrong, and the real result never corrected the ladder. Index options trade until 4:15pm, so now the bot settles first, at 4:05pm, and opens the next condor between 4:05 and 4:14 from the real result. It fills at real (delayed) Yahoo quotes, prices monthly-expiration Fridays only from the SPXW contracts that settle at the close (the standard monthly SPX contract settles on that morning's open), and trades only when both Yahoo and an NYSE holiday and half-day calendar agree the market is open. Tests replay its real schedule over weeks of made-up days, including duplicate runs, weekends, Thanksgiving and a half day, and check that it opens exactly one condor a day at exactly its level's size.
Keeping the scheduled jobs moving
The AI Fund runs in one scheduled GitHub Actions workflow. In October a Pages deploy sat waiting indefinitely, and because every run shared one queue, everything behind it was cancelled: the fund and the demo data stopped updating for six days. The workflow now gives the deploy its own queue, where a newer deploy replaces an older one, with a 15-minute timeout, while the step that updates the fund's state still runs strictly one at a time.
The condor bot has to be running at the close every trading day, and GitHub skipped every scheduled run on one of its first days. So it has its own workflow that runs around the clock: each run steps the bot at its times and, before GitHub's six-hour job limit, starts the next run itself, which GitHub doesn't skip the way it skips scheduled runs. The schedule is only a fallback that restarts the chain if a run is ever lost, and one shared queue makes sure exactly one run carries it on. Fixes along the way, from prices quoted in pence showing 100 times too high to tickers like BRK/B turning into a different company, each came with a test, for about 125 tests in all.
Useful without the AI
Everything except the advisor works without an Anthropic API key: the dashboard, picks, charts and portfolio run on market data alone.
Current limits
The full app is single-user and runs locally. The live demo is a static build of the same code: market data is a snapshot of about 50 large caps that a GitHub Action refreshes every 30 minutes while markets are open, your portfolio and watchlist stay in your browser, and the AI advisor runs with your own Anthropic API key. Top Picks ranks that fixed list plus your watchlist, not the whole market.
The AI Fund trades simulated money at the latest snapshot price, so real fills would differ a little. Its returns and the S&P 500's both leave out dividends, and a track record measured in weeks says little about whether the rules actually work. The backtest can't test the fundamental factors and still carries some hindsight from its stock list, so it shows how the rules behave rather than predicting returns.
The condor bot trades paper money at delayed quotes, filled at the mid price less a cent of slippage, so real fills would differ. Its record is days old, and a strategy that wins most days can still lose several in a row. It's a learning tool for a strategy, not a recommendation to trade it.