← Projects

PortfolioLens

How I built it

Web app · August 2026 · Live

I understood Monte Carlo simulation on paper. I wanted to find out if I could actually build it.

PortfolioLens takes a few real stocks and how much of your money is in each, then runs the numbers: how much it’s likely to return, how much it swings, the best possible trade-offs between the two, ten thousand possible futures, and how it would have done through 2008, 2020 and 2022.

The part I find most interesting is a simpler question. When one stock drops, which of the others go down with it?

Under King and Bay

Picture each stock as a tower in the Financial District, and the PATH underneath as how closely they move together. Two stocks only get a tunnel if they’re correlated above 0.35, and the stronger the link, the wider the tunnel. Drop one and the hit travels through the tunnels, weaker at every hop.

This is the sample portfolio from the app, running PortfolioLens’s own model in your browser. All five stocks are 20% each, so the towers are the same height.

Tap a tower to drop its stock, then swipe for the rest →

King St Wthe PATHAPLE–GOOGL: correlation 0.36MSFT–GOOGL: correlation 0.55MSFT–NVDA: correlation 0.56MSFT–META: correlation 0.51GOOGL–NVDA: correlation 0.49GOOGL–META: correlation 0.53NVDA–META: correlation 0.48APLE−1.7%MSFT−20.0%GOOGL−7.1%NVDA−7.3%META−6.6%
Whole portfolio−8.5%
A −20% shock to MSFT spreads most heavily to NVDA (correlation 0.56, est. −7.3%), GOOGL (correlation 0.55, est. −7.1%), META (correlation 0.51, est. −6.6%). Estimated total portfolio drawdown: −8.5%.

It’s a simple model on purpose: a shock spreads through the graph and fades by a fixed amount at each step. It won’t predict a real crash. It’s there to answer “what else in this portfolio should I be watching?”

Ten thousand futures in one pass

The Monte Carlo runs all 10,000 paths as one big array, with no loop over simulations. Instead of stepping through every one of the 2,520 trading days in ten years, it jumps between about 50 checkpoints, which the model allows exactly.

Two details make it honest. The random moves go through a Cholesky factor of the covariance matrix, so simulated stocks move together the way they really have, instead of each doing its own thing. And the drift gets an Itô correction, so the average path isn’t quietly more optimistic than the data.

The formulas were the easy part

Real market data is messy. Stocks start trading on different dates, and some days are missing. PortfolioLens only uses the days every holding actually traded, so a recent IPO shrinks the window instead of breaking the request.

The bug I learned the most from: a stock whose price barely moves can make the covariance matrix singular, and then the Cholesky step simply fails. The fix is a tiny nudge on the diagonal, small enough not to change the answer. Finding it taught me the difference between knowing a model and making one that doesn’t fall over.

Treating it like it’s public

The analysis route is the one doing real work, so besides a rate limit per visitor it also caps how many simulations can run at once. CSV exports escape anything that starts like a spreadsheet formula, so a crafted ticker can’t turn into one when someone opens the file. Nothing about a portfolio is saved anywhere.

The maths lives in plain Python functions with no web framework attached, which made it easy to test on its own. There are just over a hundred tests.

Not a forecast

Everything here is built from what already happened. The ten-year fan of outcomes is a projection under the model’s assumptions, not a prediction. I’d rather it be clear about that than look smarter than it is.

↑↓ to move↵ to openesc to close