Skip to main content

Scoring and salary calculation for GridRival fantasy F1

Project description

gr_analytics

Tests

Python package for scoring and salary calculation in GridRival fantasy F1.

Installation

pip install -e .

Quick Start

import pandas as pd
from gr_analytics import score_event, score_my_team, optimal_lineup

# Load your race scenario
scenario = pd.read_csv("my_race.csv")

# Score the event (defaults to the latest round in driver_data)
result = score_event(scenario)

# Or score a specific round
result = score_event(scenario, round=1)

# Score your specific team selection
points, salary_change = score_my_team(
    scenario,
    drivers=["RUS", "ANT", "LEC", "BEA", "LIN"],
    team="MER",
    star_driver="BEA",
    round=1,
)

# Find the optimal lineup (maximise points, £100M budget)
lineup = optimal_lineup(result)

# With locked-in drivers (already under contract, cost nothing)
# and a budget for the remaining open spots
lineup = optimal_lineup(
    result,
    locked_in=["HAM", "LEC"],   # driver_abbr or team code
    optimize_for="points",       # or "salary_change"
    budget=60.0,                 # £M available for non-locked picks
)

Scenario Format

The scenario DataFrame must have one row per driver with these columns:

Column Type Description
driver_abbr str Driver abbreviation (e.g. "RUS", "VER")
qualifying_position int Official qualifying position (1–22)
completed_qualifying int 1 if driver completed qualifying, 0 if DNQ
finishing_position int Race finishing position (1–22)
completed_pct float or "DNS" Fraction of race completed (0.0–1.0), or "DNS" if driver did not start

DNQ drivers get 0 qualifying points but their qualifying_position is still used to calculate overtake points.

DNS drivers (completed_pct="DNS") get 0 for all race-related points (race, overtake, improvement, completion, teammate).

DNF drivers (e.g. completed_pct=0.3) receive partial completion bonus points and their finishing position is used normally.

Qualifying and race positions must each form a complete sequence 1..n with no duplicates or gaps.

Output

score_event returns a DataFrame with all drivers and constructors, with scoring columns appended:

Drivers:

  • pts_qualifying, pts_race, pts_overtake, pts_improvement, pts_completion, pts_teammate
  • points_earned — total fantasy points
  • salary_after_event, salary_change

Constructors:

  • pts_qualifying, pts_race (sum across both drivers, using constructor-specific tables)
  • points_earned, salary_after_event, salary_change

Scoring Rules

All scoring follows GridRival's rules for Grand Prix events (no sprint races).

Drivers

Bonus Rule
Qualifying P1=50, P2=48, … P22=8 (step −2)
Race finish P1=100, P2=97, … P22=37 (step −3)
Overtake (qualifying pos − finishing pos) × 3, min 0
Improvement Points for finishing ahead of 8-race average (2 pos=2 pts, 3=4, 4=6, 5=9, 6=12, 7=16, 8=20, 9=25, 10+=30)
Completion 3 pts each at 25%, 50%, 75%, 90% of race distance (max 12)
Teammate Points for beating teammate by margin: ≥1 pos=2 pts, ≥4=5, ≥8=8, ≥13=12

Constructors

Constructor qualifying and race points use separate tables (P1=30/60, step −1/−2 per driver) summed across both drivers. No overtake, improvement, completion, or teammate bonuses.

Salary Adjustment

After each race, salaries adjust based on the gap between a driver's actual starting salary and the default salary for their points-ranking position:

adjustment = truncate(variation / 4, to nearest £100K)

Capped at ±£2M for drivers, ±£3M for constructors.

Driver Data

Bundled driver data (gr_analytics/data/driver_data.csv) contains starting salaries and 8-race averages by round:

  • round=0 — pre-season (before Australia 2026)
  • round=1 — post-Australia 2026

Lineup Optimisation

optimal_lineup uses mixed-integer linear programming (via scipy.optimize.milp) to find the best 5-driver + 1-constructor lineup within a salary budget.

lineup = optimal_lineup(
    scored,                  # DataFrame from score_event()
    locked_in=None,          # list of driver_abbr / team codes already on your team
    optimize_for="points",   # "points" or "salary_change"
    budget=100.0,            # £M for non-locked picks
)
  • locked_in picks are included free (already under contract) and don't count against the budget.
  • optimize_for="points" selects the optimal star driver (who earns double points) across all candidates.
  • optimize_for="salary_change" maximises total salary gain for the next race's team valuation.

The returned DataFrame has a star column (1 = starred driver, points mode only).

Running Tests

python -m pytest tests/test_scoring.py -v

Tests include hand-calculated unit tests for all scoring components and a full integration test against real GridRival results from Australia 2026 (22 drivers + 3 constructors).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gr_analytics-0.2.1.tar.gz (17.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gr_analytics-0.2.1-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file gr_analytics-0.2.1.tar.gz.

File metadata

  • Download URL: gr_analytics-0.2.1.tar.gz
  • Upload date:
  • Size: 17.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for gr_analytics-0.2.1.tar.gz
Algorithm Hash digest
SHA256 f93d7774a8e3a20be0af72660f3c3ef8ffb67e0f75f9ebbf3eb6495cf15e17f6
MD5 4a5b6a3fd07c3f96a6aec740cb3eb0c4
BLAKE2b-256 e73c090c4705bcafc3a4249c3f80d819e99a2081f4c6297ab2c80cff31090e0f

See more details on using hashes here.

File details

Details for the file gr_analytics-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: gr_analytics-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for gr_analytics-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8a8145dfeea2ae29e11526d1293da097a294206a3342d357513802be758fb757
MD5 3d45ac63ed821c86a3e52392d1420401
BLAKE2b-256 8a4ec849a0356cdd75cb4df1abb67dc75d7ad6535f8214f92291ed8590363d86

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page