Skip to content
JW
CompetitionCV award2024

MCM 2024 — Tennis Momentum

2024美赛C题论文与代码

A mathematical model of momentum in tennis, combining match-state simulation with logistic regression and ExtraTrees prediction.

MCM 2024 — Tennis Momentum project diagram

22p

MCM paper

MCM

competition model

2.3

largest event weight

01 / Overview

What this package actually contains.

The MCM 2024 paper models momentum in tennis as a state variable that changes after points, games, sets and specific events. The Python workflow scores each event, accumulates momentum over time and tests whether the resulting state improves match-outcome prediction.

Objectives

  • 01Define a measurable momentum score from observable match events.
  • 02Model when momentum shifts and which player benefits.
  • 03Predict point or match outcomes with the momentum state as a feature.

Competition narrative

Problem, model, result, paper.

The page foregrounds the modelling decision and result before implementation details.

Stage 01

Point-level data

Scores, sets, games, aces, errors and winners.

01

Stage 02

Momentum scoring

Weighted event contributions accumulated through the match.

02

Stage 03

Model features

Momentum series, scoring context and player state.

03

Stage 04

Prediction

Logistic regression and tree-based model candidates.

04

Stage 05

Evaluation

Accuracy, feature weights and match-flow visualisation.

05

02 / Package highlights

What this work demonstrates.

  • Models shifts in match momentum using player, court and strategy variables.
  • Uses Lazypredict for model screening and ExtraTreesRegressor for prediction.
  • Connects stochastic simulation with interpretable sports analytics.

03 / Model

The modelling choices behind the result.

01

Momentum as an engineered state

Each point updates the momentum score for the two players. Set, game and point advantages receive smaller weights, while winners, unforced errors and net points produce larger shifts. The score is accumulated across the match and clipped at zero to avoid an unbounded negative state.

  • Event weights were chosen to distinguish scoreboard progress from shot-level quality.
  • Accumulation gives the model a short memory of recent match flow.
  • The momentum series can be plotted to identify swing points.
02

Predictive validation

The momentum variables were passed into logistic regression together with match context. The paper also explored model screening and ExtraTrees prediction, allowing the team to compare a transparent baseline with a nonlinear ensemble.

04 / Key code

Selected modelling code.

Only verified source excerpts and pseudocode taken from the project papers are shown.

Verified project codePython

Momentum update rules

Original Python excerpt showing weighted point-event updates and accumulation.

for index, row in match_data.iterrows():
    if row['p1_sets'] > row['p2_sets']:
        match_data.at[index, 'momentum_1'] += 0.0065
    elif row['p2_sets'] > row['p1_sets']:
        match_data.at[index, 'momentum_2'] += 0.0065

    if row['p1_games'] > row['p2_games']:
        match_data.at[index, 'momentum_1'] += 0.2177
    elif row['p2_games'] > row['p1_games']:
        match_data.at[index, 'momentum_2'] += 0.2177

    if row['p1_ace'] > row['p2_ace']:
        match_data.at[index, 'momentum_1'] += 0.4
    elif row['p2_ace'] > row['p1_ace']:
        match_data.at[index, 'momentum_2'] += 0.4

    if row['p1_winner'] > row['p2_winner']:
        match_data.at[index, 'momentum_1'] += 2.3
    elif row['p2_winner'] > row['p1_winner']:
        match_data.at[index, 'momentum_2'] += 2.3

    if index > 0:
        match_data.at[index, 'momentum_1'] += (
            match_data.at[index - 1, 'momentum_1']
        )
        match_data.at[index, 'momentum_2'] += (
            match_data.at[index - 1, 'momentum_2']
        )
Verified project codePython

Logistic regression baseline

Original Python excerpt for scaling momentum features and fitting a classifier.

features = ['momentum_1', 'momentum_2']
target = 'point_victor'

X = data[features]
y = data[target]

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

X_train, X_test, y_train, y_test = train_test_split(
    X_scaled, y, test_size=0.2, random_state=42
)

model = LogisticRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
print('Accuracy:', accuracy_score(y_test, y_pred))
print('Feature weights:', model.coef_)

Reproducibility notes

  • The score is interpretable because each input event has an explicit contribution.
  • Accumulation converts a point-level table into a time-series state.
  • The workflow supports both plotting and predictive modelling.

Limitations / next steps

  • Hand-set momentum weights require validation against a larger set of matches.
  • Point-level prediction is noisy and should be evaluated with player-level and match-level splits.

05 / Downloads

Files in this folder.

Open the original report, presentation or source archive. PDF cover pages with private details were removed.

PDF

MCM 2024 paper

EN · 22 pages · 1.4 MB

22-page competition paper.

Open file
ZIP

Python source archive

Mixed · 14 KB

Curated Python scripts behind the competition model.

Download ZIP