← FastballAPICONTENT HISTORY
WHAT CHANGED
Update to FastballAPI
Snapshot Oct 30, 2026 · 00:06 UTC · version 1.0.0
Collection source: downloaded plugin package.
First saved snapshot
No earlier snapshot is available to establish a change.
Save FastballAPI and check future changes in Following.
Up to 10 plugins free · no card required.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Computes Pythagorean and Pythagenpat expected records from runs scored and allowed, measures how far a team's actual record is from it (luck), and projects regression for MLB and college baseball. Use when the user asks about Pythagorean record, expected wins, run differential, who got lucky or unlucky, one-run-game luck, or whether a team is as good as its record. Do not use for general standings and rankings: see team-analysis. Do not use for single-game prediction: see game-preview. Do not use to validate a model: see walk-forward-validation.",
"included_files": [],
"name": "pythagorean-record",
"skill_md_contents": "---\nname: pythagorean-record\ndescription: \"Computes Pythagorean and Pythagenpat expected records from runs scored and allowed, measures how far a team's actual record is from it (luck), and projects regression for MLB and college baseball. Use when the user asks about Pythagorean record, expected wins, run differential, who got lucky or unlucky, one-run-game luck, or whether a team is as good as its record. Do not use for general standings and rankings: see team-analysis. Do not use for single-game prediction: see game-preview. Do not use to validate a model: see walk-forward-validation.\"\nmetadata:\n version: 1.0.0\n author: FastballAPI\n---\n\n# Pythagorean Record\n\n> **Default data tool:** FastballAPI (`fastballapi-tool`).\n> `get_standings` (2 credits) already returns `runs_scored`, `runs_allowed`, `run_differential` and `pythagorean_win_pct` for every team. `get_team_stats` (5) adds the process behind the runs.\n\nYou separate what a team did from what its scoring says it should have done. The gap is mostly luck in one-run games and sequencing, and it regresses.\n\n## When to Use\n\n- \"Who was lucky in 2025?\"\n- \"Is Toronto really a 94-win team?\"\n- \"What does run differential say about the Brewers?\"\n- Expected wins at midseason, and what to expect the rest of the way\n- Fitting a Pythagorean exponent for college baseball or another run environment\n\n## When NOT to Use\n\n- Standings, rankings, form: `team-analysis`\n- A single game's price: `game-preview`, `odds-explorer`\n- Testing a prediction model: `walk-forward-validation`\n\n## Commands Available\n\n| Command | What it does | Credits |\n|---------|--------------|---------|\n| `get_standings` | W-L, home/away, last 10, `runs_scored`, `runs_allowed`, `run_differential`, `win_pct`, `pythagorean_win_pct` | 2 |\n| `get_team_stats` | Runs per game for and against, team batting and opponents' batting | 5 |\n| `get_games` | Final scores for one-run-game splits | 2 |\n| `get_ratings` | Elo, a cross-check that accounts for opponent strength | 2 |\n\nAll accept `league` (`mlb`, `ncaabase`) and `season`.\n\n## Commands That Do NOT Exist\n\n| Not available | Use instead |\n|---------------|-------------|\n| `get_expected_record`, `get_pythag` | Read `pythagorean_win_pct` from `get_standings`, or compute below |\n| `get_base_runs`, `get_xwins` | Not available. Compute BaseRuns yourself from `get_team_stats` if needed |\n| `get_one_run_record` | `get_games` for the team, then count games decided by one run |\n| `get_clutch` | Not available. See `run-value-analysis` for RISP splits |\n\n## The Formulas\n\n**Classic Pythagorean** (James): expected win pct = RS^x / (RS^x + RA^x).\n\n**Exponent.** The classic value is 2. A better fit for modern MLB is about 1.83. FastballAPI's own `pythagorean_win_pct` matches 1.83: checked against four 2025 teams (MIL .608, NYY .597, TOR .546, PHI .583), the exponent 1.83 reproduces the API value to three decimals each time, and the exponent 2 does not. Use 1.83 for MLB unless you fit your own.\n\n**Pythagenpat** (Smyth/Patriot): exponent x = ((RS + RA) / G)^0.287, so the exponent rises with run environment. For 2025 MIL, x = 1.87 and the result is within a fraction of a win of the 1.83 version. It matters more for college and other high-scoring environments.\n\n```python\ndef pythag(rs, ra, exp=1.83):\n return rs**exp / (rs**exp + ra**exp)\n\ndef pythagenpat(rs, ra, g):\n x = ((rs + ra) / g) ** 0.287\n return rs**x / (rs**x + ra**x)\n```\n\n**Rule of thumb:** about 10 runs of differential is about 1 win in MLB. Check it against your own data rather than quoting it blindly.\n\n## How It Works\n\n**Step 1: Pull standings.** `get_standings` with `season`.\n\n```json\nPOST /v1/get_standings\n{\"season\": 2025}\n```\n\nReal rows (2025, trimmed):\n\n```json\n{\"data\": {\"season\": 2025, \"standings\": [\n {\"abbrev\": \"MIL\", \"wins\": 97, \"losses\": 65, \"runs_scored\": 806, \"runs_allowed\": 634, \"run_differential\": 172, \"win_pct\": 0.599, \"pythagorean_win_pct\": 0.608},\n {\"abbrev\": \"TOR\", \"wins\": 94, \"losses\": 68, \"runs_scored\": 798, \"runs_allowed\": 721, \"run_differential\": 77, \"win_pct\": 0.58, \"pythagorean_win_pct\": 0.546},\n {\"abbrev\": \"NYY\", \"wins\": 94, \"losses\": 68, \"runs_scored\": 849, \"runs_allowed\": 685, \"run_differential\": 164, \"win_pct\": 0.58, \"pythagorean_win_pct\": 0.597}]}}\n```\n\n**Step 2: Expected wins and luck.**\n\n| Team | Wins | Expected (G x Pythag) | Luck (wins minus expected) |\n|------|------|------------------------|----------------------------|\n| TOR | 94 | 88.5 | +5.5 |\n| PHI | 96 | 94.4 | +1.6 |\n| MIL | 97 | 98.5 | -1.5 |\n| NYY | 94 | 96.7 | -2.7 |\n\nToronto and New York finished with the same 94-68 record on very different scoring: +77 vs +164. A team that outperforms its run differential by 5 wins is a candidate for regression, with caveats below. Sort the whole league by `luck` to find the outliers.\n\n```python\nrows = get_standings(season=2025)[\"data\"][\"standings\"]\nfor r in rows:\n g = r[\"wins\"] + r[\"losses\"]\n r[\"expected_wins\"] = g * r[\"pythagorean_win_pct\"]\n r[\"luck\"] = r[\"wins\"] - r[\"expected_wins\"]\nrows.sort(key=lambda r: r[\"luck\"])\n```\n\n**Step 3: Explain the gap before predicting regression.** Over-performance of Pythagorean is not all luck. Ranked by how much of it is repeatable:\n\n| Source of gap | Repeatable? |\n|---------------|-------------|\n| One-run-game record | Mostly luck (hold near .500 across teams) |\n| Sequencing: hits clustered with runners on | Mostly luck |\n| Elite closer plus bullpen used to win close games | Partly skill |\n| Blowout wins and losses (runs wasted) | Neutral on average |\n| Mid-season trades changing talent | Not luck; a timing issue (use rolling windows) |\n\nCheck the one-run record with `get_games`: count finals where the absolute run difference is 1 and split by wins. A team that went 30-15 in one-run games has a story; a team at 22-23 does not.\n\n**Step 4: Regression.** Do not publish a forecast from rules of thumb alone. Test it:\n\n1. Take `win_pct` and `pythagorean_win_pct` for season N and the actual `win_pct` for season N+1, for every team in 10 or more seasons (`get_standings`, 2 credits per season).\n2. Fit next-year win pct on both predictors, with teams as the unit.\n3. If `pythagorean_win_pct` carries more weight than `win_pct`, run differential is the better predictor and the luck term does regress. Report the coefficients and the sample size. This is a walk-forward question: fit on seasons up to N-1, test on N. See `walk-forward-validation`.\n\nRosters change between seasons, so this test mixes luck regression with talent turnover. Do not call all of the gap \"luck\".\n\n**Step 5: Fit an exponent for another environment** (college baseball, or another era):\n\n```python\nimport numpy as np\nx = np.log([r[\"runs_scored\"] / r[\"runs_allowed\"] for r in rows])\ny = np.log([r[\"wins\"] / max(r[\"losses\"], 1) for r in rows])\nexponent = (x @ y) / (x @ x) # least squares through the origin\n```\n\nUse only teams with a meaningful number of games.\n\n## College Baseball\n\n`league: \"ncaabase\"`. The standings list every team ESPN carries, in win-pct order, including teams with a few games. A 3-0 team with 31 runs for and 10 against has a Pythagorean of .888: meaningless at that sample. Filter on games played (for example at least 30) before sorting. ESPN does not carry every Division I game, so runs and records can be partial. Fit the exponent on the filtered set, since college run environments are higher than MLB.\n\n## Sample Size Reality\n\nA 162-game record has a standard error near 6 wins from luck alone (sqrt(162 x 0.25) = 6.4). Pythagorean cuts the noise but not to zero. A one-win gap is nothing. A five-win gap in a full season is notable, not decisive. Before the All-Star break, 90 games means a standard error near 4.7 wins.\n\n## Credit Usage\n\n| Operation | Credits |\n|-----------|---------|\n| One season's league table | 2 |\n| Ten seasons for a regression | 20 |\n| One-run-game split for one team | 2 |\n| Process stats for all teams | 5 |\n\n## Anti-patterns\n\n| Mistake | Why it is wrong | Do This |\n|---------|-----------------|---------|\n| Calling every gap \"luck\" | Bullpens and trades are real | Split by source |\n| Using exponent 2 and comparing to the API | Values will differ by a few thousandths | Use 1.83 or state yours |\n| Projecting a team's next win total as its Pythagorean | Rosters change | Fit and test, then say the error |\n| Ranking college teams on a few games | Tiny samples | Filter on games |\n| Using full-season Pythagorean for a playoff series | Playoff opponents, rotations differ | Use as context only |\n| Ignoring postseason in run totals | Standings are regular-season; `get_games` mixes both | Filter `season_type` |\n\n## Output Format\n\n```\n2025 regular season, luck vs run differential\nMost over expected record: TOR 94-68 vs 88.5 expected (+5.5), RD +77\nMost under: NYY 94-68 vs 96.7 expected (-2.7), RD +164\nExponent: 1.83 (matches pythagorean_win_pct)\nRead: Toronto's record is ahead of its scoring; New York's is behind it.\nCaveat: one season; luck is not a forecast until tested (see walk-forward-validation).\n```\n\n## What to Do Next\n\n| You found | Next | Skill |\n|-----------|------|-------|\n| Large gap | Check Elo and process stats | `team-analysis` |\n| Want to test regression | Temporal validation | `walk-forward-validation` |\n| Gap explained by clutch hitting | RISP run value | `run-value-analysis` |\n| Want to price a team's win total | Fair odds first | `odds-analysis` |\n"
}SHA-256 of public snapshot: 7bec7369d583221012eeb39727f373e145be236f162e184755e74a85240a8e78