Roman Prigodskii

All work

Vertex Boxing

It began from a thesis:

Regional and club boxing is priced less efficiently than the top of the sport.

Concluded research, September 2026 Every result is a backtest. The report and the code are public under MIT. The data is not, because BoxRec’s terms forbid redistribution.

I moved the Vertex MMA models to professional boxing to test that claim. On every bout with a market price, it fails. What the model turned out to read is where the price is going.

bouts, 1950 to July 2026
413,279
priced bouts
3,288
nats, blended into the closing price
+0.0043
on the 2026 holdout, against a bar of 20
e = 41.8

The thesis, and what happened to it

The project began from a claim: UFC closing prices are efficient, but regional and club boxing prices are not, so that is where a model built on records would find room. The data says the reverse.

Wherever the model put a fighter at least 2 points above the opening price, a threshold fixed before the table was seen, I measured how far the price then moved towards the model by the close. That move rises with the level of the fight.

Chart of how far the price moved towards the model on average, by scheduled distance, with 95% intervals: 4 to 6 rounds +0.0044, 8 rounds +0.0075, 10 rounds +0.0093, 12 rounds +0.0180.
How far the price moved towards the model, by scheduled distance4 to 6 rounds (club, 283 bouts): +0.0044, 95% interval +0.0017 to +0.0073. 8 rounds (regional, 337 bouts): +0.0075, 95% interval +0.0033 to +0.0119. 10 rounds (national, continental, 781 bouts): +0.0093, 95% interval +0.0060 to +0.0127. 12 rounds (title, 468 bouts): +0.0180, 95% interval +0.0130 to +0.0232.move towards the model, in probability0+0.01+0.02+0.034 to 6 rounds club+0.00448 rounds regional+0.007510 rounds national, continental+0.009312 rounds title+0.0180
Redrawn from the figure in section 4.2 of the report.How far the price moved towards the model, by scheduled distance, with 95% intervals. Priced test bouts, June 2023 to July 2026, in a backtest. Report, section 4.2

Cut by the belt instead of the distance, the ordering is the same. The model reads records and ratings, and a rating is only as good as the record under it. At world level both fighters have thirty bouts behind them; on a club card the market knows which of the two is being managed, and the model is reading two thin records. The anonymous regional card the claim was aimed at gets no price at all, so there it cannot be tested.

On a window the rule was never chosen on

Refit on data up to June 2021 and run unchanged on the two years after, the pattern held: at the top of the market the price moved 2.0 times as far towards the model as at the bottom (+0.0276 against +0.0136), and the two intervals do not overlap.

10 June 2021 to 10 June 2023

The rule copied unedited onto two years it was never chosen on. Lines are 95% intervals. The outlined rod is the lower tier’s value laid twice end to end. Report, section 4.2

How far the price moved towards the model, by tier, 10 June 2021 to 10 June 2023Lower tier, 365 bouts: +0.0136, 95% interval +0.0080 to +0.0191. Upper tier, 461 bouts: +0.0276, 95% interval +0.0200 to +0.0347. In the upper tier the price moved 2.0 times as far towards the model as in the lower, and the two intervals do not overlap.move towards the model, in probability0+0.01+0.02+0.03+0.04the intervals do not overlapLower tier8 rounds or fewer, no belt365 bouts+0.0136Upper tier12 rounds, or a continentalor world belt, 461 bouts+0.0276the lower tier, twice: 2.0 times
How far the price moved towards the model, by tier, 10 June 2021 to 10 June 2023Lower tier, 365 bouts: +0.0136, 95% interval +0.0080 to +0.0191. Upper tier, 461 bouts: +0.0276, 95% interval +0.0200 to +0.0347. In the upper tier the price moved 2.0 times as far towards the model as in the lower, and the two intervals do not overlap.move towards the model, in probability0+0.01+0.02+0.03+0.04no overlapLower tier 8 rounds or fewer, no belt365 bouts+0.0136Upper tier 12 rounds, or a continental or world belt461 bouts+0.02762.0 times

What the model knows

On its own the model is a worse forecast than the closing price: −0.0211 nats [−0.0322, −0.0100], and −0.0198 when refit yearly. Blended into the closing price at a weight of 0.17 it improves that price by +0.0043 [+0.0024, +0.0062] on 3,288 priced bouts, so it carries information the price does not.

