Market Brief — analyst-grade equity metrics, in your pocket.
An app that surfaces the metrics serious investors actually care about — Sharpe ratio, max drawdown, P/E — backed by a Python service I built and deployed end-to-end.
The problem.
Most retail investing apps show you a price chart and a market cap. That's fine for casual users, but it leaves out the metrics that actually inform investment decisions — risk-adjusted return, drawdown history, valuation multiples. To get those, retail investors either pay for Bloomberg-tier tooling or stitch together spreadsheets manually.
I wanted to build something that closed that gap: a clean, fast iOS app where you type a ticker and immediately see the metrics you'd care about if you actually understood markets.
What it does.
Type any ticker. Within a couple of seconds you get the live price, market cap, and P/E ratio you'd expect — alongside the metrics most consumer apps skip:
- Sharpe ratio — risk-adjusted return, calculated against the risk-free rate
- Maximum drawdown — the worst peak-to-trough fall over the lookback window
- Volatility measures — annualised standard deviation of returns
- Annualised return — compound growth over the lookback window, so tickers are comparable
Everything renders in a layout designed to be readable on a phone, not a Bloomberg terminal.
How it's built.
iOS client (Swift)
The mobile app is built natively in Swift. It handles the UI, request orchestration, input validation and connectivity checks, plus a client-side rate limiter so a fast tapper can't hammer the backend. Native rather than cross-platform was a deliberate choice — financial UIs benefit from feeling fast and tight, and Swift gives me direct control over animations, scroll behaviour, and gesture handling.
Backend (FastAPI on Fly.io)
The backend is a FastAPI service in Python, shipped as a Docker image to Fly.io and redeployed by GitHub Actions on every push to main. When the iOS client requests a ticker, the backend pulls the underlying data from yfinance, computes the derived metrics server-side, and returns a single structured response. Doing the maths on the backend means the iOS app stays simple — it renders, it doesn't compute.
Handling failure
Live market data calls are not free, and Yahoo's endpoint is flaky under load. Rather than pretend otherwise, the app treats failure as a first-class state:
- Every failure maps to a typed error with a plain-English message — invalid ticker, offline, unknown symbol, rate limited, server error, or a response that wouldn't decode
- A sliding-window rate limiter on the client (ten requests a minute) stops repeated taps from hammering the backend
- Connectivity is monitored, so the request button disables offline and comes back when the connection does
"The interesting work wasn't writing Swift. It was deciding what computation belonged on the client, what belonged on the server, and how the app should behave when the data source lets it down."
What I'd do differently.
If I were starting over today, three things would change:
- Move off
yfinance. It's free and easy but rate-limited and unofficial. A proper paid data source (IEX Cloud, Polygon) would be more reliable and let me offer intraday granularity. - Add a proper test suite. The metric calculations are pure functions — they're crying out to be tested with property-based tests. I'd reach for
pytest+hypothesisnext time. - Add a caching layer. Every request goes straight to Yahoo. A short-TTL cache in front of it would cut latency on repeat queries and take the pressure off an upstream that rate-limits under load.
What it taught me.
This project is the most concrete example I have of owning something end-to-end — UI, backend, deployment, App Store submission, post-launch updates. I'd built things before in coursework. This was the first time I'd shipped a product to a public store and watched it go through review. The non-engineering parts (App Store guidelines, signing certificates, screenshots, metadata) turned out to be a substantial chunk of the work — and a part of "shipping software" that university courses simply don't cover.