Skip to content
Oxford, United KingdomIndex 01 to 10

Finn Lakin

I rebuild published numbers from primitives and report the gap.

Sometimes the gap is the finding. Economics, finance and software on one side; film, print, drawing and clothes on the other. It is one habit either way: take the finished thing apart, work out what it is made of, and write down what you found.

Four rebuilt. 3 held.

Economics, Finance & International Business, Oxford Brookes University. Exchange year at Université Paris Dauphine. Class of 2027.

Four published quantities, rebuilt from primitives and checked against the source. The last row is the point of the table: the same model that pins the yield curve down cannot pin down the premium it draws out of it.

Four reconstructions, against the published series
  • Order book state

    736,997 events replayed

    Against
    Coinbase
    Deviation
    byte-identical
    Verdict
    holds
  • US CPI, headline rate

    rebuilt from eight expenditure groups, 101 months

    Against
    BLS
    Deviation
    0.083 pp
    Verdict
    holds
  • Fitted yield curve

    affine term structure, re-estimated

    Against
    NY Fed ACM
    Deviation
    0.45 bp
    Verdict
    holds
  • Term premium

    same model, same data, same estimation

    Against
    NY Fed ACM
    Deviation
    14 bp
    Verdict
    31× the fitted error
Term premium, ten year

14 bp

against 0.45 bp on the curve it is drawn from, from the same model, the same data and the same estimation window.

31× the fitted error

Selected work

Index

Ten projects, strongest evidence first. Ordered by how much of each result you can check for yourself, rather than by how large the number is. Every project states what it does not show.

NoPieceFigureBuilt withEvidence
01marked-to-model
The venue's own quotes were clean. Its mark surface, the one that decides liquidations, broke static arbitrage 11,593 times.
11,593Rust · Python · differentialReproducible
02nanobook
An update costs about 5 nanoseconds, roughly 9 times faster than the BTreeMap most people reach for first.
~5 nsRustMeasured
03term-premium
The fitted yield reproduces to 0.45 bp. The premium drawn out of that same curve reproduces to 14, and the start date alone moves it 81.
0.45 bpPython · no dependenciesMeasured
04deflated-sharpe
The winning rule's Sharpe is 0.75. The best of 796 rules with no skill at all would be expected to score 0.80.
796Python · no dependenciesSimulated
05honest-backtest
AAPL mean reversion earns 8.4% a year before costs and loses 2.0% after them.
+8.4%Python · CLISimulated
06orderbook-sim · orderbook-live
Queue position is unknowable, so it ships as three named models rather than one number. The fill rate lands between 23.1% and 25.0%.
23.1–25.0%Python · TypeScriptSimulated
07whose-inflation · my-inflation
The headline rate rebuilds to 0.083 pp. Inside March 2022's 8.7%, the car-dependent commuter was living 11.0% and the student 7.5%.
0.083 ppPython · TypeScriptMeasured
08trade-mirror
Across 39 country pairs the numbers came out arithmetically impossible. Drop the Netherlands and the implied freight wedge is 1.062, right where theory says it should sit.
39Python · CLIReproducible
09rent-or-buy
Break-even at 8.3 years, and buying wins in 52% of the swept scenarios. That is another way of saying it is close to a coin toss.
8.3 yrTypeScript · zero runtime dependenciesIllustrative
10finance-analysis
Bank statement in, plain English out. DuckDB does the analytics and the model writes the SQL.
Python · FastAPI · DuckDBTool
Reproducible
A fresh clone reproduces every figure offline, from a capture committed to the repo.
Measured
Measured or benchmarked against real data, which the repo fetches rather than ships.
Simulated
A simulation over real historical prices. Not a record of trading, and no money was at risk.
Illustrative
Model output from assumptions the reader sets. The range is the result; the point estimate is not.
Tool
A tool rather than a finding, so there is no result here to reproduce.
Deribit, the same scan on two surfacesStatic arbitrage violations

Marks are not tradeable prices, so this is a statement about the margin surface rather than about arbitrage available to anyone. The top of book is clean.

NY Fed ACM, re-estimated from the same dataDeviation from the published series