The model against the closing price, in natsOn its own the model trails the closing price by 0.0211 nats, 95% interval −0.0322 to −0.0100. Blended into the price at a weight of 0.17 it improves the price by +0.0043, interval +0.0024 to +0.0062, on 3,288 priced bouts.against the closing price, in natsthe price−0.03−0.02−0.010+0.01← worse than the pricebetter →The model on its own−0.0198 when refit yearly−0.0211Blended into the priceat a weight of 0.17, 3,288 bouts+0.0043
The model against the closing price, in natsOn its own the model trails the closing price by 0.0211 nats, 95% interval −0.0322 to −0.0100. Blended into the price at a weight of 0.17 it improves the price by +0.0043, interval +0.0024 to +0.0062, on 3,288 priced bouts.against the closing price, in natsthe price−0.03−0.02−0.010+0.01← worse than the pricebetter →The model on its own−0.0198 when refit yearly−0.0211Blended into the priceat a weight of 0.17, 3,288 bouts+0.0043
The model against the closing price, alone and blended, with 95% intervals.

With its margin charged, though, the closing price holds: the one test that found otherwise had read stale prices (e = 1.15 on true closing prices) and was withdrawn. At the opening price, a median three days before the fight, it is different. On its own the model forecasts worse than the opening price. Blended in, it moves that price 87% of the way to where it closes.

Five forecasts of the same 3,077 fights, by log-lossLog-loss on the same 3,077 fights, June 2023 to December 2025, where lower is better. The model alone, 0.3590; The opening price, 0.3506; The open, blended with the model, weight 0.35, 0.3396; The closing price, 0.3379; The close, blended with the model, weight 0.15, 0.3336. Blended into the opening price, the model moves it 87% of the way to the close.log-loss, lower is better0.3600.3550.3500.3450.3400.335← worsebetter →The model alone0.3590The opening price0.3506The open, blendedwith the model, weight 0.3587% of the way to the close0.3396The closing price0.3379The close, blendedwith the model, weight 0.150.3336
Five forecasts of the same 3,077 fights, by log-lossLog-loss on the same 3,077 fights, June 2023 to December 2025, where lower is better. The model alone, 0.3590; The opening price, 0.3506; The open, blended with the model, weight 0.35, 0.3396; The closing price, 0.3379; The close, blended with the model, weight 0.15, 0.3336. Blended into the opening price, the model moves it 87% of the way to the close.log-loss, lower is better0.3600.3500.340← worsebetter →The model alone0.3590The opening price0.3506The open, blended with the model, weight 0.3587% of the way to the close0.3396The closing price0.3379The close, blended with the model, weight 0.150.3336
Five forecasts of the same 3,077 fights, June 2023 to December 2025, by log-loss; further right is better. Report, section 9.1

The opening price, tested with e-values

Each window was scored as an e-value, the method of my first paper, at the prices actually posted, margin included. If the opening price already held what the model knows, the e-value could not grow in expectation; the further it grows, the stronger the evidence that the price was inefficient. The bar is 20; 2023–2025 was registered as one of four hypotheses tested together, so its bar was 80.

Four windows at the opening price, each scored as an e-value

On a log scale from 1, where every e-value starts, to 1,000. Blue marks a window past its bar.

