{% extends "base_public.html" %} {% block title %}Racinglines 101{% endblock %} {% block main_class %}r101 r-seq{% endblock %} {% block content %}

racinglines › 101

Racinglines 101

The short version of what this demo does, for anyone who just clicked "I'm already confused": how we trade, how the prediction engine works, how we score it, and how to use the app.

How we trade

The one-sentence version

We built a computer model that guesses how an F1 race will go (who wins, who makes the podium, who beats their teammate), and we use it to trade on Polymarket, a site where people bet on those questions. There are two ways to trade, and this demo shows both.

Makers and takers

Think of a currency exchange booth at an airport. The booth posts two prices: what it pays for your dollars, and what it charges you for them. The booth is the maker. You, walking up and trading at those prices, are the taker.

Maker: the booth

Posts a price to buy and a slightly higher price to sell, then waits. It earns the small gap between the two, over and over. Its job is to know the fair price better than anyone walking by, and to step aside when it doesn't.

Taker: the traveller

Doesn't post anything. It looks at the prices already on offer and trades only when one looks like a bargain. Its job is to be picky: most of the time, it does nothing.

On Polymarket, a "price" is a probability. If "Norris wins" trades at 30¢, the crowd thinks he has about a 30% chance. If our model says 45%, that's a bargain to a taker. To a maker, it's a sign to quote around 45¢ instead of 30¢, or not at all.

Why two roles

  • They make money in different ways. A maker earns small, steady amounts from the gap between its prices. A taker earns occasional, larger amounts when it spots a mispriced market. In our backtests the two barely move together, so running both is steadier than running either one.
  • They need different amounts of trust in the model. A maker lives or dies by its fair price: if it's wrong, faster traders pick it off. A taker only needs the model to be right about the few markets where it disagrees strongly with the crowd.
  • The model is the maker's secret sauce. If takers could see the fair price the maker's quotes come from, they could trade against the maker whenever its quotes lagged the model. So, like a real exchange booth, the maker keeps its model to itself.

The two demo strategies

Try the demo opens the pro demo, the maker account running C. The demo taker, which follows A, signs in by name. For the fantasy league alpha every account gets the same app: five strategy styles to follow in the Lab, built from strategies like these, and the Lab's backtests and research.

A: the core taker

After each practice and qualifying session, reprices every race market. It buys only when the model and the crowd disagree by 10 points or more (5 for head-to-head markets), sizes the bet by how big the gap is (at most $50 a market), and adjusts as the weekend goes on.

C: the maker sleeve

Quotes 2¢ either side of our fair price, 25 shares at a time, leaning against whatever it already holds. It stays out of thin markets, near-certain ones, and any market where the model and the crowd disagree by more than 5 points.

Both were chosen by testing hundreds of setting combinations on past races, then keeping only the ones that made money in both seasons we have market data for.

Betting against the model?

No. Every strategy takes its lead from the model. A taker only buys the side the model calls cheap, and a maker only quotes around the model's own price, staying out of markets where it and the crowd disagree too much.

A bet can still be sold at a loss. Strategy A re-prices after every session, so if the model changes its mind, A sells. When the market will pay more than the model now thinks the bet is worth, selling is the better deal, whatever A paid for it. If the gap only shrinks, A sells part of the bet to carry less risk. There is no stop-loss: a strategy sells because the model changed, never just because the price moved against it.

← The home page and the demoNext: How the engine works →

How the engine works

One engine for every sport

Behind every price on this site is one prediction engine. It doesn't know what F1 or downhill is. Each sport comes with a short description of the data it has, and the engine prices whatever it's given: just finishing positions, or every lap and sector time, or every timed run.

SportWhat the engine reads
F1Results, qualifying, the starting grid, practice, every lap and every sector
Downhill MTBEvery timed run, practice included
NASCARResults, qualifying and fastest laps
MotoGPResults and qualifying

More detail means sharper prices, but the steps are the same in every sport: measure how fast everyone is, run the race thousands of times on a computer, and count.

Measuring who's fast

