Unreleased changes
Merged to main since 0.1.5 and not yet released. Released versions are on the Changelog.
Unreleased
Added
- CFB / NFL: the advanced box's team rows carry
yards_per_dropback, sack-inclusive yards per dropback:(pass_yards + sack_yards) / passes, over the same dropbacks asyards_per_pass, which is unchanged and still counts a sack as 0 yards. It is the basis of SDV'syardsdropbackpercentiles, so Game on Paper's Binion box can rank the number it shows against them. Theespn_{cfb,nfl}_adv_team(and CFBadv_team_gamelog) releases pick it up on their next rebuild. (#740) - CFB / NFL: the advanced box's turnover rows carry
passes_defended, the opponent's ESPN box passes defended against the team's throws (CFB addsInt; ESPN's college PD excludes it), null where the box has none. (#737) - CFB CBS ids: the CBS scoreboard resolver reads FCS and postseason pages for the id map, a new
offline
_match_cbs_cardjoins a season's stored CBS cards to ESPN games (either home/away order, within three days), and the ESPN -> CBS team map gains five FCS schools (325 teams). (#815) - Cricket:
cricket_win_probabilityselects the ODI fielding-restriction regime from the match date (cricket_match_statenow carriesmatch_date;cricket_model_constants.ODI_REGIMES/cricket_regime: pre-2005, 2005 powerplays, 2011 window, 2012 two new balls, 2015+) and applies a regime whole -- its own resource grid andREGIME_CONSTANTSpar/sigma -- or falls back to the pooled 2002-2026 fit (a grid with fewer than 100 cells of 30+ states, or no fitted constants: the 13-month 2011 window). Output gainsregime. - Crosswalk history harvest: private
sportsdataverse._crosswalk_historycaptures Fox, Yahoo and CBS raw game listings and per-game box payloads into the*-alt-rawrepos: resumable, atomic, season-checked, and paced byXWALK_RPS/XWALK_<PROVIDER>_RPSonly; a 403 or 429 stops the run. (#805) - Czech Extraliga: 9
elh_*wrappers insportsdataverse.hockey.elh(play-by-play, shots, events, scoreboard), pluselh_game_ids. (#826) - eSports hokejovyzapis: 41 wrappers over the DEL (12), ICE Hockey League (12), EIHL (9) and
Metal Ligaen (8) feeds, in
sportsdataverse.hockey.{del_,icehl,eihl,metal}. (#826) - Hockey:
sportsdataverse.hockey.sihfwraps the keyless Swiss Ice Hockey Federation statistics API (data.sihf.ch), covering every SIHF league (National League, Swiss League, MyHockey League, the amateur, junior and women's leagues). There are elevensihf_*wrappers. Four return season tables:sihf_results,sihf_standings,sihf_player_statsandsihf_goalie_stats.sihf_phaseslists thephase_idvalues those four take for a league and season (the ids differ by league, season and table), with each phase's name and game count. Six read one game:sihf_pbp(goals, penalties, goaltender changes, revoked goals and shootout attempts),sihf_game_info,sihf_game_player_stats,sihf_game_goalie_stats,sihf_game_team_statsandsihf_game_lineups. SIHF answers an unknown season, league or phase with another one (Season=1890returns the current season), and only the body's filter echo shows it. The runtime compares that echo with the request and raisesNoDataErrorwhen they differ, so a wrong season is never returned under the requested label.sihf_standingscounts every game by default (venue="All"; asked nothing, SIHF answers the away-games table), and a table body with fewer rows than it announces raisesAssetFetchError. - HockeyAllsvenskan: 11
ha_*wrappers insportsdataverse.hockey.ha(schedule, play-by-play, standings, skater/goalie/team stats, leaders, players). (#826) - KHL: 23 wrappers in
sportsdataverse.hockey.khl: 14khl_*over the khl.ru REST and 9khl_webcaster_*over the webcaster API. (#826) - Ligue Magnus: 11
magnus_*wrappers insportsdataverse.hockey.magnus(competitions, schedule, standings, game sheet, play-by-play, lineups, shootout). (#826) - Liiga: 23
liiga_*wrappers insportsdataverse.hockey.liiga(schedule, box scores, shot map, standings, team and player stats). (#826) - MLB:
load_mlb_schedule(seasons)reads themlb_schedulesrelease (statsapi schedule, every game type, 1988+). - MLB:
load_mlb_statcast(seasons)reads themlb_statcastrelease (Baseball Savant pitch-level data, one parquet per season, 2015+; spring training and exhibition pitches included). Theon_1b/on_2b/on_3brunner ids are published as floats and cast to Int64 at the loader boundary. - National League: 17
nl_*wrappers insportsdataverse.hockey.nl(games, box scores, shots with xG, standings, player and team stats). (#826) - NBA / WNBA / MBB / WBB crosswalks:
{nba,wnba,mbb,wbb}_schedule_crosswalk(fox=True)fillsfox_game_id(and the NBA/WNBAfox_home_team_id/fox_away_team_id) from Fox's per-date scoreboard, matched on US-Eastern date and teams in either home/away order (a late West-coast tip ESPN files at 23:59 ET matches Fox's 00:00 ET a day apart);nba_crosswalks_from_archive/wnba_crosswalks_from_archive(fox_games=True)fill them for any season Fox serves.yahoo=Trueon the WNBA / MBB / WBB team and schedule crosswalks fillsyahoo_team_id(Yahoo's listing joined to ESPN by full name, short name, then nickname where the school names agree; unmatched Yahoo teams are logged) andyahoo_game_id={lg}.g.{YYYYMMDD ET}{home Yahoo id}, checked against the ids Yahoo lists so a neutral-site game takes Yahoo's home side. Both legs are opt-in and fail-soft: any Fox or Yahoo failure logs a warning and leaves the columns null. - NBA / WNBA crosswalks:
nba_crosswalks_from_archive/wnba_crosswalks_from_archivetakefox=True:fox_team_idby team name for any season, and the Fox player columns for the current season only (Fox rosters are today's). A failed Fox fetch warns and leaves them null. (#786) - NBA / WNBA:
nba_crosswalks_from_archive()/wnba_crosswalks_from_archive()build a past season's team, schedule and player crosswalks offline from the ESPN schedule and game-roster parquet plus the local stats box-score archive; the live builders only reach the current season. - NBA:
load_nba_stats_draft(seasons)reads thenba_stats_draftrelease;seasonsis the draft year. (#780) - NBA: loaders for the multi-file
nba_statsreleases:load_nba_stats_synergy,_hustle_player/_team,_matchups/_matchups_rollupand five_draft_combine_*tables. Each unions a season's files, stampsseason_type/per_modefrom the file name where rows lack them, and takes START-yearseasons. (#780) - NBA: the team and schedule crosswalks now compute
yahoo_team_id(nba.t.{espn id}) andyahoo_game_id(nba.g.{YYYYMMDD ET}{home id}) from 2014 on, where they were null. - NCAA:
scrape.ncaa.espn_player_xwalkmaps NCAA roster player ids to ESPN athlete ids per (season, ESPN team) for MBB, WBB and MFB, in four tiers that leave ties unmatched; the-rawrepos run it as stage 07. (#813) - SHL: 27
shl_*wrappers insportsdataverse.hockey.shl, plusshl_ssgt_uuidandshl_player_crosswalk. (#826) - SIHF: 22 more
sihf_*table wrappers (team, skater and goalie goals, shots, special teams, penalties, shootouts, faceoffs, time on ice, attendance), 33 in the family. (#826) - VHL: 13
vhl_*wrappers insportsdataverse.hockey.vhl(schedule, game report, play-by-play, standings, skater/goalie stats, players, rosters), plusvhl_tn. (#826) - WNBA crosswalks:
wnba_crosswalks_from_archive(..., yahoo=True)fillsyahoo_team_*andyahoo_game_idfor a past season through the live builders' Yahoo code; a failed Yahoo fetch leaves the columns null with a warning. (#803) _crosswalk_alt.match_season(known_teams=)takes fixed ESPN -> provider team pairs, andknown_teams("cbs", "cfb")serves the CFB CBS resolver's static map. Date co-occurrence cannot separate teams that share every game date: an FCS team with one FBS opponent, or any team early in a season. With the map, CBS CFB games match 99% of ESPN's schedule in most seasons (2026 so far: 101 to 445 of 448), and matched players rise from about 7,500 to 10,000-12,300 a season._crosswalk_alt.with_alt_game_legs()/fill_game_legs()fill a basketball schedule crosswalk's Fox game and team ids (and any null Yahoo game id) from the parsed*-alt-datahistory, only where the game id is null. On the published NBA crosswalks it fills 1,260 of 1,379 games for 2002 and 1,326 of 1,405 for 2025; the rest are preseason and All-Star games, which Fox does not list.nba_crosswalks_from_archive()/wnba_crosswalks_from_archive()takealt_root=: the*-alt-datacheckout whose parsed Fox / Yahoo history fills the player crosswalk'sfox_athlete_id/fox_playerandyahoo_player_id/yahoo_player_nameoffline, only where they are null. The new privatesportsdataverse._crosswalk_altparses the stored Fox / Yahoo / CBS payloads into per-seasongamesandgame_rostersparquet (python -m sportsdataverse._crosswalk_alt) and matches them to ESPN: teams by (date, side) co-occurrence, games on (US-Eastern date, team pair), players inside each game and team, voted across the season.ncaa_wbb_shot_locationstakesseason=, resolved throughwbb_period_model(halves through 2014-15, quarters from 2015-16) instead of binding quarters unconditionally; the default stays quarters because stats.ncaa.org shot locations only exist from 2019. (sdv-internal-refsrules/wbb.yaml#wbb-2016-four-quarters)parse_soccer_scoreboard(everyespn_<league>_scoreboard) carries the event'sseason_typeandseason_slug, and both it and the summaryheaderframe carry a derivedtournamentcolumn ("apertura"/"clausura", null for single-tournament leagues) so Liga MX's two competitions per ESPN season id can be split. (sdv-internal-refsrules/ligamx.yaml#ligamx-1996-two-short-tournaments-per-season)sportsdataverse.nba.nba_game_page: per-play in-game win probability with deltas and an overtime regime, the pregame prior from the spread, shot coordinates in the court frame, team four factors / ratings / pace, and player TS% / usage (NBA 48-minute and WNBA 40-minute regulation vialeague_id; only"00"and"10"are scored, anything else raisesValueError), for the Game on Paper NBA game page and the sdv-db nightly stage. Team turnovers repair ESPN's duplicated pre-2013 team turnover (team_turnovers == turnovers,total_turnovers == 2 * turnovers) and its null 2018total_turnovers, and the win probability settles to 1.0 / 0.0 on the "End Game" / "End Period" row of a decided game from the 4th period on. A null score on a play is carried forward before scoring, andgame_page_framesreturns the rate frames with their documented columns (zero rows) before both team box rows exist.- NFL Fox event ids resolve through
sportsdataverse.nfl.fox_pbp.game_id._resolve_fox_game_id, the Fox twin of the CBS week-scoreboard resolver (same arguments, light import), so sdv-db's nightly id map can fillfox_event_id; the football id map's team table now carriesfox_team_id.
Changed
- CFB validation: the box-score parity harness grades penalties (accepted fouls, committing team), fumbles lost (offense and defense) and net passing (total minus rushing) the way ESPN counts them, and adds a player-level check and a per-game integrity screen. (#764)
- CFB: the team summaries, percentiles, passing, receiving and advanced-box column descriptions match the republished definitions: run-stuff and opportunity rates over rushes, per-drive drive metrics, passer success over dropbacks, per-target receiving rates null for 2021-2024. (#741)
- MBB/WBB:
ncaa_espn_team_crosswalk(league=)reads the{mbb,wbb}_crosswalksportsdataverse-data release (built weekly by sdv-reference-data), so a new season no longer waits for an sdv-py release; it warns and falls back to the bundled CSV when the release cannot be read. (#770) - MBB:
load_mbb_player_crosswalk()documentskp_player_id, the KenPom player id hoopR-mbb-data now publishes afteryahoo_player_name(18 columns), andkp_game_idonload_mbb_schedule_crosswalk()is described as filled. The livembb_player_crosswalk()builder stays at 17 columns. (#787) - MLB:
fit_zone_model(the umpire-zone and catcher-framing called-strike logistic) excludes 2026+ pitches with aUserWarning-- Savant reports their location at the middle of the plate against the ABS zone and the calls are challengeable -- andmlb_umpire_called_strike_prob/mlb_umpire_bias/mlb_catcher_framingcarry anabs_eraflag (per-umpire and per-catcher rows split by era). - Possession cache:
nba_season_compile.PIPELINE_VERSIONis 5, so per-game caches keyed by it (compile_nba_season, and WNBA builders that import_game_cache_key) recompile once. (#818) - Spring football:
enrich_spring_football_pbpthreads the league-seasontouchback_yardlineandep_point_valuesfromget_sf_constantsintoenrich_nfl_pbp(new keyword-onlyleague=,touchback_yardline=,ep_point_values=; NFL defaults unchanged), so XFL / UFL kickoffs are scored from their own touchback spot. - Tests: warnings are errors. A test asserts an expected warning with
pytest.warns(..., match=...)or filters an incidental one by exact message; live tests skip on a timeout or upstream 429/5xx, the live job runs on Ubuntu, and thetestsextra needs pytest >= 8.0. (#726) load_cfb_teams_crosswalk/load_cfb_schedule_crosswalkaccept 2013. Thecfb_crosswalkrelease now carries 2013 (Yahoo and Fox legs), which the old 2014 floor hid.
Deprecated
- NBA / WNBA:
load_nba_stats_{pbp,possessions,lineups}_v3and the fourload_wnba_stats_*shims (lineups,player_season_stats,standings,team_season_stats) now say they will be removed in 0.2.0; they named 0.1.0, which has shipped. A test fails if a removal version falls behind again. (#726)
Removed
- MBB / WBB: the NCAA <-> ESPN team-crosswalk builder
tools/crosswalk/is gone; sdv-reference-data (sdv_reference/crosswalks/) builds and publishes the{mbb,wbb}_crosswalkasset thatncaa_espn_team_crosswalk()reads first (#770). The bundled fallback copies stay. (#788)
Fixed
- CFB / NFL: the advanced box's
expected_turnoverstakes its pass term from ESPN's box passes defended, not from "broken up by" text whose coverage swings by season (2025 CFB weeks 1-8 vs 9-15: 0.68 vs 1.45 before, 1.26 vs 1.46 now); text stays the fallback where the box has no PD. (#737) - CFB play-by-play: a fumble recovered by a team written mixed-case ("recovered by AlbSt") or in parentheses ("recovered by Omar Jacobs (BGSU)") is charged to the right team; 2014-20 team fumbles lost now match ESPN's box in 97-98% of team-games, from 86-90%. (#767)
- CFB play-by-play: kneel-downs ("Kneel down by TEAM ... (team loss of 2)", "takes a knee") and rushes no yardage reader matched (2004-13 "rush up the middle for 21 yards", yardless vendor rows) carry rushing yards; 2025 team rushing yards match ESPN's box in 64% of team-games, from 46%. (#768)
- CFB play-by-play: pre-2014 extra-point rows ("Extra point by Dave Rayner (MSU) is good.", "Felipe
Macias extra point GOOD.") set
xp_attempt,xp_madeandxp_kicker_player_name; all 46,762 had none. (#771) - CFB play-by-play: pre-2014 penalties ("HAWAII penalty 15 yard personal foul accepted") are charged to the team named in the text; 2006-13 team penalties match ESPN's box in 72-83% of team-games, from 21-25%. (#769)
- CFB play-by-play: regex-fallback player names no longer carry the clause they ran into ("Tommylee Lewistackled b", "Logan Hall, clock:32", a spot read as a fumbler); garbled names fall below 0.3% in every role and era, from up to 21%. (#772)
- CFB:
cfb_rosters_crosswalk(providers=(..., "yahoo"))fillsyahoo_athlete_idfrom Yahoo's team roster, matched by name + jersey, then by a unique name; it read the ~200-player stat-leaders feed and found 0-2 per team. New optionalyahoo_team_idskips the Yahoo team lookup. (#762) - CFB:
get_go_wpreturns NaN for a 4th-down row with noyards_to_goalordistance, instead of a garbage go-for-it value from casting NaN to an integer; other plays are unchanged. (#726) - CFB: overtime win probability values the forced two-point try after a touchdown (the third
overtime on before 2021, the second from 2021;
cfb_wp_overtime.OT_TWO_POINT_FORCED_FROM) instead of a kicked extra point in every period;get_2pt_probsrecommends the try there withxp_wpnull. - CFB: scoring zero rows (QBR on a live game's opening drive,
predict_from_cardon an empty frame) no longer logs XGBoost's "Empty dataset" warning. (#726) - Crosswalks:
{mbb,wbb,nba,wnba}_player_crosswalk(season=)for a past season reads that season's ESPN player box scores; ESPN's team-roster endpoint ignores?season=, so past seasons shipped the current roster under their own label (MBB 2025, WBB 2014-2025). (#782) - ESPN rankings parsed to an empty frame.
espn_{cfb,mbb,wbb,mch,wch}_rankings()ran the Site v2 payload throughparse_items, which reads a Core v2itemslist; the polls sit in a top-levelrankingslist, so every league returned zero rows. A dedicatedparse_rankingsnow gives one row per ranked or vote-receiving team per poll (live 2026-10-08: cfb 208 rows over 5 polls, mbb 77, wbb 75, mch 35, wch 20), withpoll_id,season,season_type,week(the week within the season type, which ESPN's Core v2 rankings URL uses),rank(null on vote-receiving rows),previous_rank,points,first_place_votesand the team fields;team_idis a string. The college baseball and softball wrappers route through it too, but ESPN answers their rankings URL with a 404. (#732) - Hockey:
sihf_phasesgives a nullphase_namewhen a phase's name is missing, blank or not a string, like the other SIHF parsers; it gave""for a missing or blank name and the stringified value ("['x']") for a list or object. - HockeyTech derived coordinates put home-team events off the rink.
add_coord_transforms(every<league>_pbpandpwhl_pbp) flipped home events with a 0-200 x 0-85 mirror applied to centre-origin feet, so homex_coord_rightran 191 to 290 ft andy_coord_right49 to 125 ft (PWHL game 42), andy_coord_fixedapplied the y transform twice. The feed puts the home team's attack toward x = 0 in every period (320 PWHL games; sdv-internal-refs #50), and the columns are now rotations of the feet frame (#51):x_coord_fixed/y_coord_fixed= (-x, -y), home team shooting right;x_coord_right/y_coord_right= home (-x, -y), visitor (x, y);x_coord_vertical/y_coord_vertical= (-y_right, x_right). The right and vertical columns are null when an event's side is unknown (no team, as on faceoffs, or a null or empty home team id) instead of defaulting to the visitor's.shot_distance,shot_angleand xG are unchanged. The published PWHL play-by-play releases keep the old values until they are rebuilt. - HockeyTech empty-net goals from a team's own half were measured to the wrong net.
add_shot_distance_anglemeasures to the nearer net (89 - |x|), which per-event validation showed is right for own-half events with a goalie in net: they are near-net events whose coordinates the feed mirrored (own-half quality shots match ordinary ones at 10 / 24 / 35 ft). An own-half empty-net goal is a genuine long shot (27 in 320 PWHL games; median 126 ft, measured 59 ft). Empty-net goals (empty_net"1") now measure to the net their team attacks; every other event is unchanged (sdv-internal-refs #52).shot_distance,shot_angle,scoring_chanceand the xG features of those goals change. - HockeyTech schedules returned other seasons' games.
<league>_schedule(season=...)for the 19 HockeyTech league families, andpwhl_schedule, readmodulekit/scorebar. That view ignores theseason_idit is sent, returns games oldest-first and stops at its 10,000-row limit, soahl_schedule(season=2026)returned 10,000 AHL games from 1995 to 2012 and none from 2025-26; OHL and ECHL failed the same way, and PWHL returned every season's games. The schedule functions now readmodulekit/schedule&season_id=<id>, which the feed scopes to one season (live 2026-10-08: AHL 2025-26 = 1,152 games, OHL = 682, PWHL = 120, each in that season alone), andparse_schedule(..., season_id=)drops any row from another season (#727). Behaviour changes:- With neither
seasonnorseason_id, the schedule is the newest regular season, as in the other season-aware functions. It used to be the feed's whole window. game_statusnow reads the schedule view's strings:Final OTwhere scorebar saidFinal 1st OT, and the start time (7:00 pm EST) for an unplayed game.- A season's playoffs and preseason are separate HockeyTech season ids; pass
season_idfor them. - An empty reply, or a season filter that keeps nothing, is zero rows with the 12 columns.
- With neither
- MLB docs: the
pitchercolumn in theload_mlb_xera,load_mlb_stuff_plus,load_mlb_command_plus,mlb_statcast_search(+_minors/_wbc),as_of_splitandbip_trajectory_featuresreturns tables now reads "MLBAM player id of the pitcher" instead of the inherited "Whether the position is a pitcher". On the Statcast-search,as_of_splitandbip_trajectory_featurespages,home_score/away_scoreare the score before the pitch (not after the play) andplayer_namefollowsplayer_type(the batter by default). Onespn_mlb_schedule,home_score/away_scoreare now described as the ESPN scoreboard score rather than a per-play run total. - MLB:
pitch_featuresstandardizes velocity, spin, movement and release within pitcher AND season (game_year, else the year ofgame_date), so PITCHf/x speeds (2008-16) and Statcast out-of-hand speeds (2017+, about +0.5-1 mph) never share one mean. - NBA / WNBA crosswalks: the archive team and player crosswalks no longer carry All-Star and other exhibition sides (e.g. WNBA 2026 TEAM SPOON / TEAM COOP); their games stay in the schedule crosswalk. (#786)
- NBA:
logistic_fit_irlsno longer overflows on separable data, andnba_rapmfits a single possession without a divide-by-zero warning. (#726) - NFL:
get_go_wpon a full nflverse frame no longer raises pandasPerformanceWarnings; output is unchanged. (#726) - NFL: overtime
wp/vegas_wpnow follow the season's overtime rule format (model_vars.OVERTIME_FORMATS): sudden death, nflfastR's One_FG form with a per-gameDrive_Diff, or a both-teams-possess form (postseason 2022+, regular season 2025+) under which an opening-drive touchdown no longer ends the game; spring-football overtime gets null. - NFL: the kickoff-touchback spot is now the rule spot per season (
model_vars.touchback_yardline: 80 / 75 / 70 for 2024 / 65 from 2025) in the EP feature substitution, the overtime re-score and the ESPNyds_kickoff_return; nflfastR still scores 2024+ kickoffs at 75, so kickoff-rowepdiverges from nflverse there by design. - NHL:
load_nhl_game_rosters()accepts published roster seasons from 2010 instead of rejecting seasons before 2024. - NHL: twelve release loaders rejected seasons their releases publish:
load_nhl_game_info(),load_nhl_goalie_boxscores(),load_nhl_linescore(),load_nhl_penalties(),load_nhl_scoring(),load_nhl_scratches(),load_nhl_skater_boxscores()andload_nhl_three_stars()started at 2024, andload_nhl_officials(),load_nhl_shifts(),load_nhl_shootout()andload_nhl_shots_by_period()at 2025. Every NHL release publishes from 2010 (the 2009-10 season), and all of them now accept it.load_nhl_pbp_lite()reads the release's currentplay_by_play_lite_<season>files, now published for 2010-2027. The legacyplay_by_play_<season>_litefiles stopped at 2026, so the current season was missing. The current files hold every legacy column, plusgame_date. - sdv-docs index: stdlib and third-party objects a module re-exports (
typing.Any,xgboost.Booster,tqdm,functools.lru_cache, 14 in all) are no longer indexed as sdv-py functions. SDV partials and type aliases whose__module__isfunctoolsortypingstay indexed. - sdv-docs: the server opens an index whose path contains
?,#or%; such a path used to end the SQLite URI early and silently open a different, empty file. A corrupt or foreignSDV_DOCS_DBnow gets anindex unreadable: …answer instead of a raisedDatabaseError. - sdv-docs: when the
mcpimport fails,sdv-docsprints the import error after the install hint, so an installed but incompatiblemcpis visible. - WNBA / Summer League lineups: rotation lineups are timed on the league's own periods (WNBA 10-minute quarters, halves before 2006; Summer League 10-minute quarters), not NBA 12-minute ones; a malformed rotation returns an empty frame and every engine falls back to pbp lineups. (#818)
_crosswalk_altCBS parse skips a box score whoseplayerStatsis a list: CBS answers a few college football game ids with a basketball box (CFB 2017 and 2021), which used to stop the whole season's parse.cfb_schedule_crosswalkbuilds the same rows from the same upstream data. A Yahoo scoreboard week that answered HTTP 200 with a cut-off JSON body was skipped, so its Yahoo ids and Yahoo-only games came and went between nightly builds (1,565 vs 1,608 rows for 2026)._download_json(and the Yahoo Shangrila getter) now re-fetches a truncated JSON body up to twice, and a full-season build raisesCrosswalkSourceErroron any failed ESPN calendar, ESPN week or Yahoo week instead of skipping it.ncaa_wbb_game_pbp/ncaa_wbb_play_by_playbind the WBB period model for the game's era (halves through 2014-15, quarters from 2015-16) instead of quarters unconditionally; a pre-2016 game no longer parses to zero rows. Newseason=argument pins the era; without itinfer_wbb_period_modelreads it from the page's first-period clock. (sdv-internal-refsrules/wbb.yaml#wbb-2016-four-quarters)parse_soccer_summary(soespn_<league>_summaryfor every ESPN soccer league) warns (UserWarning, naming the event id) when a payload carries a match header butkey_events,commentaryandlineupsare all empty, instead of returning the zero-row frames silently. ESPN lists usa.nwsl 2014-2018 but ships no detail for those seasons. (sdv-internal-refsrules/nwsl.yaml#nwsl-2013-espn-season-coverage-start)- CFB pbp:
fumble_lost/fumble_recoveredread the recovering team from the text (a punt returner recovering his own fumble is no loss; a muffed punt the kicking team recovers is one), kickoff touchbacks come out to the 25 from 2012 (they switched only after 2013, inyds_kickoff_returnand the EP touchback yardline), andyds_fumble_returnreads the 2004-06 "returned for a N yard touchdown". - CFB pbp: pre-2014 onside recoveries (
Kickoff Return (Defense)) are typedKickoffbefore the kickoff possession flip, so they carrykickoff_play/kickoff_onsideand the right kicking / receiving team; andtd_playfollows a touchdown type that 2014+ scoring-summary text never spells out ("12 Yd Interception Return (X Kick)"). - Era-dependent behaviour catalogued in sdv-internal-refs
rules/is now honoured at the code sites it flagged: ESPN soccer summaries null the(0.0, 0.0)"no location" coordinate pairs and strip trailing spaces from names (rules/epl.yaml);cricket_match_statereads a DLS-reduced innings' revised over allocation from the score string instead of the format's full ball budget (rules/cricket.yaml#cricket-1999-duckworth-lewis);mlb_statcast_searchclamps a pre-2008-03-25 window to the tracking floor with a warning andget_baselineswarns when it falls back to the nearest committed season (rules/mlb.yaml);get_court(league_id, season=)returns the three-point geometry in force that season (NBA 22-ft arc 1994-97, WNBA 19'9" / 20'6.25" / FIBA eras);get_sf_constants(league, season=)resolves the UFL 2024 / 2025 / 2026, XFL and CFL rulesets; HockeyTechot_period_lengthcarries the sourced regular-season OT length for PWHL (300), ECHL and USHL (420) and BCHL (600). - NFL play-by-play
opportunity_runnow marks a carry that gained 4 or more yards; it was inverted (<= 4), so short runs counted as opportunities and the box'srushing_opportunity_rateran about 0.62 instead of about 0.46.opportunity_run,highlight_runandadj_rush_yardagenow gate onrush, as the CFB processor does, so rushing touchdowns and fumbled rushes are no longer dropped. - The archive crosswalks' team pairing (date and home/away co-occurrence) leaves a team unpaired when two candidates tie, instead of taking the lower id. A full season never ties; a slice of a few dates could pair the wrong franchises.
- The fourth-down surface's PAT make probability (
get_2pt_wp/get_2pt_probs,conv_1pt) scores the FG model at nflfastR's pre-2015 spot (yardline_100 = 3, the kick snapped from the 2) for seasons before 2015 instead of the modern 15 for every season; newPAT_YARDLINE_PRE_2015/PAT_YARDLINE_POST_2015/PAT_FIRST_SEASON_FROM_15constants innfl.model_vars. (sdv-internal-refsrules/nfl.yaml#nfl-2015-pat-snap-from-15)
Data
- Cricket: the win-probability artifacts are refit on Cricsheet male internationals 2002-2026 (3,581 T20I +
2,589 ODI): the surface is regime-keyed with per-cell support, the calibrator is fitted on the regime-aware raw
probabilities, pooled constants move to T20 149.5/42/33 and ODI 249.3/76/59, and both holdout fixtures carry
match_date. Holdout Brier 0.1898 -> 0.1882, max per-decile gap 0.0326 -> 0.0369 (gate 0.05). - NCAA 2026-27 MBB (365) and WBB (363) team ids added to the bundled
ncaa_teamids_{mbb,wbb}.csv, captured from stats.ncaa.org's Division I team list, and their 2026-27 rows to the bundled NCAA ↔ ESPN team crosswalks (every team matched; West Florida joins in the ASUN, New Orleans is now LSU New Orleans, Saint Francis left Division I).