Case study
Robinhood performance dashboard
A correct record from a messy export.
Takes a raw brokerage CSV and turns it into a correct, per-trade profit-and-loss record by pairing every buy fill with the sell fill that closes it.
The work here is data correctness, not trading. The interesting part is the transaction-pairing algorithm and the pipeline around it. This page documents how the record is built and where naive approaches get it wrong.
CSV Ingest · Transaction Pairing · FIFO · Options Matching · D3 Analytics
A messy export becomes a correctly paired, per-trade record.
What actually happens
Export gives you
A flat list of fills: buys and sells interleaved across symbols, partial quantities, day trades, and options contracts, in the order they happened.
Correct record
The problem
The export is a flat log of fills, not a list of trades.
Nothing in the file says which sell closed which buy. That link has to be reconstructed.
Positions are scaled and day-traded across interleaved rows.
One symbol can have many open lots at once. Naive pairing matches the wrong lot and computes the wrong cost basis.
Multiple option contracts share the same underlying.
Matching by symbol alone collapses distinct contracts together and produces P/L that never occurred.
The system
One direction of data flow: a raw export enters, a correct per-trade record leaves. Each stage has a single job and hands a cleaner shape to the next.
The hard part
Pairing is where correctness is won or lost. The algorithm has to decide, for every closing fill, exactly which open lot it draws from, and hold the rest open. These are the cases it has to get right.
How the pairing handles it
The interface
The record is meant to be inspected, not just read. Every view reads from the same paired trades, and everything recomputes together when the table is sorted or filtered.
Trades table
A sortable, filterable table of closed trades. Changing it drives every statistic and chart on the page.
Per-trade bars
One D3 bar per closed trade, so an individual result can be read back to the fills that produced it.
Cumulative line
A running line over time, drawn from the same records, so the whole and the parts always agree.
Stack
Backend
Python, FastAPI, and Pandas: parsing the export, running the pairing algorithm, and serving per-trade records.
Frontend
React and D3.js: the trades table, per-trade bars, and cumulative line, all recomputing from a single source.
Source
The pairing algorithm and the full pipeline are open. Read the code that turns the export into the record.