The engine starts by turning past races into a pace for every competitor. Three ideas do most of the work.

  • Recent races count more. A race's weight halves every 120 days in F1 (240 in downhill), so last month matters more than last season, but last season still counts.
  • A few results aren't enough to be a favourite. Everyone is pulled toward the middle of the field until they've raced enough to earn their place. One lucky weekend doesn't make a rookie a title contender.
  • The right kind of evidence. Finishing 2nd of 5 says less than 2nd of 40, so results are scaled by the size of the field. In downhill, times are compared as percentages, so a 2-second gap means the same on a short track and a long one.

F1 gets a richer version. The engine splits pace into the car (shared by both drivers in a team) and the driver (how they compare with their teammate). In our data the car explains about 60% of the spread in qualifying and 86% in race pace. It also learns how each car does on fast and slow sections of track, so it can tell a team that shines in Monza from one that shines in Monaco.

Running the race 10,000 times

A pace isn't a prediction. Races have crashes, bad starts and lucky safety cars. So the engine runs the race on a computer, over and over: 10,000 times for an F1 race. Each run is one version of Sunday.

What goes into one run

A starting grid (the real one once qualifying is over, a simulated one before), each driver's expected pace, a dose of random luck, and a chance of retiring based on the team's recent reliability. Confirmed grid penalties move drivers back before the start.

Teammates share some luck

A car with a bad setup is usually slow for both drivers. So part of the random luck is drawn once per team and shared by both drivers, measured from past races: about half of it in qualifying, a fifth in the race.

Overtaking matters too. At a track where passing is hard, the grid decides more of the result; at one where it's easy, race pace does. The engine learns how much from each circuit's history.

From simulations to prices

Once the engine has 10,000 versions of the race, every question is a count.

MarketHow it's priced
WinNorris wins 4,500 of 10,000 runs: 45%
Podium, top 10The share of runs he finishes in the top 3, or top 10
Head-to-headThe share of runs he finishes ahead of the other driver
PoleThe share of runs he's first on the simulated grid
ChampionshipToday's points plus every remaining race simulated, many times over

Because every market comes from the same runs, the prices agree with each other. A driver can't be more likely to win than to finish on the podium. That 45% is the fair price the strategies compare with the market's.

Updating through the weekend

The engine re-prices after every session: each practice, sprint qualifying, the sprint and qualifying. Practice laps sharpen the pace estimates; once qualifying is over, the simulated grid is replaced by the real one. On a sprint weekend the sprint is priced as a race of its own, with its own grid and points.

Prices are always as of a moment. A price made on Friday night only uses what was known on Friday night. That rule is what makes a backtest honest: replaying last season, the engine never sees a result before it happened.

What's real and what isn't

This is an early demo that paper trades. From now through 2027, the two strategies follow real Polymarket F1 markets live, race weekend by race weekend, and record the trades they would make at the real prices. No real orders are placed and no real money moves.

  • The backtests replay the full history of Polymarket's F1 race markets: every price and every trade, from the markets' first race onward.
  • The model learns from official F1 timing data (results, lap times, practice and qualifying) going back to 2020, several seasons before those markets existed.
  • No peeking: at every point in a backtest, the model only uses data that existed at that moment. That's the same rule it follows live.
  • Past results don't promise future ones. Two race weekends are mostly luck; the paper-trading season is how we find out whether the backtests hold up.
  • The demo accounts' track record (2025 and 2026 so far) is one of those replays, run with the strategy each account used at the time, and it's labelled backtest replay in the app. The demo maker started 2025 on the default setup, switched twice mid-season to whatever the Edge Finder showed was working so far, then chose C for 2026 as the steadiest of the leaders. The demo taker has always followed A, taking about a third of its recommendations (the hotter ones more often). Each account's strategy page (in the Lab) shows the whole story: cumulative paper P&L, every decision and the evidence behind it, and every weekend.

← How we tradeNext: How we score the engine →

How we score the engine

The Brier score

A price is a forecast, so we grade it like one. The main grade is the Brier score: the average squared gap between the chance we gave and what happened, where what happened is 1 if it came true and 0 if it didn't.