The quantity the model is fitted to comes back almost exactly. The quantity derived from it does not, and the gap is the finding rather than a bug in the reconstruction.

01Rust · Python · differential

marked-to-model

The venue's own quotes were clean. Its mark surface, the one that decides liquidations, broke static arbitrage 11,593 times.

Reproducible

Deribit publishes a mark price and a mark implied volatility for every listed option. Those numbers are not decoration: they set margin requirements and they decide liquidations. I checked whether they are consistent with themselves.

A published surface is this: thousands of numbers arriving faster than anybody checks them. The whole project is one long look at what is in there.

Mixkit, free licence

static arbitrage violations in the mark surface
11,593
snapshots, BTC and ETH chains
88
at or above one full tick, 2.0% of the total
235
in the venue's own bid and ask, scanned the same way
0

What this does not show. Marks are not tradeable prices and the top of book is clean, so this is a statement about the margin surface rather than about arbitrage available to anyone. One venue. The lifetimes are censored, so the persistence figures are a lower bound.

02Rust

nanobook

An update costs about 5 nanoseconds, roughly 9 times faster than the BTreeMap most people reach for first.

Measured

A limit order book built for update latency, and checked hard enough that the latency number means something. Twenty minutes of live Coinbase data replayed against an independent Python implementation, to establish that the fast thing is also the correct thing.

Every car here is taking a route it chose from a few, and the pattern that comes out is nobody's plan. That is most of what an order book is.

Mixkit, free licence

per update, 9.2× faster than BTreeMap
~5 ns
events replayed, byte-for-byte identical
736,997
agreement with the exchange's own snapshots
99.4%
reading the top ten levels, the cost of the design
1.6× slower

What this does not show. This is an aggregated price-level book, not order-by-order. There is no matching engine and no order entry, and it is single-threaded. The latency figure is a benchmark on a committed sample session, not a claim about a production venue.

03Python · no dependencies

term-premium

The fitted yield reproduces to 0.45 bp. The premium drawn out of that same curve reproduces to 14, and the start date alone moves it 81.

Measured

Rebuilds the New York Fed's ACM term premium decomposition from the yield curve up, and then asks how much of the split the model can actually pin down. The answer is that the fit is pinned down and the decomposition is not.

A curve is fitted to what is observed. What is derived from it inherits every assumption that went in, and spreads.

Mixkit, free licence

median error on the Fed's fitted yields
0.45 bp
error on the term premium from the same model
14 bp
specification band, from the start date alone
81 bp
correlation with the Fed's published ten-year premium
0.9997
Ten-year term premium, rebuilt81 bp wide
0.00%estimating from 1961
0.82%estimating from 2000

The same model, the same data and the same estimation. Only the start date changes, and the answer moves across the whole band.

What this does not show. This is not a claim to reproduce the Fed's published term premium level to the basis point, and it is not a trading signal. Starting the estimation in 1961 puts the recent ten-year premium near zero; starting in 2000 puts it near 0.82%. Both are the same model.

04Python · no dependencies

deflated-sharpe

The winning rule's Sharpe is 0.75. The best of 796 rules with no skill at all would be expected to score 0.80.

Simulated

This charges a backtest for the search that produced it, with the two tools built for the job: the deflated Sharpe ratio and the probability of backtest overfitting. I searched 796 ordinary trading rules across four stocks over ten years and kept the best one, which is exactly how a strategy usually gets found.

796 rules, searched. Somewhere in a space this shape there is always one that looks like skill.

Mixkit, free licence

rules searched, best one kept
796
annualised Sharpe of the winner
0.75
expected Sharpe from luck alone at that search size
0.80
deflated Sharpe once the search is charged for
0.43

What this does not show. This is not a claim that these four stocks contain no signal, and it is not a trading system. It is a demonstration that a Sharpe quoted without the size of the search behind it carries almost no information. On 75% of the ways of splitting the history, the in-sample best ranks below the out-of-sample median.

05Python · CLI

honest-backtest

AAPL mean reversion earns 8.4% a year before costs and loses 2.0% after them.

Simulated