Four windows at the opening price, scored as e-values2016–2020, 2,016 bouts, pre-registered in public: e = 7.0 × 10 to the 6, past the bar of 20. 2021–2023, 1,545 bouts, declared in advance as already seen: e = 12.5, short of the bar of 20. 2023–2025, 3,077 bouts, pre-registered, committed locally: e = 3.9 × 10 to the 8, past the bar of 20 (registered as one of four hypotheses, with a bar of 80). Jan–Jul 2026, 541 bouts, pre-registered in public: e = 41.8, past the bar of 20.the bar, 20110100201,0002016–20202,016 bouts, untimestamped pricese = 7.0 × 106off this scale2021–20231,545 bouts, timestamped pricese = 12.52023–20253,077 bouts, timestamped pricese = 3.9 × 108off this scaleJan–Jul 2026541 bouts, timestamped pricese = 41.8
Four windows at the opening price, scored as e-values2016–2020, 2,016 bouts, pre-registered in public: e = 7.0 × 10 to the 6, past the bar of 20. 2021–2023, 1,545 bouts, declared in advance as already seen: e = 12.5, short of the bar of 20. 2023–2025, 3,077 bouts, pre-registered, committed locally: e = 3.9 × 10 to the 8, past the bar of 20 (registered as one of four hypotheses, with a bar of 80). Jan–Jul 2026, 541 bouts, pre-registered in public: e = 41.8, past the bar of 20.the bar, 20110100201,0002016–2020 2,016 bouts, untimestamped pricese = 7.0 × 106off this scale2021–2023 1,545 bouts, timestamped pricese = 12.52023–2025 3,077 bouts, timestamped pricese = 3.9 × 108off this scaleJan–Jul 2026 541 bouts, timestamped pricese = 41.8
How each window was fixed before it was scored
WindowHow it was fixedResult
2016–20202,016 bouts, opening prices without a timestamp Pre-registered in public: the protocol’s hash was timestamped in Bitcoin blocks 968272 and 968274 and pushed to GitHub before the model was trained. e = 7.0 × 106passed
2021–20231,545 bouts, timestamped opening prices The same protocol, declared in advance as already seen. e = 12.5did not clear the bar
2023–20253,077 bouts, timestamped opening prices Pre-registered, but committed locally, so the order rests on my word. e = 3.9 × 108passed; 1.2 × 108 with everything settled in fight week removed
Jan–Jul 2026541 bouts, timestamped opening prices Pre-registered in public: the rule for which bouts to score was chosen on the three windows above and pushed before the holdout model was trained. e = 41.8passed

The obvious refinements, scoring only title fights or dropping club fights, lowered the evidence in every past window, so the rule stayed as it was. The 2016–2020 opening prices carry no timestamp and no named source, and that market was thinner, so that result is historical.

The leak it caught

Judges’ scorecards are published only for fights that went the distance, so the mere presence of judge fields told the model how a fight had ended, a fact nobody has before the bell. Where judges were recorded, 9.7% of fights ended early; where they were not, 74.3% did.

How a fight ended, read off whether its judges were recorded

A control on 5,673 events confirmed it was the outcome and not the crawler. Report, section 6

Probability that a fight ended early, by whether its judges were recordedWhere judges were recorded, 0.097; where they were not, 0.743. A control on 5,673 events confirmed it was the outcome and not the crawler.probability the fight ended early00.51Judges recorded0.097Judges not recorded0.743
Probability that a fight ended early, by whether its judges were recordedWhere judges were recorded, 0.097; where they were not, 0.743. A control on 5,673 events confirmed it was the outcome and not the crawler.probability the fight ended early00.51Judges recorded0.097Judges not recorded0.743

Put back into the final model, the leak is worth +0.0038 on held-out bouts and nothing on priced ones. It is gone, and a check now tests every column for it. So are two smaller bugs that made identical runs disagree: re-run seven weeks later, the published scoreboard came back identical to sixteen significant digits.

Checks built to kill the result

The opening-price result survived retraining without anything settled in fight week, a simulated null (mean e 0.20, never reaching its registered bar of 80), price-only controls with no model in them (1.2 and 0.25), and every year on its own. Sixteen classic price biases, among them favourite–longshot, the unbeaten record and the home fighter, were tested at the closing price; none reached 20.