Brier = average of (p − y)²

  • Lower is better. 0 is a perfect forecast; the worst a single forecast can score is 1.
  • A coin flip scores 0.25, whatever happens: (0.5 − 1)² and (0.5 − 0)² are both 0.25.
  • It's in the same units as a probability, so it's easy to compare forecasts on the same races.

The closest thing in racing to a coin flip is the teammate head-to-head: will driver A finish ahead of driver B? Here is one, worked out. The box runs real Python: edit the numbers and press Run.

{% raw %}forecast 70%  beat  (0.7 - 1)² = 0.09
forecast 70%  lost  (0.7 - 0)² = 0.49
forecast 90%  beat  (0.9 - 1)² = 0.01
forecast 90%  lost  (0.9 - 0)² = 0.81
forecast 50%  beat  (0.5 - 1)² = 0.25
coin flip: 0.25 0.25{% endraw %}

A confident miss is expensive: 90% and wrong costs 0.81, nine times what a 70% miss costs over a 70% hit.

Confident misses: Brier vs log loss

The second grade is log loss: minus the log of the chance we gave to what actually happened. Both scores agree on the easy cases. They part ways on confident misses: Brier never goes above 1, but log loss keeps climbing as the chance goes to zero.

01234500.20.40.60.81Chance given to what happenedPenaltylog loss: −ln(p) = 2.30Brier: (1 − p)² = 0.81
The penalty for one forecast, drawn from the two formulas. Move the slider to slide the dots along the curves: at 10% (a 90% call that missed) Brier charges 0.81, log loss 2.30.
10% → Brier 0.81, log loss 2.30
{% raw %}chance   Brier  log loss
  99%    0.00      0.01  
  90%    0.01      0.11  
  70%    0.09      0.36  #
  50%    0.25      0.69  ###
  30%    0.49      1.20  #####
  10%    0.81      2.30  #########
   1%    0.98      4.61  ##################{% endraw %}
BrierLog loss
A coin flip scores0.250.693
Worst single forecast1No limit
A confident miss isPunishedPunished hard
Best at catchingOverall errorRare upsets priced too low

We report both, because they can rank two forecasts differently. Log loss matters most to a market maker: if a long shot we price at 1% really wins 1 time in 20, takers will keep buying it from us.

Honest and sharp

A Brier score splits into three parts:

Brier = Reliability − Resolution + Uncertainty

  • Reliability (lower is better): do the drivers we price at 20% win about 20% of the time? This is calibration, and it's what a market maker needs most, because a price that's wrong in a steady direction gets traded against.
  • Resolution (higher is better): do our prices move away from the average when they should? Giving all 20 cars 5% is perfectly honest and perfectly useless. Being calibrated isn't enough; a forecast has to take a stand.
  • Uncertainty: how hard the races are to call. Not up to us: for a race winner with 20 cars it's 0.0475, the score of giving everyone 1 in 20.

To check reliability we group our prices into bands and count how often those drivers won. Here are our 2025 race-win prices:

0%10%20%30%40%50%60%0%10%20%30%40%50%60%Our price (middle of each band)How often they wonoffcalibratedon the line = honest
Reliability of our 2025 race-win prices (F1 calibration), each band plotted at its middle. Points on the dashed line are honest prices.
{% raw %}priced    off: n    won   calibrated: n    won
5-10%        246   2.0%             172   2.9%
10-20%       327  19.6%             201  24.4%
20-35%        86  34.9%             109  24.8%
35-50%        13  53.8%              39  41.0%{% endraw %}

Uncorrected (red), the engine was too flat: drivers we priced at 5 to 10% won 2.0% of the time, and the favourites won more often than we said. It gave long shots too much and favourites too little. That's a reliability problem, and it's fixable.

Fixing a flat forecast

The fix is one number. Raise every win chance to a power a and rescale so they add up to 100% again: with a above 1, favourites gain and long shots shrink, but the order never changes.

q = pa / sum of all pa

{% raw %}a = 1.0: 30.0% 25.0% 20.0% 12.0%  8.0%  5.0%
a = 1.5: 36.2% 27.5% 19.7%  9.2%  5.0%  2.5%
a = 2.3: 44.7% 29.4% 17.6%  5.4%  2.1%  0.7%{% endraw %}

