Alexandre Dalban

Work · trading · 24 min read

A live trading system on Polymarket

I built this with a collaborator. We ran it on personal capital from December 2025 to June 2026, then wound it down to make room for research. If you only read one section, read the two postmortems.

$260ktotal volume traded, across 6,213 markets
+$155net P&L on that volume, or about six basis points of it
78.0%win rate on 3,037 trades, the one strategy with a verified profit
13strategies traded or researched across three generations
Dates
Built from December 2025. Live on personal capital from late December 2025 to June 2026, wound down in June
Status
Wound down. Nothing on this page is still running.
Role
Joint project. I wrote most of the research code and most of the production system. Credits.
Scale
Personal capital. The open book was worth a few thousand dollars at its largest, and about $1,650 in USDC when the hub went live in March. This isn't a fund track record.
Code
The repositories are private. Ask me if you want a walkthrough. The exchange account is public.

Seven months in one chart

The wallet is public, so the whole run is one line. It's the exchange's own mark, it covers everything the account did, and it sums up the project: up to +$612 in six weeks, back to break-even by the middle of February, down to −$182 in April, and +$155 when I took the snapshot in September.

The number I'd put next to it is the volume. The account traded $259,999 across 6,213 markets to end $155 up. That's about six basis points of the money we pushed through the exchange, on a book that was never more than a few thousand dollars at a time and turned over several hundred times. It's the right way to read everything below: the edges here are real and they're thin, and most of the work went into finding out which ones survived contact with a fee schedule.

Cumulative profit and loss for the wallet as reported by Polymarket's public profile, December 2025 to September 2026, one point per day. This is wallet-level, so it includes all three generations, every strategy on this page and any other activity on the shared wallet. Source: Polymarket's public P&L endpoint for the account, snapshot taken 2 September 2026. The volume and market counts come from the exchange's public leaderboard endpoints for the same wallet, read on 5 September 2026.

Four things happened in that line, and the rest of the page is about them.

Generation one: pricing Polymarket off Deribit

The first real strategy came from an assumption that sounds obvious. Polymarket lists "Will the price of Bitcoin be above $80,000 on 4 February?" and settles it at 17:00 UTC. Deribit runs a liquid options market on the same underlying, priced by people who do this professionally. If Deribit knows the distribution of BTC tomorrow and Polymarket doesn't, the gap between them is the trade.

Deribit does know it, in a well-defined sense. Breeden-Litzenberger (1978) says the risk-neutral density is the second derivative of the call price with respect to strike, so a full options chain contains the market's entire distribution of where the price lands. Reading P(BTC > $80,000) off that chain is an operation, not a guess. We built the machinery for it:

The pricing engine started on 20 January and was placing live orders by the 23rd. It traded until we retired it in late March. Across the first generation's whole run, from late December to 23 March, the account made 3,939 trades on 994 crypto markets and won 62.4% of the ones that settled.

Why it didn't work

The premise was half right. Polymarket is less efficient than Deribit, but not by much, and every step of the pipeline above adds an error that's the same size as the edge we were looking for. Three of them mattered.

The chain isn't dense enough where the markets are. Deribit's daily options only carry strikes within roughly ±12% of spot. Polymarket lists "above $80,000" when spot is $70,000, and there's no bracketing pair at the daily expiry, so you either skip the market or reach for a different one. We tried reaching. Pricing a one-day settlement with a weekly option 3.8 days out pulls every probability toward 50%, because the distribution at the later expiry is wider. At 60% crypto volatility that's a 10 to 15 percentage-point error on any strike that isn't at the money. I widened the expiry tolerance to fill those gaps on 23 March and reverted it the same day.

The quotes are widest exactly where we needed them. Across 853 Deribit calls sampled on 23 March, the mark price and the bid-ask midpoint differed by 1.97% on average, and the median bid-ask spread was 4.88%. On the options with less than a day to expiry, which are the ones a daily Polymarket market actually needs, the mean spread was 21.1%. Deep out-of-the-money strikes had a median spread of 9.5%. So the input to a two-decimal probability was a price with a two-figure percentage uncertainty on it.

The bigger the disagreement, the more likely we were the wrong one. This was the finding that ended the strategy. If you sort the trades by how far the model's probability sat from the market price, accuracy is a hump. Trades where the two agreed to within 5 points had nothing to trade. Trades in the 10 to 20 point band settled at about 74%, close to what the model claimed. Above 20 points, where the model was shouting, the trades settled at 58 to 61% while the model was claiming 94% or more. The strategy sized on model confidence, so it put the most money into the trades it was worst at.

