Skip to content

Search

Search projects, papers and posts, or ask the AI.

All work

Finance & Trading2026

LIFECYCLE

Lifetime-Utility Research Platform for Multi-Asset Retirement Portfolios

A research platform that measures, in certainty-equivalent consumption, how much a cash-flow-aware multi-asset allocation is worth over 60/40 or a target-date glidepath across savings rates, withdrawal rates and economic regimes.

Video demo 0 0PythonUpdated Nov 2026
91
heatmap cells per decumulation sweep, each a cached, addressable run
5
scenario generators
14
allocation policy types
27
backend tests
lifecycle · recorded demo · 0:22
  1. 01Problem

    Most retirement tools ask whether a portfolio survives. I wanted to measure how much better off an investor is when the allocation responds to their own cash flows, horizon and the economic regime. LIFECYCLE answers that in certainty-equivalent consumption: the constant real spending level that gives the same lifetime utility as the simulated outcome. The headline exhibit is a heatmap of the percentage gain of an optimised policy over a 60/40 portfolio, across withdrawal rates from 2% to 8% and years relative to retirement.

  2. 02Data

    I wrote ingestion for five public sources: the Kenneth French library, FRED, the Federal Reserve's Gürkaynak–Sack–Wright yield curves, the New York Fed ACM term premium and the SSA life table. A committed snapshot of 52,884 rows lets the panel build with no network access, and a manifest records the SHA-256 of every file. I also wrote WRDS ingestion for CRSP, bond and ETF series, which take priority when present. Treasury, TIPS and credit returns built from public yields are repriced month to month and tagged as model-generated.

  3. 03Market Models

    The research layer studies how assets move together before anything is simulated. I implemented rolling 12, 36 and 60-month correlations, Ledoit–Wolf shrinkage, DCC-GARCH(1,1), Student-t copula tail dependence and PELT change points, with covariance forecasts scored out of sample by QLIKE. A fixed-income module prices bonds on the fitted curve and reports duration, DV01, convexity, rate-shock tables and a PCA of yield changes. Five scenario generators feed the simulator: historical cohorts, a stationary block bootstrap, a multivariate Student-t, a Markov-switching model and a yield-curve factor model.

  4. 04Lifecycle Kernel

    The simulator is a Numba kernel that moves wealth forward monthly in real terms. It covers accumulation and decumulation in one model: labour income following the Cocco–Gomes–Maenhout profile, a pension, rebalancing costs, SSA mortality and a bequest motive. Spending can follow fixed real, fixed percentage, guardrails, bucket or amortised rules. Utility is CRRA with a consumption floor, and paths that cannot fund planned spending are flagged as shortfalls instead of being dropped. Every policy is compared with its benchmark on the same random paths, so differences are paired.

  5. 05Optimisation

    I implemented 14 allocation policy types. The static ones include mean–variance, risk parity, mean–CVaR solved as a linear program and a CRRA-optimal constant mix fitted on simulated paths. The dynamic ones include regime-dependent mixes and a parametric policy that is fitted on one set of seeds and reported on another. As a reference point I solved a reduced three-asset problem by grid dynamic programming, with a 200-point cash-on-hand grid, a 21-point weight simplex and Markov-switching regimes.

  6. 06Runs and API

    Every computation is a frozen specification whose SHA-256, combined with the data catalog hash, becomes its run ID, so an identical request returns from the cache. Runs are stored in a SQLite registry with the engine version, lockfile hash, seeds and timings. A sweep is a grid of such runs: the default decumulation surface has 91 cells, 13 withdrawal rates by 7 horizons, at 2,000 paths per cell. A FastAPI service exposes 25 operations under /v1, streams progress over server-sent events and returns path arrays as Arrow IPC.

  7. 07Research Terminal

    The front end is a Next.js application with nine screens: an overview, a research lab, a fixed-income panel, a simulator, a policy optimizer, a withdrawal-rate lab, comparison and validation, a run history and a methodology page. It never computes analytics; each chart is drawn with Plotly from a backend run and carries that run's ID, spec hash and catalog hash. Clicking a heatmap cell opens the policy behind it, its wealth and consumption fans and its depletion probability, and any run can be exported as PDF, CSV, BibTeX or JSON.

  8. 08Validation

    I wrote 27 backend tests on synthetic fixtures, covering accounting identities, recovery of the Merton solution, estimator recovery and the API. One test replays historical 60/40 cohorts against an independent spreadsheet-style loop and requires agreement to 1e-8. For results, the platform reports Monte Carlo, parameter and model uncertainty separately: convergence across 1,000 to 10,000 paths, a parameter bootstrap, and the same policy under three scenario generators. A result is called robust only if its sign survives all three, and a reproduce command re-executes any run and asserts identical summary statistics.

  9. 09Findings

    On the public-data snapshot, with WRDS data still pending, the headline run compared a parametric dynamic policy with 60/40 for a risk aversion of 4 under the block bootstrap. Across the 91 cells the mean gain in certainty-equivalent consumption was 7.55%, the largest was 17.6%, and 80 cells were more than two standard errors from zero. Gains were close to zero for retirees withdrawing 3% or less and generally grew with the withdrawal rate. These numbers are model-dependent research output from one data vintage, not investment advice.

Screenshots