Inspiration
Every small business eventually faces a decision like: open a second location now, wait six months, or not at all? Almost everyone answers this with a spreadsheet NPV — and that spreadsheet has a blind spot. It assumes you decide today, once, and can never change course. It structurally can't price the value of flexibility: waiting for more signal, expanding once a bet is confirmed working, or bailing out for a salvage value if it isn't.
Big companies have priced that flexibility for decades using real options valuation — the same math behind financial options, applied to oil leases, pharma R&D, power plants. Small businesses essentially never do this, because the tooling assumes a quant on staff. That gap — genuinely underserved, genuinely solvable with real math — is what we built OptionRun to close.
What it does
OptionRun turns a small-business capital decision into a financial option and prices it properly. Pick a decision template (open a second location / expand capacity / abandon a product line, or go fully custom), enter a handful of numbers — or upload a revenue-history CSV and let the app estimate volatility from your real data — and it returns:
- Static NPV vs. Real Option Value, with the dollar value of flexibility called out and a plain-English recommendation (invest now / wait / abandon / hold), plus the exact threshold and timeframe that would flip the call.
- Greeks (Δ, Γ, Vega, Θ, ρ) — the same sensitivities an options desk reads, applied to the business decision.
- A Monte Carlo projection cone — thousands of simulated futures for the business value, shown as P10–P90 confidence bands.
- A convergence diagnostic proving the price is a real converged number, plus the exercise boundary showing the actual decision rule over time.
On our demo case, static NPV says lose $40,000, don't do it — but the real option value is +$57,000, because the option to wait is worth something a spreadsheet can't see.
How we built it
The core is a from-scratch quantitative finance engine in TypeScript — no options-pricing library. The decision is modeled as an option on a business-value process following Geometric Brownian Motion, with a cost-of-waiting yield (the real-options analog of a dividend) that makes "wait" a genuinely costly choice rather than a free lunch.
The value is computed three independent ways so the numbers cross-check each other, instead of trusting one algorithm:
- A Cox-Ross-Rubinstein binomial lattice — backward induction with American early exercise at every node, which also yields the exercise boundary.
- A Longstaff-Schwartz least-squares Monte Carlo pricer — regression-based American option pricing over thousands of simulated paths, including a hand-rolled Gaussian-elimination solver for the regression. Structurally different from the lattice, so agreement between the two is meaningful.
- Black-Scholes closed form as the European limit — a sanity floor (American ≥ European) and the convergence oracle we test the other two against.
On top: Greeks by central finite differences, Monte Carlo percentile bands by
order statistics, and a convergence series across a log-spaced step grid. All
Monte Carlo code runs on a seeded PRNG — never Math.random() — so every result
is reproducible and every test is deterministic.
The frontend is a single Next.js app: the pricing engine is pure, framework-free TypeScript with zero DOM/React dependency, so it's independently testable and the API route and UI are thin consumers of it. We iterated hard on the visual design too — starting from a generic "AI-glassmorphism" look and rebuilding it into a restrained, editorial "Swiss terminal" system (one grotesque typeface, monospace figures only, monochrome + a single signal color, flat hairline surfaces) once we realized the flashier version was undermining how serious the underlying math is.
Challenges we ran into
- Getting the option payoffs exactly right. The "expand" decision (scaled
payoff
max(α·S − K, 0)) needed its Black-Scholes cross-check rescaled by the same α or the sanity-check number looked wrong by a factor tied to the leverage — caught by comparing American vs. European values and noticing the gap was way bigger than an early-exercise premium should ever be. - A subtle React/animation bug in the UI layer, not the math: keying a results section by a per-recalculation value made an exit/enter transition library replay every time, and in one environment that transition never fully completed — silently freezing the page on a stale result even though the correct number had already arrived over the network. Fixed by keying on something stable and updating in place instead.
- Being honest about what "error" means. Our convergence chart originally reported the gap between the lattice and the Black-Scholes value as "relative error" — but when the cost-of-waiting is positive, that gap is the early-exercise premium, a real economic quantity, not a numerical mistake. We caught this and relabeled it correctly rather than showing a misleading number.
Accomplishments that we're proud of
- Three independent, hand-written pricing algorithms that agree with each other to within basis points — real proof the numbers are correct, not just plausible.
- 38 deterministic unit tests that encode actual financial theory (binomial→ Black-Scholes convergence, put-call parity, Greek signs) rather than just smoke-testing the UI.
- A tool a non-quant small business owner could genuinely use to make a real decision, backed by graduate-level numerical methods they never have to see.
What we learned
Real options theory is criminally underused outside of large-capital-project finance, and the actual math — binomial lattices, least-squares Mo
Built With
- monte-carlo-simulation
- nextjs
- node.js
- quantitative-finance
- react
- recharts
- tailwindcss
- typescript
- vercel
- vitest

Log in or sign up for Devpost to join the conversation.