The checks built to kill the opening-price result, as e-values on a log scaleA logarithmic e-value axis from 0.01 to 1,000, with the bar at 20. The result at the opening price over 2023 to 2025, e = 3.9 times 10 to the 8, and the same retrained without anything settled in fight week, 1.2 times 10 to the 8, are both off the scale to the right. Price-only controls with no model in them score 0.25 and 1.2. A simulated null averages 0.20. None of sixteen classic price biases, tested at the closing price, reached 20.the bar, 20The result, at the opening price over 2023–2025e = 3.9 × 108off this scaleRetrained without anything settled in fight weeke = 1.2 × 108off this scalePrice-only controls, no model in them0.251.2A simulated null, on averagemean e 0.20Sixteen classic price biases, at the closing pricenone reached 200.010.1110100201,000
The checks built to kill the opening-price result, as e-values on a log scaleA logarithmic e-value axis from 0.01 to 1,000, with the bar at 20. The result at the opening price over 2023 to 2025, e = 3.9 times 10 to the 8, and the same retrained without anything settled in fight week, 1.2 times 10 to the 8, are both off the scale to the right. Price-only controls with no model in them score 0.25 and 1.2. A simulated null averages 0.20. None of sixteen classic price biases, tested at the closing price, reached 20.the bar, 20The result, at the opening price over 2023–2025e = 3.9 × 108Retrained without anything settled in fight weeke = 1.2 × 108Price-only controls, no model in them0.251.2A simulated null, on averagemean e 0.20Sixteen classic price biases, at the closing pricenone reached 200.010.1110201,000
Each check as an e-value, on a log scale from 0.01 to 1,000. Every e-value starts at 1.

One pattern I had published:

The price moves towards the model only on favourites.

It came from taking the margin off the open and the close by two different methods. Fixed, it vanished, and the report records the correction.

A random search, with the rules written first

The last thing tried was brute force, under a protocol committed before the first fit. 200 random configurations were trained on bouts up to June 2021 and ranked on 2021–2023, and the top five were scored once on 2023–2026, which the search never saw.

Six of the 200 had beaten the model already in use on the window they were ranked on; none of the five taken forward kept that lead on unseen bouts. The best had led by +0.0017 where it was chosen and trailed by 0.0004 where it was not.

The best of 200 random configurations, against the model already in useRanked on 2021 to 2023, where it was chosen, it led the model already in use by 0.0017. Scored once on 2023 to 2026, which the search never saw, it trailed by 0.0004.where it was chosenranked on 2021–2023where it was notscored once, 2023–2026+0.0017−0.0004
The best of the 200. The dashed line is the model already in use.

What it does not show

  • The model is not a better forecast than the market.−0.0211 nats against the close
  • With its margin charged, the closing price holds.e = 1.15 on true closing prices
  • The opening-price result is historical.the forward test runs to 2029
  • The effect was absent in 2021–2023.e = 12.5, short of 20

The anonymous regional card carries no price, so the thesis was refuted where it can be tested and cannot be tested where it was aimed.

The report has all three tests and every check that could have killed them.

The forward test

The weight in the final rule, 0.10, was picked after the 2026 holdout was scored, so only fights that had not happened can test it. On 24 September 2026 the rule was frozen and pushed publicly before any bout it covers had been fought: a model trained to 24 July 2026, blended into the opening price at that weight, and tested on every fight where the blend rates a fighter above the price posted for them.

It is an e-value that can be read at any checkpoint, rejects at 20, and closes on 25 September 2029, three years after the freeze. At 60 to 90 such fights a year, an effect as large as the rule’s 2016–2026 average would be expected to pass in one to two years, before the close. One about half that size would take three to four, so the test would probably close before it passed. With no effect it would never pass. The result will be reported either way.

When a true effect would pass, at 60 to 90 fights a year

From the freeze to the close, with the ranges the protocol gives for a pass. The range for half the effect begins where the test closes.

The forward test, from its freeze to its closeFrozen and pushed on 24 September 2026; it closes on 25 September 2029. At 60 to 90 qualifying fights a year, an effect as large as the rule's 2016 to 2026 average would pass one to two years after the freeze, before the close; one about half that size would take three to four, so the test would probably close before it passed; with no effect it would never pass.Frozen and pushed24 September 2026The test closes25 September 20292027202820292030the calendarif the true effect istodayAs in 2016–2026the rule’s averageone to two yearsAbout half thatthree to four yearsNonenever01 year2 years3 years4 yearsyears since the freeze
The forward test, from its freeze to its closeFrozen and pushed on 24 September 2026; it closes on 25 September 2029. At 60 to 90 qualifying fights a year, an effect as large as the rule's 2016 to 2026 average would pass one to two years after the freeze, before the close; one about half that size would take three to four, so the test would probably close before it passed; with no effect it would never pass.Frozen24 Sep 2026Closes25 Sep 20292027202820292030todayAs in 2016–2026 the rule’s averageone to two yearsAbout half thatthree to four yearsNonenever01 year234years since the freeze