Tests a trading strategy against ten years of real prices, then charges it for everything a real trade would actually have cost, and watches most of the profit disappear. Commission, spread, slippage and borrow, applied per fill rather than as an annual haircut.

Costs are paid like this, a little at a time, which is why a backtest that ignores them can turn a loss into a plausible return.

Mixkit, free licence

a year before costs
+8.4%
a year after them
−2.0%
of starting capital paid away in charges
114%
symbols lose money once costs are applied
3 of 4

What this does not show. No shorting constraints and no borrow cost. The risk-free rate is set to zero. Daily bars only, so intraday fills are assumed away. Four symbols, all of which still exist: that is survivorship bias and I have not fixed it, only labelled it.

06Python · TypeScript

orderbook-sim · orderbook-live

Queue position is unknowable, so it ships as three named models rather than one number. The fill rate lands between 23.1% and 25.0%.

Simulated

Rebuilds what an exchange's order book looked like at any moment in the past, then lets you test whether an order you would have placed would actually have been filled. Where the honest answer depends on an assumption nobody can verify, the assumption is named and the spread between them is reported.

Latency is the only number here that a picture can carry: the gap between one of these and the next.

Mixkit, free licence

fill rate, across the three queue models
23.1–25.0%
events replayed in about half a second
200,000
tests, including a 20,000-operation differential
115

What this does not show. No market impact: the simulated order does not move the book it is placed into. A synthetic venue, a single instrument and constant latency. The live viewer's fill estimates run from 31% to 85% depending on the model, and the honest answer there is the range rather than any single number.

07Python · TypeScript

whose-inflation · my-inflation

The headline rate rebuilds to 0.083 pp. Inside March 2022's 8.7%, the car-dependent commuter was living 11.0% and the student 7.5%.

Measured

Rebuilds US CPI from its eight expenditure groups, checks the reconstruction against the published series, and then reweights it for households that spend differently. One published number turns out to contain a wide spread of lived experiences, and the spread widens in a shock.

One index number stands for every price everybody pays. Close enough in, it stops being one number.

Mixkit, free licence

mean absolute error against the published headline
0.083 pp
months reconstructed
101
the car-dependent commuter, March 2022
11.0%
the student, same month, same country
7.5%

What this does not show. United States only, and eight expenditure groups rather than the full basket. The calculator does not measure your spending, it lets you assert it: the output is only as good as the shares you set, and the presets are informed guesses rather than anybody's receipts.

08Python · CLI

trade-mirror

Across 39 country pairs the numbers came out arithmetically impossible. Drop the Netherlands and the implied freight wedge is 1.062, right where theory says it should sit.

Reproducible

Every international trade gets counted twice, once by the exporter and once by the importer, and the two numbers never match. This compares them and asks why they disagree. The Rotterdam effect falls out of the discrepancies on its own, without being looked for.

Following somebody else's route exactly still costs you the traffic. That gap is the whole question here.

Mixkit, free licence

country pairs, 2022
39
implied freight wedge, excluding the Netherlands
1.062
tests, all offline against cached responses
38

What this does not show. The freight adjustment is a single global constant of 1.08 applied to every route regardless of distance or cargo. That is the weakest thing in the project and it is the reason the wedge is quoted with the Netherlands excluded rather than as a headline.

09TypeScript · zero runtime dependencies

rent-or-buy

Break-even at 8.3 years, and buying wins in 52% of the swept scenarios. That is another way of saying it is close to a coin toss.

Illustrative

A rent-versus-buy calculator that answers the question people actually have, which is not 'which is cheaper this month' but 'which choice leaves me wealthier by the time I would sell, and how much does that answer depend on things nobody can know'. UK mode carries stamp duty; the tornado chart ranks the assumptions by how much they move the result.

The decision this models is not financial for most people. The arithmetic still has an answer, and it moves a long way on assumptions nobody states.

Mixkit, free licence

break-even, month 99, on the default assumptions
8.3 yr
of swept scenarios where buying wins
52%
swing from appreciation alone, 1.5% to 5.5%
$180,827
tests
98

What this does not show. A fixed mortgage rate with no refinancing, and a property-tax growth assumption that does most of the work in the long run. Every figure above is the output of assumptions a user sets, so the range matters and the point estimate does not.