Realised settlement win rate by the gap between the model's probability and the market price, over 1,414 backtested trades on the same daily markets the strategy traded. The model's own claimed probability in the top two buckets was above 94%. The 10 to 20 point band is the only place the model was roughly as right as it thought it was, and the strategy traded the whole 6.5 to 55 point range. Source: post-fix backtest diagnosis, April 2026.

The Q-to-P machinery turned out to be decoration. The mean adjustment it applied to the raw probability was +0.0001, because Breeden-Litzenberger on a sparse chain already returns values clustered against 0 and 1, and a few points of variance-risk-premium correction can't move a number that's sitting at 0.99. Of 888 high-confidence trades, 886 were already above 90% before any adjustment ran. The model also had a side problem: the 672 high-confidence NO trades settled at 83.0%, and the 216 YES trades at 60.6%, which is what you'd expect if the risk-neutral measure is overstating upside and nothing is correcting it.

The verdict I'd write now is that the model picks the correct side 64.3% of the time and overpays for it. That's a real signal and it isn't a tradeable one, because the interpolation across strikes and maturities that makes the number computable at all introduces an error of the same order as the mispricing it's trying to find.

Delta, vega and the hedge we never built

We managed the greeks and never hedged them. The scorer carried a delta budget and gave every buy and sell a delta term, so the book drifted back toward flat on its own, and by March we'd got noticeably better at not letting one direction accumulate. What the scorer can't do is hedge. A real hedge means shorting perpetuals on a second venue against the binary book, which is another exchange, another set of keys, another margin account and a funding cost against a book worth a few thousand dollars. We never tried it properly. It was a big enough build that it kept losing to whatever was in front of us.

So the book carried whatever delta the model handed it, and the wallet shows it. Single days moved by $100 to $300 on an open cost basis of a few thousand: −$119 on 27 January, +$299 three days later, +$116 on 7 February and −$179 the day after. The range markets were the clearest case. Buying "between $68,000 and $70,000" is a short-volatility position however you label it, and the between direction was the only one that lost money over the whole run (−$111 settled, against +$655 on the directional above markets). We removed it from production on 23 March.

The volatility story is the one part of this I remembered wrong, and the data is worth writing down. The run-up to +$612 happened while Deribit's BTC volatility index went from about 42 to 59, which is what a long-volatility book does when volatility shows up. The decay isn't the mirror image. From 7 February to the end of March the index averaged 54, above the 43 it averaged during the run-up, so the book gave its gains back while volatility stayed high. Volatility didn't fall until April and May (44, then 38), by which point the strategy had already been retired. Whatever cost us the second half, it wasn't volatility collapsing. On the evidence above it was the pricing error, arriving in size because the sizing rule was reading that error as confidence.

Generation two: the 15-minute markets

Polymarket lists a binary market every fifteen minutes for each of BTC, ETH, SOL and XRP, on whether the price will be up or down at settlement. Each contract pays $1 or $0. Up and Down have separate order books, so the two asks don't have to sum to one. And because a market settles every 15 minutes, a strategy settles a few hundred times a day. That volume is the appeal. A hypothesis gets answered in days instead of quarters, which is the opposite of the daily markets above, where a bad assumption took six weeks to show up.

The edge we spent most of our time on is the oldest one in binary markets. Ten minutes before settlement, across 10,113 collected markets, the side priced near 0.80 wins about 90% of the time and the side priced near 0.20 wins about 8%. So favourites are underpriced and longshots are overpriced.

Calibration curve of Polymarket 15-minute Up/Down markets ten minutes before settlement: realised probability of Up against the implied probability from the Up ask. The curve is S-shaped around the diagonal.
Implied versus realised probability of Up, ten minutes before settlement, on 10,113 collected 15-minute markets (all four assets). Brier score 0.127. Favourites above 0.6 are underpriced and longshots below 0.4 are overpriced. The bin counts are printed above each point. Source: minute-level order-book snapshots covering September 2025 to April 2026 for BTC and ETH and late February to April 2026 for SOL and XRP, analysed 12 April 2026.

