OwnLedger

Filing status & state — set in Assumptions
Everything below runs entirely in this browser tab. Nothing you enter is sent anywhere.

Portfolio

Drop position/holdings exports from any brokerage — Fidelity, Schwab, Vanguard, E*TRADE, Merrill, or anything shaped similarly. The parser looks for column headers rather than assuming one exact layout, and handles files where each account's holdings sit under their own header block (Schwab's export style) as well as one flat table with an account column (Fidelity's style).

Import

Drop one or more CSV or Excel exports at once, or drop more in later — every file you've loaded stays loaded and combines together. Re-dropping a file with the same name replaces just that one (useful for refreshing a stale snapshot). Use "Clear all portfolio data" below to start over.

Drop CSV or Excel files here, or click to choose

.csv, .xlsx, .xls

Import a file above to begin.

Spending

Drop a transaction export from a bank, credit card, or brokerage cash-management account — the parser looks for a date column and an amount (either one signed column, or separate debit/credit columns). Category breakdowns use whatever category column the file provides; if none exists, transactions are grouped by keyword matching instead. Anything that lands in "Uncategorized" (or is guessed wrong) can be corrected by hand in the transaction detail table below — corrections are remembered for that transaction going forward.

Import

Each upload merges into what's already loaded, so overlapping date ranges across multiple exports are safe to re-upload.

How duplicate transactions are detected
Matched by date + amount + description. A new row only counts as a duplicate against copies that were already in your accumulated history from an earlier import — two rows within the same file are never compared to each other, so two genuinely separate same-day, same-amount charges (two phone lines, two coffees) both count, every time. Only re-uploading an overlapping export collapses the repeat.

Drop CSV files here, or click to choose

.csv

Import a file above to begin.

Glide Path — Historical Window Survival

Runs your income & withdrawal model through every real historical window the dataset supports (1928–2025, sourced from NYU Stern/Damodaran), blended by the asset allocation you set on the Assumptions tab — exhaustive, not sampled. "Success" means the portfolio never hits zero before your plan-to age.

Fill in Assumptions (ages, spending, starting balances), then run.

Detailed Report

Styled after the classic Fidelity "detailed retirement income analysis" — built entirely from your Assumptions (and your imported Portfolio, if you've loaded one). One path, applied deterministically every year — no scenarios, no simulation. Use the Glide Path tab for the historical-sequence stress test.

0%–8%, applied deterministically to every year of the projection. Nominal = this rate + your Assumptions-tab inflation rate.

Fill in Assumptions, then this runs automatically.

Roth Conversion

A standalone what-if sandbox for the conversion schedule — isolated from the full income model (no pension, Social Security, or other cash flows), so you can quickly test different age ranges, bracket targets, or fixed amounts against a starting pre-tax balance alone. The schedule's settings (age range, mode, bracket, fixed amount) are shared with the Assumptions tab and drive the Glide Path and Detailed Report automatically — this tab just runs them in isolation and shows the year-by-year detail.

Sandbox inputs

Age range, mode, and bracket/amount come from the schedule set on Assumptions → "Roth conversion schedule." Only these two are specific to this sandbox:

Summary

Set the schedule on Assumptions, then run it here.

Assumptions & Methodology

Every lever this planner uses. Nothing here is pre-filled with anyone's actual numbers — fill in your own, then Apply & Rebuild.

Household

Spouse's own age isn't used in the projection yet (single retirement-age household model, for now) — a second Social Security benefit and independent spousal ages are on the list for when this becomes multi-person.

Pre-retirement (working years)

Any surplus after tax and your spending target accumulates into taxable savings; a shortfall draws it down. This is a simple bridge model — it'll get more detailed once Spending is built.

Pension

Social Security

Disability payments

Unlike pension or Social Security, disability payments here have both a start AND an end age. The tax-free range is independent — it can cover all, none, or only part of the payment period above, so a mix of taxable and tax-free years is possible (e.g. private disability insurance transitioning to SSDI, or vice versa). Any payment year falling outside the tax-free range is taxed as ordinary income. This applies everywhere the plan is run: Glide Path, Detailed Report, and Roth conversion bracket calculations.

Roth conversion schedule (optional)

Model a multi-year conversion schedule — pick the age range, choose whether each year fills to a bracket ceiling or converts a fixed dollar amount. This feeds the Glide Path directly.

Spending & return assumptions

%
%
Real return = nominal − inflation = the rate applied to portfolio growth throughout the projection, since the whole model runs in today's dollars. IRS tax brackets are inflation-indexed annually, so — expressed in today's dollars — they're held flat across the projection. Social Security's §86 taxation thresholds ($25,000/$34,000 single, $32,000/$44,000 MFJ) are not inflation-indexed by law, so they're deflated year by year here, which is what makes more of your Social Security become taxable the further out the projection runs.

Starting balances

No portfolio imported — enter your current balances by tax treatment directly. Import one on the Portfolio tab and these fill in automatically.

Asset allocation

Blend used by the Glide Path's historical bootstrap. No portfolio imported — set it directly; it's normalized to 100% automatically. Import a portfolio on the Portfolio tab and this is computed from actual holdings instead.