The power is fitted race by race on earlier races only, so a backtest never uses a result to fix the race it came from. Each simulated race is then re-weighted to match, so the podium, top-10 and head-to-head prices move with the win price and stay consistent with it. It worked on the win prices (blue in the chart above): 2025 log loss went from 0.1694 to 0.1627, and 2026 from 0.2244 to 0.2194. It didn't fix every band: 10 to 20% is still priced too low, and 20 to 35% is now priced too high.

The calibration is off by default. The engine's settings and the method were chosen with these seasons in view, so only races after 14 October 2026 are a clean test. Turning it on for good is the owner's call.

Our scorecard

The F1 engine against two simple guesses, after qualifying: the grid-only guess (how often each grid slot has won, podiumed or scored points in earlier races) and the uniform guess (everyone gets the same chance). Skill is the share of the uniform guess's error the forecast removes.

{% raw %}market      ours    grid  uniform  skill
Win       0.0307  0.0309   0.0471    35%
Podium    0.0692  0.0708   0.1265    45%
Top 10    0.1500  0.1630   0.2500    40%
H2H       0.1960           0.2500    22%{% endraw %}

From F1 evaluation (run 955, the engine's current setup). The engine beats uniform in every season and stage, and every session sharpens it: the average chance it gave the eventual winner rose from 12.1% before practice to 27.5% after qualifying, and to 31.0% with the current setup.

The harder test is the market. On race winners in 2026, our calibrated prices beat Polymarket's log loss (0.2194 against 0.2222). In 2025 the market was sharper (0.1439 against our 0.1627). That gap is why the paper-trading season matters.

The ideas and layout of this part follow the Brier Score Cheat Sheet by @WalrusQuant, from bayesRatings: methodology. The numbers and charts here are our own.

← How the engine worksNext: Using the app →

Using the app

The web app

This site, laid out for the fantasy league alpha. Sign up and you get F$1,000 of fantasy money and four tabs; Try the demo shows the same tabs, and can look but not trade. No real money moves, and nothing reaches an exchange.

TabWhat's on it
MarketsThe prediction markets now, with our fair probabilities next to each venue's prices, for F1, NASCAR and MotoGP
TradePick an F1 market, see its recorded order book, and buy or sell in F$, one immediate-or-cancel order at a time
HistoryYour F$, every trade and order (refused ones with the reason), your strategy's trades, and the leaderboard
LabFollow one of five strategy styles and choose its sizing; its track record and positions; backtests, the Edge Finder and replays

The command line

Everything the site does runs from one command, racinglines, installed with the Python package. The task comes first and the sport second:

CommandWhat it does
racinglines model backtest kart --demoPrices every past race as of before it, and scores the prices
racinglines model forecast kart --demo --saveSimulates the rest of the season and the championships
racinglines live run kart/demo-2026-09 --demo --simulate --no-fetchRuns a live private book against 100 simulated takers

--demo runs the real engine on a made-up Mario Kart season, so you can try it without any race data of your own. Swap kart for f1, nascar, motogp or mtb_dh once you have the data. To watch it first, the quickstart replay replays the same commands in your browser.

With a racinglines.bet account the command line also reaches the hosted server: --remote runs the book commands and Lab jobs there, racinglines remote calls any tool your account may use, and racinglines data pull f1 copies one sport's shared data into your own database. It's in testing, and every remote command prints a warning that a review of venue and data terms is still pending.

Claude, through MCP

racinglines mcp starts an MCP server, which lets Claude (or any other MCP client) work with the same data and simulations as the site and the command line. You ask in plain English, and Claude picks the tools:

  • "What did we have for the Baku winner the evening before qualifying, and what did Polymarket say?"
  • "How did the maker do on Kalshi in 2025?"
  • "Replay that with a 3¢ spread."

There are two ways in. Locally, you run the server on your own machine against your own database. Hosted, you connect Claude to racinglines.bet and sign in with your account, and every job it starts is filed under your account. Remote access is still in testing.

← How we score the engineThe home page and the demo →

{% endblock %}