We researched six strategy families on these markets. S5 and S6 have live records, S4 and S8 traded briefly, and S1 and S7 never traded. Backtest numbers are labelled as backtests. The Sharpe figures aren't computed the same way as each other and none of them are fund-style numbers: the S7 pair is annualised from daily-summed backtest P&L on days a trade settled, the S4 figure from weekly portfolio returns over about 31 weeks, and the sizing figures further down are per-trade ratios on binary payoffs.

  1. S5Favourite press traded live
    Idea
    Buy the higher-priced side of a 15-minute market 5 to 15 minutes before settlement, when its ask is between 0.65 and 0.95 and the two asks sum to less than 1.15. Hold to settlement.
    Evidence
    Live, 10 to 28 April: 3,037 trades, 78.0% win rate, +$383 verified on-chain, +0.80% per rolled dollar.
    Outcome
    Traded live. It's the only strategy with a verified live profit.
  2. S5On 5-minute markets killed live
    Idea
    The same rule on the 5-minute cadence.
    Evidence
    Live: 216 trades, 71.3% win rate, −$494. The backtests had been positive.
    Outcome
    We disabled it. Postmortem 2.
  3. S6Machine-learned gate flat live
    Idea
    Take S5 signals only when a LightGBM model's expected value clears 5%. The model uses 102 features from the order book, its trajectory, Binance candles and on-chain flow.
    Evidence
    Walk-forward backtest: 81.0% win rate. Live on 5-minute markets: 288 trades, +$4.61.
    Outcome
    Flat live. We moved it to 15-minute markets and dropped XRP for miscalibration.
  4. S1Streak reversal researched
    Idea
    After three to five same-direction outcomes in a row, the next 5-minute market reverses 53 to 57% of the time, while the opening prices stay near 50/50. Executed with post-only maker orders.
    Evidence
    Out-of-sample backtest: 2,745 trades, 53.2% win rate, +$64. The same trades executed as a taker lose $95.
    Outcome
    Researched only. The edge is smaller than the taker fee, so it's maker-only or nothing.
  5. S4Model-priced daily markets backtest
    Idea
    The same daily above/below markets as generation one, priced with the Phantom forecaster's Student-t distribution instead of the options surface.
    Evidence
    Backtest only, August 2025 to March 2026: 1,118 trades, 67% win rate, weekly Sharpe 2.2, maximum drawdown −36% with delta-aware sizing.
    Outcome
    21 live executions in April. There's no live result worth reporting.
  6. S7At-the-money strike leak, never traded
    Idea
    Hourly "above $X" markets, entered 15 minutes before settlement at the strike nearest the spot price.
    Evidence
    Backtest Sharpe 9.5 with the leak, 0.85 without it.
    Outcome
    It never traded. Postmortem 1.
  7. S84-hour favourite press added April
    Idea
    Favourite press on 4-hour markets with an order-book-imbalance filter (my collaborator's research).
    Evidence
    Backtest, October 2025 to April 2026: 754 trades, 91.8% win rate, +7.8% return on stake. The in-sample and out-of-sample splits agree.
    Outcome
    Added in April. No separate live tally survives.
Heatmap of realised win rate by favourite ask price (rows, 50 to 95 percent) and minutes into the 15-minute window (columns), from 882 markets. Green above 0.65 and after the first minute, red near 50 percent.
Realised win rate from buying the favourite, by its ask price and by how far into the 15-minute window the entry happens, on 882 tick-level markets with one cent of assumed slippage. The green region above 0.65 is the S5 entry gate. The bottom rows show why buying near-coin-flips loses after fees. Source: tick-level order-book replay, 13 April 2026.

The system

Generation one was a monolith: the cross-venue matcher, the Deribit-priced fair-value engine, a dashboard and an executor that could place live orders from 23 January. We retired it in March for a hub-and-worker design that ran until June.

The production tree came to about 20,000 lines of Python and 6,700 of TypeScript, in a repository of 505 commits, running on a small cloud server. I wrote the large majority of it.

What happened live

The hub went live on 28 March with three strategies on a different market type, the negative-risk multi-outcome markets: a dispersion trade on the constraint that the outcome prices have to sum to one, an Avellaneda-Stoikov market maker with a regime switch on order-flow toxicity, and a tail-theta position. In eleven days the market maker lost $168.64 and the other two roughly broke even. We retired all three on 9 April when S5 and S6 replaced them. The dispersion signal itself was real, and mean-reverting with a half-life of 42 to 157 minutes across all eight events we tested, but it only paid on events with a clear favourite and only in the last month before settlement, which is a narrower opportunity than it first looked.

S5 traded from 9 April. An execution audit over its first eleven days (2,527 intended buys, 95.4% filled, median signal-to-fill latency 4.31 seconds) found that price slippage was slightly favourable, and that the realised win rate, 78.2% with a 95% interval of 76.5 to 79.8%, was significantly above the backtest's 75.6% (binomial z = 3.02). The implementation shortfall came from failed and partial fills. Prices weren't the problem. In the second half of April the dashboard's cumulative curve peaked near +$800 and gave back a third of it, almost all of it ETH, which lost $194 on the dashboard while XRP made $466 and SOL made $261.

The reconciliation in May also found that the dashboard had been counting partial fills that never completed. Against the on-chain record, S5's result from 10 to 28 April was +$383 on 3,037 trades, a 78.0% win rate and +0.80% per dollar rolled. The screen had said +$549. Slippage over all 3,037 trades summed to $3.

S5 cumulative live P&L by asset from 10 to 28 April 2026, with a drawdown panel. Total peaks near 800 dollars and ends near 550; ETH ends negative; maximum drawdown 311 dollars.
S5 cumulative live P&L by asset, 10 to 28 April 2026, as the dashboard recorded it, with drawdown below. The +$549 total in the legend is the dashboard's accounting. The on-chain reconciled figure for the same window is +$383. Maximum drawdown was $311 on a wallet of roughly $1,650. Source: live-performance analysis script run by my collaborator in June 2026 on the April fills.
Realised win rate against the break-even win rate implied by the entry price, per ask bucket, over the first eleven live days (n = 760, 872, 556 and 238). This is where the live edge was. The 0.80 to 0.90 bucket sat at break-even (83.8% against 84.2%). The other three were profitable. The 0.70 to 0.80 bucket, the largest, produced the biggest share of the window's settled P&L, and the widest per-trade edge was at 0.90 to 0.95. Source: the same execution audit. Wilson 95% intervals on the realised win rates, by bucket: 65.4 to 72.0, 74.6 to 80.2, 80.5 to 86.6 and 95.2 to 99.1; the 0.80 to 0.90 interval contains its 84.2 break-even.

By May the exchange had migrated its order API and we spent the last engineering commits on fee accounting. The tuning memo written at that point recommended dropping ETH, tightening the sum-of-asks filter to 1.02 and trading only the 10 to 15 minute entry window. It also prescribed a two-week verification period before scaling. We didn't run that verification. The MSc, the internship and the research were taking the time, and the numbers showed a small, real, fragile edge on a small wallet, so we stopped.

Postmortem 1: fifteen minutes of look-ahead

In April we researched an hourly strategy. Fifteen minutes before settlement, find the "above $X" market whose strike sits nearest the spot price and trade its favourite. The first backtest came back with a 98.8% win rate, +8.3% return on stake and an annualised Sharpe of 9.5 on daily backtest P&L. Numbers like that are what made us look again.

The bug was one function argument. The helper that fetched the spot price to choose the strike was being called with the settlement time instead of the entry time. So the backtest picked its strike already knowing where the price would end up. Fifteen minutes of BTC drift is enough to turn a coin flip into a near-certainty.

With the entry-time price the strategy still wins 94.5% of its trades, because favourites near settlement usually do. But the losses are about fifteen times the size of the wins. Over 696 trades the corrected backtest makes $85 at 25 contracts a trade, a 0.52% return on stake, an annualised Sharpe of 0.85 on daily P&L and a $155 drawdown.

Corrected S7 backtest: cumulative P&L over 696 trades climbing to about 190 dollars then decaying to about 85, with drawdown shading, and a scatter of per-trade P&L showing many small wins and a few losses near minus 20 dollars.
The at-the-money strike strategy after the fix: 696 trades from August 2025 to April 2026, 94.5% win rate, +0.5% return, annualised Sharpe 0.85 on daily P&L (days with trades only). The lower panel shows why a 94.5% win rate nets nothing. The wins are a few dollars each and the losses are $15 to $25. The image title rounds the Sharpe to 0.8. Source: corrected backtest, 12 April 2026. The strategy was my collaborator's; the bug hunt and this write-up were joint.
Win rateReturn on stakeSharpeTrades
Backtest with the settlement-time price (the leak)98.8%+8.3%9.5not recorded
Backtest with the entry-time price94.5%+0.52%0.85696
Sharpe annualised from daily backtest P&L, days with trades only.
The corrected strategy month by month, at 25 contracts per trade. Three of the nine months lose and a fourth (March) is flat at six cents. September, the second-busiest month, makes most of the profit. April, the busiest, loses. This isn't a strategy and it never traded. Source: corrected backtest results file, April 2026.

Afterwards the S7 backtest was rewritten to read the spot price at the entry timestamp, and the postmortem in the repository overview records the rule in writing: verify that a backtest uses only information available at decision time. The research procedure written that week already required every signal to be computed only from data available at time T, and its go-live checklist has a no-look-ahead item. When a backtest looks like a money printer, the first thing to check is whether it can see the answer.

Postmortem 2: a live loss that killed a variant

S5 traded both the 15-minute and the 5-minute cadence from its first live day. The backtests were positive on both, with the 5-minute edge the thinner of the two. Live, the 5-minute variant won 71.3% of 216 trades and lost $494. Those two facts are compatible. At the 0.65 to 0.95 entries the strategy takes, a 71% win rate is below break-even for anything bought above 0.71.

The diagnosis in the repository was a price-band problem. The 0.68 to 0.83 entry band that backtested well on 5-minute markets ran below break-even live, and the fills themselves were clean (orders filled at the quoted ask with median slippage of zero). So the backtest was wrong and the execution wasn't.

We didn't tune it. We cut the 5-minute markets entirely, raised the minimum entry price from 0.55 to 0.65, removed a "dead zone" exclusion the backtest had suggested and reduced the bet size from 25 to 10 contracts while the 15-minute variant proved itself. The machine-learned gate, which had been flat on the 5-minute markets (288 trades, +$4.61), moved to the 15-minute cadence for the same reason.

The rule we kept from this: a live result that diverges from its backtest tells you something about the backtest, so we stop rather than average it in.

Four-panel analysis of the S6 strategy live on 5-minute markets: calibration by entry price, an equity curve over 288 trades ending near 4.61 dollars, win rate by asset with ETH below break-even, and win rate by minutes to end.
The machine-learned gate live on 5-minute markets: 288 trades, +$4.61. It was calibrated on paper and flat in practice, with ETH below break-even. A negative result that cost almost nothing. Source: live analysis, 11 April 2026.

Smaller things we learned

Three out-of-sample equity curves for the streak-reversal strategy at streak thresholds 3, 4 and 5. In each, maker execution ends positive (64, 32 and 18 dollars) and taker execution ends negative (minus 95, 43 and 16).
Streak reversal, out of sample, executed as a maker (green) and as a taker (red) on identical signals, for three streak thresholds. The sign flips in every panel because the fee is larger than the edge. Source: tick-level replay of the pmxt archive, 13 April 2026.

Afterwards: the June rewrite

In June I rebuilt the trading infrastructure from scratch, on my own, as a production-only system. It has no research code and none of the old strategies were ported. The design goal was a system that couldn't do the things that had cost us money or sleep. Git shows 64 commits and 22,770 lines of Python in the first 53 hours, and 77 commits and 24,076 lines of Python (8,599 of them tests, 381 test functions) after about 100 hours across five days. Every commit carries a Claude Code co-author trailer. The speed came from Claude Code, and the architecture is mine.

Lines added per day during the rewrite, 13 to 17 June 2026, from git. Day one is the design documents, the schemas, the gateway and the first tests. The tail is pilot fixes. Source: git numstat on the repository.

The first strategy was a two-sided maker on the noon daily BTC and ETH markets, which is the same market generation one had traded and a different way of standing in it. The research behind it found that a fair value from the Deribit volatility surface does beat the market's own Brier score (0.0631 versus 0.0643 on 2.9 million observations across 7,402 markets). It also found that centring quotes on that fair value hurts in every simulated configuration, down to a 5% weight. That pair of results is the whole lesson from generation one, measured properly: the surface knows something, and it isn't accurate enough to price against. So the maker quotes around the book mid, the model stays out of it entirely, and risk is handled by inventory caps. It went live at ten shares a quote with a $50 daily loss cap.

The pilot ran for three days and each one turned up a problem:

Then I halted it. The simulation's six-month estimate depends on a queue-position parameter I can't observe, so I don't quote it.

What I would do differently

Credits

This was a joint project. I wrote most of the research code and most of the production system. My collaborator led two of the strategies, the fill reconciliation and the exchange-API migration. A third contributor worked on the first-generation monitoring pipeline in January. The June rewrite was mine alone. The research procedure and most of the code were written with Claude Code.