InvestHub
A practice space for learning how the stock market works. Look up companies, compare them side by side, build a portfolio with pretend money, and ask an AI to explain what you're looking at.
One export commit
InvestHub went public as a single cleaned-up commit, so GitHub only shows the publish date.
-
Jun 14, 2026Published
Firebase session login, stock search and detail pages, side-by-side comparison, the practice portfolio, an options pricing helper, optional AI explanations, and a bundled list of companies to browse.
A practice sandbox for learning the market
Search any ticker for its quote, company profile, and price history, or browse a bundled list of 903 companies by sector.
Put companies next to each other on valuation (trailing and forward P/E), risk (beta), dividend yield, sector, and market cap.
Build a portfolio of simulated holdings and review your strategy. A helper looks up option mark prices from Yahoo's options chains.
With a Cohere key configured, you can ask for a plain-English explanation of a stock, a comparison, or your portfolio. Without one, everything else still works and the AI buttons tell you it isn't set up.
One Flask app, data fetched on demand
Flask serves both the pages and the JSON endpoints behind them. Firebase handles identity through session cookies, and market data comes from Yahoo Finance when you ask for it. A batch endpoint fetches several tickers at once and computes the day's change and percent change from the previous close, so a page showing several stocks loads them in one request.
Logos needed their own fallback logic. No single free source has every company, so the app builds an ordered list of candidates from the company's website and ticker and lets the browser fall through them until one loads.
def make_logos(ticker, site=""): t = (ticker or "").upper() dom = get_dom(site) urls = [] if dom: urls.append(f"https://logo.clearbit.com/{dom}") urls.append(f"https://storage.googleapis.com/iex/api/logos/{t}.png") if dom: urls.append(f"https://api.faviconkit.com/{dom}/128") urls.append(f"https://www.google.com/s2/favicons?domain={dom}&sz=128") urls.append(f"https://www.google.com/s2/favicons?domain={t}.com&sz=128") return list(dict.fromkeys(urls)) # dedupe, keep order
Condensed from app.py; the original dedupes with an explicit loop.
Making the portfolio real
- A proper transaction model with saved buys, sells, shorts, and options positions.
- Unit tests around quote normalization and portfolio math.
- Cached quote refreshes, so the app makes fewer calls to Yahoo.
- Deployment notes for a host like Render, Railway, or Fly.io.
Runs locally with a Firebase project; the Cohere key is optional.