10Python · FastAPI · DuckDB

finance-analysis

Bank statement in, plain English out. DuckDB does the analytics and the model writes the SQL.

Tool

Import a CSV export from any bank, Monzo, Starling, Revolut or a standard statement, into a local database, then interrogate it in plain English. Built because spreadsheets are slow to ask new questions of and dashboards only answer the questions they were built for.

Most of what a market does is not visible from here either. The tool exists to pull one part of it into view.

Mixkit, free licence

What this does not show. This is the one project here with no measured result to report, because there is nothing in it to measure: it is a tool rather than a finding. Your CSV is loaded into a temporary in-memory database for the session and is not persisted, but the question and the schema go to a model API, so it is a local tool with one network dependency. The hosted demo runs on a free tier that sleeps when idle, so a cold first load takes about forty-five seconds and shows a blank tab while it wakes. It is quick once awake.

About

Why this way

I read Economics, Finance & International Business at Oxford Brookes University, and I have just come back from an exchange year at Université Paris Dauphine, taught in French. Before that, Charterhouse, with A-levels in Mathematics, Economics and French.

The projects on this page came out of a habit rather than a plan. Somebody publishes a number, I want to know how it was built, and the only way to find out is to build it again and see where the two answers part company. Most of the time they agree, and the exercise teaches me the method. Occasionally they do not, and that is the more interesting outcome: a mark surface that breaks static arbitrage eleven thousand times while the quotes beside it stay clean, a term premium that moves eighty-one basis points on the choice of start date, a backtest that turns from profit to loss once it is charged for its own trading.

The habit has a cost worth naming. It makes me slow to accept a figure and slower to publish one, and there are results here that took longer to caveat than to compute. I would rather that than the alternative, which is a portfolio of numbers nobody can check.

What I want next is to do this for a desk: equity research, quantitative methods, or the engineering underneath both.

Path

Where I have studied and worked

Four years of it, with what each place was actually for.

  1. Sep 2021 – Present
    Junior AnalystJura Consulting
  2. Sep 2025 – May 2026
    Exchange year, International Business and Data Analysis in RUniversité Paris Dauphine
  3. Oct 2024 – Nov 2024
    Team LeaderBloomberg Global Trading Challenge

Tools

What I actually use

Programming

  • Python
  • R
  • Rust
  • TypeScript
  • SQL and DuckDB

Methods

  • Econometrics
  • Affine term structure models
  • Backtest overfitting and deflated Sharpe
  • Market microstructure
  • Index reconstruction
  • Monte Carlo and scenario sweeps

Finance

  • Equity research
  • Options and derivatives
  • Energy markets
  • Portfolio construction
  • Financial modelling
  • Bloomberg Terminal

Elsewhere

  • Athletics, UK top 100 in hurdles, 2022
  • Competitive slalom and giant slalom skiing
  • Team leadership

Languages

English
Native
French
BilingualDELF B2, plus an exchange year taught in French
Spanish
Professional

Bays

Five cut, none filled

Space held for the other half of the work: the pictures, the prints, the clothes. Empty until there is something of mine to put in it, because a wall hung with stock images is an advertisement for stock images.

01Painting, drawing
02Photography, film
033D, code
04Graphic design
05Archive, fashion

References

On record

From people who have worked alongside me.

Finn ran our Bloomberg Trading Challenge team with the calm of someone twice his age. He set the thesis, structured how we sized positions, and ran the team retros honestly when trades went against us. […]
Vadym KosmarovTeammate, Bloomberg Global Trading Challenge 2024

Cut. A closing sentence citing a performance figure has been cut, because no committed record of that figure exists and it should not appear on this site under anybody's name.

I've worked with Finn on London-based transaction advisory deals where precision and turnaround matter. His analytical output punches well above his year of study — the spreadsheets are clean, the assumptions are documented, and the commentary is sharp enough to drop straight into a client deck. He's one of the most commercially-minded students I've come across.
William Du-CannCollaborator, Transaction Advisory, London

Contact

Get in touch

Happy to talk through any of the methods above, including the parts that did not work.