Payoff Surfaces¶
Payoff surfaces compute the outcome of a bet for every possible scoreline on the goal grid.
How It Works¶
- A
PayoffSurfacemaps each (home, away) scoreline to a payoff: +1 (win), 0 (push), or -1 (loss) - Combined with a model's PMF, this yields expected value per cell
- Summing gives the model-implied win/loss probability and fair odds
Asian Handicap¶
from pyrf.payoffs import AsianHandicap
from pyrf.market import QuotedLine
from pyrf.models import DixonColes
from pyrf.core import GoalGrid
surface = AsianHandicap(line=QuotedLine(value=-0.5))
model = DixonColes(lambda_home=1.8, lambda_away=1.2, rho=-0.10)
grid = GoalGrid.default()
# Payoff grid: +1 / 0 / -1 for each scoreline
payoffs = surface.grid_payoff(grid)
# Model-implied fair odds
implied = surface.implied_odds(model, grid)
Total Goals (Over/Under)¶
from pyrf.payoffs import TotalGoals
surface = TotalGoals(line=QuotedLine(value=2.5))
implied = surface.implied_odds(model, grid)
Quarter-Line Blending¶
Quarter lines (e.g., 2.25, 2.75) are split into two adjacent half lines and averaged. This matches the industry convention where a quarter-line bet is effectively half-stake on each neighbouring half line.
surface = TotalGoals(line=QuotedLine(value=2.75))
# Internally: 50% on 2.5, 50% on 3.0
From Payoffs to Implied Odds¶
The full pipeline:
# Get probabilities for each side
probs = surface.implied_prob(model, grid)
# Convert to a fair Quote
quote = surface.implied_odds(model, grid)
API Reference¶
See the full API Reference.