athletevalue 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- athletevalue-0.1.0/.gitignore +19 -0
- athletevalue-0.1.0/.import_linter_cache/.gitignore +2 -0
- athletevalue-0.1.0/.import_linter_cache/489b52dc1b9aa1f85b757db7f7756cdd659e55c1.data.json +1 -0
- athletevalue-0.1.0/.import_linter_cache/4a4fd42e38b06ac4c9f49119ac6a1a382b9d81b9.data.json +1 -0
- athletevalue-0.1.0/.import_linter_cache/CACHEDIR.TAG +3 -0
- athletevalue-0.1.0/.import_linter_cache/athletevalue.meta.json +1 -0
- athletevalue-0.1.0/CHANGELOG.md +18 -0
- athletevalue-0.1.0/CITATION.cff +16 -0
- athletevalue-0.1.0/CLAUDE.md +14 -0
- athletevalue-0.1.0/CONTRIBUTING.md +51 -0
- athletevalue-0.1.0/DISCLAIMER.md +13 -0
- athletevalue-0.1.0/LICENSE +21 -0
- athletevalue-0.1.0/LICENSE-DATA +27 -0
- athletevalue-0.1.0/METHODOLOGY.md +185 -0
- athletevalue-0.1.0/PKG-INFO +204 -0
- athletevalue-0.1.0/README.md +171 -0
- athletevalue-0.1.0/docs/contributing.md +51 -0
- athletevalue-0.1.0/docs/index.md +171 -0
- athletevalue-0.1.0/docs/methodology.md +185 -0
- athletevalue-0.1.0/mkdocs.yml +8 -0
- athletevalue-0.1.0/pyproject.toml +180 -0
- athletevalue-0.1.0/src/athletevalue/__init__.py +5 -0
- athletevalue-0.1.0/src/athletevalue/api.py +113 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/audit.py +65 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/data/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/data/economics.toml +59 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/data/market.toml +132 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/data/mbb_impact.toml +134 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/data/mbb_wins.toml +65 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/models.py +126 -0
- athletevalue-0.1.0/src/athletevalue/assumptions/registry.py +86 -0
- athletevalue-0.1.0/src/athletevalue/cli/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/cli/main.py +175 -0
- athletevalue-0.1.0/src/athletevalue/constants.py +23 -0
- athletevalue-0.1.0/src/athletevalue/data/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/data/deal_registry/README.md +37 -0
- athletevalue-0.1.0/src/athletevalue/data/deal_registry/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/data/deal_registry/mbb_deals.csv +1 -0
- athletevalue-0.1.0/src/athletevalue/data/identity/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/data/identity/team_crosswalk.csv +376 -0
- athletevalue-0.1.0/src/athletevalue/economics/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/economics/panel.py +76 -0
- athletevalue-0.1.0/src/athletevalue/economics/program_value.py +79 -0
- athletevalue-0.1.0/src/athletevalue/economics/revenue.py +132 -0
- athletevalue-0.1.0/src/athletevalue/economics/tournament.py +79 -0
- athletevalue-0.1.0/src/athletevalue/frames/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/frames/columns.py +70 -0
- athletevalue-0.1.0/src/athletevalue/frames/games.py +194 -0
- athletevalue-0.1.0/src/athletevalue/frames/possessions.py +177 -0
- athletevalue-0.1.0/src/athletevalue/frames/team_possessions.py +46 -0
- athletevalue-0.1.0/src/athletevalue/identity/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/identity/crosswalk.py +17 -0
- athletevalue-0.1.0/src/athletevalue/identity/names.py +78 -0
- athletevalue-0.1.0/src/athletevalue/identity/resolve.py +74 -0
- athletevalue-0.1.0/src/athletevalue/impact/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/impact/cv.py +72 -0
- athletevalue-0.1.0/src/athletevalue/impact/design.py +183 -0
- athletevalue-0.1.0/src/athletevalue/impact/rapm.py +122 -0
- athletevalue-0.1.0/src/athletevalue/impact/reconstruct.py +50 -0
- athletevalue-0.1.0/src/athletevalue/impact/ridge.py +146 -0
- athletevalue-0.1.0/src/athletevalue/market/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/market/allocation.py +111 -0
- athletevalue-0.1.0/src/athletevalue/market/budget.py +64 -0
- athletevalue-0.1.0/src/athletevalue/market/registry.py +42 -0
- athletevalue-0.1.0/src/athletevalue/market/surplus.py +53 -0
- athletevalue-0.1.0/src/athletevalue/py.typed +0 -0
- athletevalue-0.1.0/src/athletevalue/schemas/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/schemas/estimate.py +75 -0
- athletevalue-0.1.0/src/athletevalue/schemas/evidence.py +64 -0
- athletevalue-0.1.0/src/athletevalue/schemas/hashing.py +16 -0
- athletevalue-0.1.0/src/athletevalue/schemas/identity.py +29 -0
- athletevalue-0.1.0/src/athletevalue/schemas/registry.py +65 -0
- athletevalue-0.1.0/src/athletevalue/schemas/source.py +82 -0
- athletevalue-0.1.0/src/athletevalue/sources/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/sources/cache.py +171 -0
- athletevalue-0.1.0/src/athletevalue/sources/eada.py +110 -0
- athletevalue-0.1.0/src/athletevalue/sources/sportsdataverse.py +74 -0
- athletevalue-0.1.0/src/athletevalue/sources/torvik.py +33 -0
- athletevalue-0.1.0/src/athletevalue/sources/user_csv.py +33 -0
- athletevalue-0.1.0/src/athletevalue/sports/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/sports/mbb/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/sports/mbb/economics_loaders.py +69 -0
- athletevalue-0.1.0/src/athletevalue/sports/mbb/loaders.py +26 -0
- athletevalue-0.1.0/src/athletevalue/uncertainty/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/uncertainty/draws.py +66 -0
- athletevalue-0.1.0/src/athletevalue/valuation/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/valuation/economy.py +83 -0
- athletevalue-0.1.0/src/athletevalue/valuation/player.py +315 -0
- athletevalue-0.1.0/src/athletevalue/valuation/report.py +79 -0
- athletevalue-0.1.0/src/athletevalue/valuation/result.py +53 -0
- athletevalue-0.1.0/src/athletevalue/valuation/season.py +213 -0
- athletevalue-0.1.0/src/athletevalue/valuation/team.py +157 -0
- athletevalue-0.1.0/src/athletevalue/valuation/validate.py +126 -0
- athletevalue-0.1.0/src/athletevalue/versions.py +12 -0
- athletevalue-0.1.0/src/athletevalue/wins/__init__.py +0 -0
- athletevalue-0.1.0/src/athletevalue/wins/pythag.py +43 -0
- athletevalue-0.1.0/src/athletevalue/wins/war.py +167 -0
- athletevalue-0.1.0/tests/__init__.py +0 -0
- athletevalue-0.1.0/tests/conftest.py +10 -0
- athletevalue-0.1.0/tests/fixtures/__init__.py +0 -0
- athletevalue-0.1.0/tests/fixtures/raw_season.py +111 -0
- athletevalue-0.1.0/tests/fixtures/synthetic.py +116 -0
- athletevalue-0.1.0/tests/golden/__init__.py +0 -0
- athletevalue-0.1.0/tests/golden/summary.txt +16 -0
- athletevalue-0.1.0/tests/golden/test_summary.py +80 -0
- athletevalue-0.1.0/tests/governance/__init__.py +0 -0
- athletevalue-0.1.0/tests/governance/test_data_licensing.py +45 -0
- athletevalue-0.1.0/tests/governance/test_no_uncited_constants.py +32 -0
- athletevalue-0.1.0/tests/property/__init__.py +0 -0
- athletevalue-0.1.0/tests/regression/__init__.py +0 -0
- athletevalue-0.1.0/tests/regression/test_live_seasons.py +36 -0
- athletevalue-0.1.0/tests/unit/__init__.py +0 -0
- athletevalue-0.1.0/tests/unit/test_assumptions.py +74 -0
- athletevalue-0.1.0/tests/unit/test_cache.py +40 -0
- athletevalue-0.1.0/tests/unit/test_crosswalk_data.py +20 -0
- athletevalue-0.1.0/tests/unit/test_cv.py +28 -0
- athletevalue-0.1.0/tests/unit/test_design.py +68 -0
- athletevalue-0.1.0/tests/unit/test_economics.py +159 -0
- athletevalue-0.1.0/tests/unit/test_game_matching.py +59 -0
- athletevalue-0.1.0/tests/unit/test_games.py +43 -0
- athletevalue-0.1.0/tests/unit/test_market.py +114 -0
- athletevalue-0.1.0/tests/unit/test_names.py +42 -0
- athletevalue-0.1.0/tests/unit/test_pipeline_offline.py +115 -0
- athletevalue-0.1.0/tests/unit/test_possessions.py +91 -0
- athletevalue-0.1.0/tests/unit/test_ridge.py +141 -0
- athletevalue-0.1.0/tests/unit/test_schemas.py +40 -0
- athletevalue-0.1.0/tests/unit/test_uncertainty.py +26 -0
- athletevalue-0.1.0/tests/unit/test_wins.py +89 -0
- athletevalue-0.1.0/uv.lock +1628 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.venv*/
|
|
4
|
+
dist/
|
|
5
|
+
build/
|
|
6
|
+
*.egg-info/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.mypy_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
.coverage
|
|
11
|
+
coverage.xml
|
|
12
|
+
htmlcov/
|
|
13
|
+
site/
|
|
14
|
+
.hypothesis/
|
|
15
|
+
.DS_Store
|
|
16
|
+
# Local-only research notes and private data (KenPom exports etc.)
|
|
17
|
+
*.local.md
|
|
18
|
+
*.local.csv
|
|
19
|
+
private/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"imports_by_module":{"athletevalue":[["athletevalue.versions",false,3,"from athletevalue.versions import MODEL_VERSION, __version__"]],"athletevalue.api":[["athletevalue.valuation.season",false,10,"from athletevalue.valuation.season import SeasonModel, assemble_season"],["athletevalue.sources.sportsdataverse",false,7,"from athletevalue.sources.sportsdataverse import SdvClient, SdvDataset"],["athletevalue.sources.cache",false,6,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.sports.mbb.loaders",false,9,"from athletevalue.sports.mbb.loaders import load_season_frames"],["athletevalue.sources.torvik",false,8,"from athletevalue.sources.torvik import TorvikClient"],["athletevalue.assumptions.registry",false,5,"from athletevalue.assumptions.registry import AssumptionRegistry, default_registry"],["athletevalue.valuation.validate",false,11,"from athletevalue.valuation.validate import ValidationReport, validate_season"]],"athletevalue.assumptions":[],"athletevalue.assumptions.audit":[],"athletevalue.assumptions.data":[],"athletevalue.assumptions.models":[["athletevalue.schemas.source",false,27,"from athletevalue.schemas.source import SourceReference"],["athletevalue.schemas.evidence",false,26,"from athletevalue.schemas.evidence import EvidenceStatus"]],"athletevalue.assumptions.registry":[["athletevalue.assumptions.models",false,12,"from athletevalue.assumptions.models import Assumption"]],"athletevalue.cli":[],"athletevalue.constants":[],"athletevalue.economics":[],"athletevalue.frames":[],"athletevalue.frames.columns":[],"athletevalue.frames.games":[["athletevalue.frames.columns",false,9,"from athletevalue.frames.columns import ("]],"athletevalue.frames.possessions":[["athletevalue.frames.columns",false,16,"from athletevalue.frames.columns import POSSESSION_COLUMNS, SLOTS, require_columns"]],"athletevalue.frames.team_possessions":[["athletevalue.constants",false,7,"from athletevalue.constants import PER_100"]],"athletevalue.identity":[],"athletevalue.identity.names":[],"athletevalue.identity.resolve":[["athletevalue.identity.names",false,7,"from athletevalue.identity.names import normalize_name, similarity"]],"athletevalue.impact":[],"athletevalue.impact.cv":[["athletevalue.impact.ridge",false,17,"from athletevalue.impact.ridge import solve_penalized, weighted_gram, weighted_moment"],["athletevalue.impact.design",false,16,"from athletevalue.impact.design import Design"]],"athletevalue.impact.design":[["athletevalue.frames.possessions",false,28,"from athletevalue.frames.possessions import LineupData"],["athletevalue.constants",false,27,"from athletevalue.constants import PER_100"]],"athletevalue.impact.rapm":[["athletevalue.impact.cv",false,11,"from athletevalue.impact.cv import CvResult"],["athletevalue.impact.ridge",false,13,"from athletevalue.impact.ridge import RidgeError, RidgeFit, fit_ridge"],["athletevalue.impact.design",false,12,"from athletevalue.impact.design import Design, build_design"],["athletevalue.frames.possessions",false,10,"from athletevalue.frames.possessions import LineupData"]],"athletevalue.impact.reconstruct":[["athletevalue.impact.ridge",false,10,"from athletevalue.impact.ridge import RidgeFit"],["athletevalue.frames.possessions",false,8,"from athletevalue.frames.possessions import LineupData"],["athletevalue.impact.design",false,9,"from athletevalue.impact.design import Design"]],"athletevalue.impact.ridge":[],"athletevalue.market":[],"athletevalue.schemas":[],"athletevalue.schemas.estimate":[["athletevalue.schemas.evidence",false,11,"from athletevalue.schemas.evidence import EvidenceStatus"]],"athletevalue.schemas.evidence":[],"athletevalue.schemas.hashing":[],"athletevalue.schemas.identity":[],"athletevalue.schemas.registry":[],"athletevalue.schemas.source":[["athletevalue.schemas.hashing",false,11,"from athletevalue.schemas.hashing import stable_id"]],"athletevalue.sources":[],"athletevalue.sources.cache":[["athletevalue.versions",false,20,"from athletevalue.versions import __version__"],["athletevalue.schemas.source",false,19,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"]],"athletevalue.sources.eada":[["athletevalue.sources.cache",false,18,"from athletevalue.sources.cache import ArtifactCache, RawArtifact"],["athletevalue.schemas.source",false,17,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"]],"athletevalue.sources.sportsdataverse":[["athletevalue.schemas.source",false,14,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"],["athletevalue.sources.cache",false,15,"from athletevalue.sources.cache import ArtifactCache, ArtifactNotFoundError, RawArtifact"]],"athletevalue.sources.torvik":[["athletevalue.sources.cache",false,12,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.schemas.source",false,11,"from athletevalue.schemas.source import LicenseTag"]],"athletevalue.sources.user_csv":[],"athletevalue.sports":[],"athletevalue.sports.mbb":[],"athletevalue.sports.mbb.loaders":[["athletevalue.valuation.season",false,7,"from athletevalue.valuation.season import SeasonFrames"],["athletevalue.sources.cache",false,5,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.sources.sportsdataverse",false,6,"from athletevalue.sources.sportsdataverse import SdvClient, SdvDataset"]],"athletevalue.uncertainty":[],"athletevalue.uncertainty.draws":[["athletevalue.schemas.evidence",false,16,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.schemas.estimate",false,15,"from athletevalue.schemas.estimate import Estimate"]],"athletevalue.valuation":[],"athletevalue.valuation.season":[["athletevalue.impact.rapm",false,18,"from athletevalue.impact.rapm import RapmResult, fit_rapm"],["athletevalue.constants",false,12,"from athletevalue.constants import PER_100"],["athletevalue.frames.team_possessions",false,15,"from athletevalue.frames.team_possessions import team_possession_totals"],["athletevalue.impact.reconstruct",false,19,"from athletevalue.impact.reconstruct import team_ratings"],["athletevalue.schemas.source",false,20,"from athletevalue.schemas.source import SourceReference"],["athletevalue.frames.possessions",false,14,"from athletevalue.frames.possessions import build_lineup_data"],["athletevalue.assumptions.registry",false,11,"from athletevalue.assumptions.registry import AssumptionRegistry"],["athletevalue.impact.cv",false,16,"from athletevalue.impact.cv import CvResult, cv_lambda"],["athletevalue.impact.design",false,17,"from athletevalue.impact.design import build_design"],["athletevalue.wins.war",false,22,"from athletevalue.wins.war import GameContext, PlayerImpact, TeamContext, fit_margin_sd"],["athletevalue.wins.pythag",false,21,"from athletevalue.wins.pythag import fit_exponent"],["athletevalue.frames.games",false,13,"from athletevalue.frames.games import build_season_games, espn_game_map"]],"athletevalue.valuation.validate":[["athletevalue.valuation.season",false,17,"from athletevalue.valuation.season import SeasonModel"],["athletevalue.identity.names",false,16,"from athletevalue.identity.names import normalize_name"],["athletevalue.assumptions.registry",false,15,"from athletevalue.assumptions.registry import AssumptionRegistry"]],"athletevalue.versions":[],"athletevalue.wins":[],"athletevalue.wins.pythag":[],"athletevalue.wins.war":[["athletevalue.uncertainty.draws",false,13,"from athletevalue.uncertainty.draws import FloatArray, summarize"],["athletevalue.schemas.evidence",false,12,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.wins.pythag",false,14,"from athletevalue.wins.pythag import margin_slope"],["athletevalue.constants",false,10,"from athletevalue.constants import PER_100"],["athletevalue.schemas.estimate",false,11,"from athletevalue.schemas.estimate import Estimate"]]},"version":2}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"imports_by_module":{"athletevalue":[["athletevalue.versions",false,3,"from athletevalue.versions import MODEL_VERSION, __version__"]],"athletevalue.api":[["athletevalue.valuation.economy",false,15,"from athletevalue.valuation.economy import EconomicsModel, assemble_economics"],["athletevalue.valuation.season",false,19,"from athletevalue.valuation.season import SeasonModel, assemble_season"],["athletevalue.assumptions.registry",false,7,"from athletevalue.assumptions.registry import AssumptionRegistry, default_registry"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.identity.resolve",false,8,"from athletevalue.identity.resolve import resolve_team"],["athletevalue.valuation.player",false,16,"from athletevalue.valuation.player import team_table"],["athletevalue.sources.torvik",false,12,"from athletevalue.sources.torvik import TorvikClient"],["athletevalue.sports.mbb.loaders",false,14,"from athletevalue.sports.mbb.loaders import load_season_frames"],["athletevalue.valuation.player",false,17,"from athletevalue.valuation.player import value_player as compose_player"],["athletevalue.sources.sportsdataverse",false,11,"from athletevalue.sources.sportsdataverse import SdvClient, SdvDataset"],["athletevalue.sports.mbb.economics_loaders",false,13,"from athletevalue.sports.mbb.economics_loaders import load_economics_frames"],["athletevalue.valuation.validate",false,21,"from athletevalue.valuation.validate import ValidationReport, validate_season"],["polars",false,5,"import polars as pl"],["athletevalue.market.registry",false,9,"from athletevalue.market.registry import load_deal_registry"],["athletevalue.valuation.result",false,18,"from athletevalue.valuation.result import PlayerValuation"],["athletevalue.sources.cache",false,10,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.valuation.team",false,20,"from athletevalue.valuation.team import team_draws"]],"athletevalue.assumptions":[],"athletevalue.assumptions.audit":[["ast",false,10,"import ast"],["dataclasses",false,12,"from dataclasses import dataclass"],["collections",false,11,"from collections.abc import Iterator"],["pathlib",false,13,"from pathlib import Path"],["__future__",false,8,"from __future__ import annotations"]],"athletevalue.assumptions.data":[],"athletevalue.assumptions.models":[["pydantic",false,24,"from pydantic import BaseModel, ConfigDict, model_validator"],["typing",false,22,"from typing import Self"],["enum",false,21,"from enum import StrEnum"],["athletevalue.schemas.evidence",false,26,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.schemas.source",false,27,"from athletevalue.schemas.source import SourceReference"],["__future__",false,19,"from __future__ import annotations"]],"athletevalue.assumptions.registry":[["athletevalue.assumptions.models",false,12,"from athletevalue.assumptions.models import Assumption"],["tomllib",false,5,"import tomllib"],["__future__",false,3,"from __future__ import annotations"],["typing",false,10,"from typing import Any, Self"],["collections",false,6,"from collections.abc import Iterator"],["pathlib",false,9,"from pathlib import Path"],["functools",false,7,"from functools import cache"],["importlib",false,8,"from importlib import resources"]],"athletevalue.cli":[],"athletevalue.cli.main":[["__future__",false,3,"from __future__ import annotations"],["json",false,5,"import json"],["athletevalue.sources.sportsdataverse",false,15,"from athletevalue.sources.sportsdataverse import SdvClient, SdvDataset"],["athletevalue.assumptions.registry",false,13,"from athletevalue.assumptions.registry import AssumptionRegistry"],["typer",false,10,"import typer"],["athletevalue.sources.cache",false,14,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.api",false,12,"from athletevalue import api"],["typing",false,7,"from typing import Annotated"],["athletevalue.valuation.report",false,16,"from athletevalue.valuation.report import money"],["pathlib",false,6,"from pathlib import Path"],["polars",false,9,"import polars as pl"]],"athletevalue.constants":[["__future__",false,8,"from __future__ import annotations"]],"athletevalue.data":[],"athletevalue.data.deal_registry":[],"athletevalue.data.identity":[],"athletevalue.economics":[],"athletevalue.economics.panel":[["polars",false,5,"import polars as pl"],["__future__",false,3,"from __future__ import annotations"]],"athletevalue.economics.program_value":[["__future__",false,3,"from __future__ import annotations"],["dataclasses",false,5,"from dataclasses import dataclass"],["numpy",false,8,"from numpy.typing import NDArray"],["athletevalue.economics.revenue",false,10,"from athletevalue.economics.revenue import RevenueModel"],["numpy",false,7,"import numpy as np"],["athletevalue.economics.tournament",false,11,"from athletevalue.economics.tournament import BidModel"]],"athletevalue.economics.revenue":[["numpy",false,22,"import numpy as np"],["__future__",false,18,"from __future__ import annotations"],["dataclasses",false,20,"from dataclasses import dataclass"],["numpy",false,24,"from numpy.typing import NDArray"],["polars",false,23,"import polars as pl"]],"athletevalue.economics.tournament":[["scipy",false,11,"from scipy.special import expit"],["scipy",false,10,"from scipy.optimize import minimize"],["numpy",false,7,"import numpy as np"],["polars",false,8,"import polars as pl"],["dataclasses",false,5,"from dataclasses import dataclass"],["__future__",false,3,"from __future__ import annotations"],["numpy",false,9,"from numpy.typing import NDArray"]],"athletevalue.frames":[],"athletevalue.frames.columns":[["__future__",false,7,"from __future__ import annotations"],["polars",false,9,"import polars as pl"]],"athletevalue.frames.games":[["athletevalue.frames.columns",false,9,"from athletevalue.frames.columns import ("],["athletevalue.identity.names",false,19,"from athletevalue.identity.names import similarity"],["dataclasses",false,5,"from dataclasses import dataclass"],["__future__",false,3,"from __future__ import annotations"],["polars",false,7,"import polars as pl"]],"athletevalue.frames.possessions":[["__future__",false,10,"from __future__ import annotations"],["athletevalue.frames.columns",false,16,"from athletevalue.frames.columns import POSSESSION_COLUMNS, SLOTS, require_columns"],["polars",false,14,"import polars as pl"],["dataclasses",false,12,"from dataclasses import dataclass"]],"athletevalue.frames.team_possessions":[["polars",false,5,"import polars as pl"],["athletevalue.constants",false,7,"from athletevalue.constants import PER_100"],["__future__",false,3,"from __future__ import annotations"]],"athletevalue.identity":[],"athletevalue.identity.crosswalk":[["__future__",false,3,"from __future__ import annotations"],["importlib",false,6,"from importlib import resources"],["polars",false,8,"import polars as pl"],["functools",false,5,"from functools import cache"]],"athletevalue.identity.names":[["__future__",false,8,"from __future__ import annotations"],["unicodedata",false,11,"import unicodedata"],["difflib",false,12,"from difflib import SequenceMatcher"],["re",false,10,"import re"]],"athletevalue.identity.resolve":[["__future__",false,3,"from __future__ import annotations"],["typing",false,5,"from typing import Any"],["athletevalue.identity.names",false,9,"from athletevalue.identity.names import normalize_name, similarity"],["polars",false,7,"import polars as pl"]],"athletevalue.impact":[],"athletevalue.impact.cv":[["athletevalue.impact.ridge",false,17,"from athletevalue.impact.ridge import solve_penalized, weighted_gram, weighted_moment"],["dataclasses",false,11,"from dataclasses import dataclass"],["numpy",false,14,"from numpy.typing import NDArray"],["athletevalue.impact.design",false,16,"from athletevalue.impact.design import Design"],["numpy",false,13,"import numpy as np"],["__future__",false,9,"from __future__ import annotations"]],"athletevalue.impact.design":[["__future__",false,18,"from __future__ import annotations"],["numpy",false,25,"from numpy.typing import NDArray"],["polars",false,23,"import polars as pl"],["athletevalue.frames.possessions",false,28,"from athletevalue.frames.possessions import LineupData"],["athletevalue.constants",false,27,"from athletevalue.constants import PER_100"],["numpy",false,22,"import numpy as np"],["dataclasses",false,20,"from dataclasses import dataclass"],["scipy",false,24,"import scipy.sparse as sp"]],"athletevalue.impact.rapm":[["polars",false,8,"import polars as pl"],["numpy",false,7,"import numpy as np"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.impact.design",false,12,"from athletevalue.impact.design import Design, build_design"],["athletevalue.frames.possessions",false,10,"from athletevalue.frames.possessions import LineupData"],["dataclasses",false,5,"from dataclasses import dataclass"],["athletevalue.impact.ridge",false,13,"from athletevalue.impact.ridge import RidgeError, RidgeFit, fit_ridge"],["athletevalue.impact.cv",false,11,"from athletevalue.impact.cv import CvResult"]],"athletevalue.impact.reconstruct":[["__future__",false,3,"from __future__ import annotations"],["polars",false,6,"import polars as pl"],["athletevalue.impact.ridge",false,10,"from athletevalue.impact.ridge import RidgeFit"],["athletevalue.frames.possessions",false,8,"from athletevalue.frames.possessions import LineupData"],["athletevalue.impact.design",false,9,"from athletevalue.impact.design import Design"],["numpy",false,5,"import numpy as np"]],"athletevalue.impact.ridge":[["__future__",false,17,"from __future__ import annotations"],["scipy",false,22,"import scipy.sparse as sp"],["numpy",false,21,"import numpy as np"],["numpy",false,23,"from numpy.typing import NDArray"],["dataclasses",false,19,"from dataclasses import dataclass"],["scipy",false,24,"from scipy.linalg import lapack"]],"athletevalue.market":[],"athletevalue.market.allocation":[["athletevalue.uncertainty.draws",false,26,"from athletevalue.uncertainty.draws import FloatArray"],["polars",false,22,"import polars as pl"],["athletevalue.constants",false,25,"from athletevalue.constants import PLAYERS_ON_COURT"],["numpy",false,23,"from numpy.typing import NDArray"],["__future__",false,17,"from __future__ import annotations"],["numpy",false,21,"import numpy as np"],["dataclasses",false,19,"from dataclasses import dataclass"]],"athletevalue.market.budget":[["athletevalue.assumptions.registry",false,10,"from athletevalue.assumptions.registry import AssumptionRegistry"],["__future__",false,3,"from __future__ import annotations"],["dataclasses",false,5,"from dataclasses import dataclass"],["numpy",false,8,"import numpy as np"],["athletevalue.schemas.evidence",false,11,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.uncertainty.draws",false,12,"from athletevalue.uncertainty.draws import FloatArray, lognormal_from_range"],["enum",false,6,"from enum import StrEnum"]],"athletevalue.market.registry":[["importlib",false,5,"from importlib import resources"],["athletevalue.schemas.registry",false,10,"from athletevalue.schemas.registry import DealRecord"],["polars",false,7,"import polars as pl"],["athletevalue.identity.names",false,9,"from athletevalue.identity.names import normalize_name"],["__future__",false,3,"from __future__ import annotations"]],"athletevalue.market.surplus":[["enum",false,5,"from enum import StrEnum"],["__future__",false,3,"from __future__ import annotations"],["numpy",false,7,"import numpy as np"],["athletevalue.uncertainty.draws",false,10,"from athletevalue.uncertainty.draws import FloatArray"],["polars",false,8,"import polars as pl"]],"athletevalue.schemas":[],"athletevalue.schemas.estimate":[["pydantic",false,9,"from pydantic import BaseModel, ConfigDict, Field, model_validator"],["statistics",false,6,"from statistics import NormalDist"],["math",false,5,"import math"],["__future__",false,3,"from __future__ import annotations"],["typing",false,7,"from typing import Self"],["athletevalue.schemas.evidence",false,11,"from athletevalue.schemas.evidence import EvidenceStatus"]],"athletevalue.schemas.evidence":[["enum",false,11,"from enum import StrEnum"],["__future__",false,9,"from __future__ import annotations"],["typing",false,12,"from typing import Self"]],"athletevalue.schemas.hashing":[["__future__",false,3,"from __future__ import annotations"],["hashlib",false,5,"import hashlib"]],"athletevalue.schemas.identity":[["__future__",false,3,"from __future__ import annotations"],["pydantic",false,5,"from pydantic import BaseModel, ConfigDict"]],"athletevalue.schemas.registry":[["typing",false,7,"from typing import Self"],["enum",false,6,"from enum import StrEnum"],["pydantic",false,9,"from pydantic import BaseModel, ConfigDict, Field, HttpUrl, model_validator"],["datetime",false,5,"from datetime import date"],["__future__",false,3,"from __future__ import annotations"]],"athletevalue.schemas.source":[["athletevalue.schemas.hashing",false,11,"from athletevalue.schemas.hashing import stable_id"],["datetime",false,5,"from datetime import datetime"],["pydantic",false,9,"from pydantic import BaseModel, ConfigDict, model_validator"],["enum",false,6,"from enum import StrEnum"],["typing",false,7,"from typing import Any"],["__future__",false,3,"from __future__ import annotations"]],"athletevalue.sources":[],"athletevalue.sources.cache":[["datetime",false,13,"from datetime import UTC, datetime"],["httpx",false,16,"import httpx"],["athletevalue.schemas.source",false,19,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"],["__future__",false,7,"from __future__ import annotations"],["hashlib",false,9,"import hashlib"],["platformdirs",false,17,"import platformdirs"],["dataclasses",false,12,"from dataclasses import dataclass"],["pathlib",false,14,"from pathlib import Path"],["os",false,11,"import os"],["json",false,10,"import json"],["athletevalue.versions",false,20,"from athletevalue.versions import __version__"]],"athletevalue.sources.eada":[["athletevalue.sources.cache",false,19,"from athletevalue.sources.cache import ArtifactCache, RawArtifact"],["warnings",false,13,"import warnings"],["athletevalue.schemas.source",false,18,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"],["__future__",false,10,"from __future__ import annotations"],["zipfile",false,14,"import zipfile"],["polars",false,16,"import polars as pl"],["json",false,12,"import json"]],"athletevalue.sources.sportsdataverse":[["__future__",false,8,"from __future__ import annotations"],["enum",false,10,"from enum import StrEnum"],["polars",false,12,"import polars as pl"],["athletevalue.schemas.source",false,14,"from athletevalue.schemas.source import LicenseTag, SourceKind, SourceReference"],["athletevalue.sources.cache",false,15,"from athletevalue.sources.cache import ArtifactCache, ArtifactNotFoundError, RawArtifact"]],"athletevalue.sources.torvik":[["athletevalue.sources.cache",false,12,"from athletevalue.sources.cache import ArtifactCache"],["athletevalue.schemas.source",false,11,"from athletevalue.schemas.source import LicenseTag"],["polars",false,9,"import polars as pl"],["__future__",false,7,"from __future__ import annotations"]],"athletevalue.sources.user_csv":[["polars",false,13,"import polars as pl"],["__future__",false,9,"from __future__ import annotations"],["pathlib",false,11,"from pathlib import Path"]],"athletevalue.sports":[],"athletevalue.sports.mbb":[],"athletevalue.sports.mbb.economics_loaders":[["athletevalue.sources.eada",false,10,"from athletevalue.sources.eada import EadaClient, EadaYearUnavailableError"],["athletevalue.sources.cache",false,9,"from athletevalue.sources.cache import ArtifactCache"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.valuation.economy",false,17,"from athletevalue.valuation.economy import EconomicsFrames"],["athletevalue.frames.games",false,7,"from athletevalue.frames.games import build_season_games, combined_game_map"],["athletevalue.identity.crosswalk",false,8,"from athletevalue.identity.crosswalk import team_crosswalk"],["athletevalue.sources.sportsdataverse",false,11,"from athletevalue.sources.sportsdataverse import ("],["polars",false,5,"import polars as pl"]],"athletevalue.sports.mbb.loaders":[["athletevalue.sources.cache",false,5,"from athletevalue.sources.cache import ArtifactCache"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.sources.sportsdataverse",false,6,"from athletevalue.sources.sportsdataverse import SdvClient, SdvDataset"],["athletevalue.valuation.season",false,7,"from athletevalue.valuation.season import SeasonFrames"]],"athletevalue.uncertainty":[],"athletevalue.uncertainty.draws":[["athletevalue.schemas.evidence",false,16,"from athletevalue.schemas.evidence import EvidenceStatus"],["numpy",false,12,"import numpy as np"],["athletevalue.schemas.estimate",false,15,"from athletevalue.schemas.estimate import Estimate"],["numpy",false,13,"from numpy.typing import NDArray"],["__future__",false,7,"from __future__ import annotations"],["math",false,9,"import math"],["statistics",false,10,"from statistics import NormalDist"]],"athletevalue.valuation":[],"athletevalue.valuation.economy":[["athletevalue.economics.revenue",false,13,"from athletevalue.economics.revenue import RevenueModel, fit_revenue_model"],["athletevalue.schemas.source",false,15,"from athletevalue.schemas.source import SourceReference"],["__future__",false,3,"from __future__ import annotations"],["polars",false,8,"import polars as pl"],["numpy",false,7,"import numpy as np"],["dataclasses",false,5,"from dataclasses import dataclass, field"],["athletevalue.economics.program_value",false,12,"from athletevalue.economics.program_value import ProgramContext"],["athletevalue.economics.tournament",false,14,"from athletevalue.economics.tournament import BidModel, fit_bid_model, units_per_bid"],["athletevalue.economics.panel",false,11,"from athletevalue.economics.panel import revenue_base, revenue_panel"],["athletevalue.assumptions.registry",false,10,"from athletevalue.assumptions.registry import AssumptionRegistry"]],"athletevalue.valuation.player":[["athletevalue.identity.resolve",false,11,"from athletevalue.identity.resolve import resolve_player"],["athletevalue.uncertainty.draws",false,18,"from athletevalue.uncertainty.draws import summarize"],["athletevalue.valuation.team",false,23,"from athletevalue.valuation.team import ("],["__future__",false,3,"from __future__ import annotations"],["athletevalue.valuation.season",false,22,"from athletevalue.valuation.season import SeasonModel"],["athletevalue.assumptions.registry",false,10,"from athletevalue.assumptions.registry import AssumptionRegistry"],["athletevalue.market.surplus",false,13,"from athletevalue.market.surplus import assign_quadrants, surplus_draws"],["athletevalue.valuation.result",false,21,"from athletevalue.valuation.result import Driver, PlayerValuation"],["numpy",false,7,"import numpy as np"],["athletevalue.schemas.identity",false,16,"from athletevalue.schemas.identity import PlayerRef"],["athletevalue.schemas.registry",false,17,"from athletevalue.schemas.registry import DealRecord"],["athletevalue.wins.war",false,33,"from athletevalue.wins.war import war_analytic"],["athletevalue.versions",false,32,"from athletevalue.versions import MODEL_VERSION"],["athletevalue.schemas.estimate",false,14,"from athletevalue.schemas.estimate import Estimate"],["polars",false,8,"import polars as pl"],["athletevalue.valuation.report",false,20,"from athletevalue.valuation.report import money"],["athletevalue.schemas.evidence",false,15,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.valuation.economy",false,19,"from athletevalue.valuation.economy import EconomicsModel"],["athletevalue.market.registry",false,12,"from athletevalue.market.registry import observed_annual_pay"],["datetime",false,5,"from datetime import date"]],"athletevalue.valuation.report":[["athletevalue.schemas.evidence",false,6,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.valuation.result",false,7,"from athletevalue.valuation.result import PlayerValuation"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.schemas.estimate",false,5,"from athletevalue.schemas.estimate import Estimate"]],"athletevalue.valuation.result":[["athletevalue.schemas.identity",false,10,"from athletevalue.schemas.identity import PlayerRef"],["athletevalue.schemas.estimate",false,9,"from athletevalue.schemas.estimate import Estimate"],["pydantic",false,7,"from pydantic import BaseModel, ConfigDict"],["athletevalue.valuation.report",false,51,"from athletevalue.valuation.report import render_summary"],["__future__",false,3,"from __future__ import annotations"],["datetime",false,5,"from datetime import date"],["athletevalue.schemas.source",false,11,"from athletevalue.schemas.source import SourceReference"]],"athletevalue.valuation.season":[["athletevalue.impact.design",false,18,"from athletevalue.impact.design import build_design"],["athletevalue.wins.pythag",false,22,"from athletevalue.wins.pythag import fit_exponent"],["polars",false,10,"import polars as pl"],["athletevalue.impact.reconstruct",false,20,"from athletevalue.impact.reconstruct import team_ratings"],["athletevalue.schemas.source",false,21,"from athletevalue.schemas.source import SourceReference"],["datetime",false,6,"from datetime import date, datetime"],["numpy",false,9,"import numpy as np"],["athletevalue.frames.possessions",false,15,"from athletevalue.frames.possessions import build_lineup_data"],["dataclasses",false,5,"from dataclasses import dataclass, field"],["athletevalue.frames.team_possessions",false,16,"from athletevalue.frames.team_possessions import team_possession_totals"],["athletevalue.wins.war",false,23,"from athletevalue.wins.war import GameContext, PlayerImpact, TeamContext, fit_margin_sd"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.frames.games",false,14,"from athletevalue.frames.games import build_season_games, combined_game_map"],["athletevalue.assumptions.registry",false,12,"from athletevalue.assumptions.registry import AssumptionRegistry"],["athletevalue.impact.cv",false,17,"from athletevalue.impact.cv import CvResult, cv_lambda"],["athletevalue.impact.rapm",false,19,"from athletevalue.impact.rapm import RapmResult, fit_rapm"],["typing",false,7,"from typing import Any"],["athletevalue.constants",false,13,"from athletevalue.constants import PER_100"]],"athletevalue.valuation.team":[["athletevalue.valuation.economy",false,16,"from athletevalue.valuation.economy import EconomicsModel"],["athletevalue.market.budget",false,13,"from athletevalue.market.budget import MarketUnavailableError, RosterBudget, roster_budget"],["athletevalue.wins.war",false,18,"from athletevalue.wins.war import war_draws"],["athletevalue.valuation.season",false,17,"from athletevalue.valuation.season import SeasonModel"],["athletevalue.market.allocation",false,12,"from athletevalue.market.allocation import Allocation, AllocationRules, allocate"],["polars",false,8,"import polars as pl"],["athletevalue.assumptions.registry",false,10,"from athletevalue.assumptions.registry import AssumptionRegistry"],["numpy",false,7,"import numpy as np"],["athletevalue.schemas.evidence",false,14,"from athletevalue.schemas.evidence import EvidenceStatus"],["athletevalue.uncertainty.draws",false,15,"from athletevalue.uncertainty.draws import FloatArray"],["athletevalue.economics.program_value",false,11,"from athletevalue.economics.program_value import ProgramValueDraws, program_value_draws"],["__future__",false,3,"from __future__ import annotations"],["dataclasses",false,5,"from dataclasses import dataclass"]],"athletevalue.valuation.validate":[["polars",false,12,"import polars as pl"],["athletevalue.assumptions.registry",false,15,"from athletevalue.assumptions.registry import AssumptionRegistry"],["athletevalue.identity.names",false,16,"from athletevalue.identity.names import normalize_name"],["athletevalue.valuation.season",false,17,"from athletevalue.valuation.season import SeasonModel"],["scipy",false,13,"from scipy.stats import spearmanr"],["__future__",false,8,"from __future__ import annotations"],["dataclasses",false,10,"from dataclasses import dataclass"]],"athletevalue.versions":[["__future__",false,8,"from __future__ import annotations"]],"athletevalue.wins":[],"athletevalue.wins.pythag":[["numpy",false,6,"from numpy.typing import NDArray"],["scipy",false,7,"from scipy.optimize import minimize_scalar"],["__future__",false,3,"from __future__ import annotations"],["numpy",false,5,"import numpy as np"]],"athletevalue.wins.war":[["numpy",false,7,"import numpy as np"],["athletevalue.uncertainty.draws",false,13,"from athletevalue.uncertainty.draws import FloatArray, summarize"],["scipy",false,8,"from scipy.stats import norm"],["athletevalue.schemas.evidence",false,12,"from athletevalue.schemas.evidence import EvidenceStatus"],["__future__",false,3,"from __future__ import annotations"],["athletevalue.wins.pythag",false,14,"from athletevalue.wins.pythag import margin_slope"],["athletevalue.constants",false,10,"from athletevalue.constants import PER_100"],["athletevalue.schemas.estimate",false,11,"from athletevalue.schemas.estimate import Estimate"],["dataclasses",false,5,"from dataclasses import dataclass"]]},"version":2}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"athletevalue.schemas.source": 1789594410.9776866, "athletevalue.identity": 1789594410.9708703, "athletevalue.economics.revenue": 1789596658.1926856, "athletevalue.assumptions.audit": 1789594465.684653, "athletevalue.assumptions.data": 1789594410.9707494, "athletevalue.sources": 1789594410.9707882, "athletevalue.economics.program_value": 1789596271.0706863, "athletevalue.market.registry": 1789596358.896882, "athletevalue.data.identity": 1789596302.3783886, "athletevalue.valuation.economy": 1789596302.380616, "athletevalue.schemas.registry": 1789594410.9841375, "athletevalue.sports.mbb.loaders": 1789594957.7058473, "athletevalue.assumptions.models": 1789595281.2135575, "athletevalue.uncertainty.draws": 1789594705.992007, "athletevalue.cli.main": 1789596658.1926923, "athletevalue.sources.user_csv": 1789594591.0002942, "athletevalue.identity.resolve": 1789596450.6353033, "athletevalue.valuation.validate": 1789595241.847176, "athletevalue.valuation.player": 1789596671.1591754, "athletevalue.uncertainty": 1789594410.9708285, "athletevalue.wins": 1789594410.970998, "athletevalue.sources.eada": 1789597023.679714, "athletevalue.impact.rapm": 1789595241.8462043, "athletevalue.frames.columns": 1789596155.473347, "athletevalue.sports": 1789594410.9711888, "athletevalue.sports.mbb": 1789594410.9712417, "athletevalue.market": 1789594410.9710865, "athletevalue.cli": 1789594410.9712825, "athletevalue.economics.panel": 1789596658.1921709, "athletevalue.schemas.evidence": 1789594410.9756007, "athletevalue.assumptions.registry": 1789594465.6819286, "athletevalue.frames.games": 1789596658.1924038, "athletevalue.frames.team_possessions": 1789594885.5227299, "athletevalue.market.budget": 1789596658.1918895, "athletevalue.impact.ridge": 1789595207.695548, "athletevalue.valuation.season": 1789596182.500107, "athletevalue.impact.reconstruct": 1789595241.8467422, "athletevalue.schemas.identity": 1789594410.982082, "athletevalue.assumptions": 1789594410.9707007, "athletevalue.wins.pythag": 1789595281.2138126, "athletevalue.valuation.report": 1789596671.159418, "athletevalue.data.deal_registry": 1789596302.3784425, "athletevalue.schemas": 1789594410.9706526, "athletevalue.impact": 1789594410.9709537, "athletevalue.valuation": 1789594410.9711432, "athletevalue": 1789594410.9607627, "athletevalue.identity.crosswalk": 1789596302.3757513, "athletevalue.schemas.estimate": 1789594410.979867, "athletevalue.data": 1789596302.3783298, "athletevalue.sources.sportsdataverse": 1789595281.213981, "athletevalue.sources.cache": 1789595266.6664531, "athletevalue.schemas.hashing": 1789594410.9733174, "athletevalue.api": 1789596532.3138816, "athletevalue.frames.possessions": 1789596155.4727912, "athletevalue.sports.mbb.economics_loaders": 1789596658.1918957, "athletevalue.valuation.team": 1789596658.1930695, "athletevalue.valuation.result": 1789596450.5988288, "athletevalue.economics": 1789594410.9710429, "athletevalue.economics.tournament": 1789596658.1919556, "athletevalue.market.allocation": 1789596658.192, "athletevalue.sources.torvik": 1789595266.667139, "athletevalue.versions": 1789594410.9653552, "athletevalue.market.surplus": 1789596358.9038951, "athletevalue.impact.design": 1789595241.8466735, "athletevalue.impact.cv": 1789595241.8442981, "athletevalue.wins.war": 1789595241.847645, "athletevalue.identity.names": 1789594957.697989, "athletevalue.frames": 1789594410.970909, "athletevalue.constants": 1789594410.9673774}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (2026-09-16)
|
|
4
|
+
|
|
5
|
+
First release, men's basketball.
|
|
6
|
+
|
|
7
|
+
- RAPM from SportsDataverse possession data with exact posterior standard errors,
|
|
8
|
+
pooled low-minute players, non-D1 opponents, neutral sites and grouped
|
|
9
|
+
cross-validation.
|
|
10
|
+
- Validation gates against the SportsDataverse league-wide RAPM and Bart Torvik
|
|
11
|
+
team ratings.
|
|
12
|
+
- Wins above replacement from a per-game win model over each team's schedule.
|
|
13
|
+
- Program value from a school fixed-effects model of EADA revenue, a tournament-bid
|
|
14
|
+
model and conference tournament units.
|
|
15
|
+
- Roster market value for 2025-26 from reported roster budgets allocated by role
|
|
16
|
+
and impact.
|
|
17
|
+
- Assumption registry with citations and evidence status on every estimate.
|
|
18
|
+
- CLI: `fetch`, `fit`, `validate`, `value`, `team`, `assumptions`, `cache-path`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use athletevalue, please cite it as below."
|
|
3
|
+
title: "athletevalue: open models of college athlete impact, program value and market price"
|
|
4
|
+
type: software
|
|
5
|
+
authors:
|
|
6
|
+
- family-names: Hodge
|
|
7
|
+
given-names: John
|
|
8
|
+
license: MIT
|
|
9
|
+
repository-code: "https://github.com/jman4162/athletevalue"
|
|
10
|
+
version: 0.1.0
|
|
11
|
+
date-released: 2026-09-16
|
|
12
|
+
keywords:
|
|
13
|
+
- college basketball
|
|
14
|
+
- adjusted plus-minus
|
|
15
|
+
- sports economics
|
|
16
|
+
- name image likeness
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# athletevalue: notes for coding agents
|
|
2
|
+
|
|
3
|
+
- Layout: `src/athletevalue/{schemas,assumptions,sources,uncertainty,identity,frames,impact,wins,economics,market,valuation,sports,api.py,cli}`.
|
|
4
|
+
Layer order and forbidden imports are in `pyproject.toml` under `[tool.importlinter]`.
|
|
5
|
+
- Checks: `uv run ruff check . && uv run ruff format --check . && uv run mypy src/ && uv run lint-imports && uv run pytest`.
|
|
6
|
+
Live-data tests: `uv run pytest -m network`.
|
|
7
|
+
- If `import athletevalue` fails under `uv run`, the editable `.pth` file has the macOS
|
|
8
|
+
`hidden` flag: `chflags nohidden .venv/lib/python3.12/site-packages/*.pth`, or prefix
|
|
9
|
+
commands with `PYTHONPATH=src` and use `uv run --no-sync`.
|
|
10
|
+
- Modelling constants go in `assumptions/data/*.toml`, never inline; governance tests fail on
|
|
11
|
+
bare numbers in `impact`, `wins`, `economics`, `market`, `valuation` (except `valuation/report.py`).
|
|
12
|
+
- Season key is the ending year. Market budgets exist only for 2026.
|
|
13
|
+
- Do not fit shipped values on KenPom, Knight-Newhouse or raw CollegeBasketballData; Torvik is validation only.
|
|
14
|
+
- Private research notes live in `*.local.md` files, which git ignores.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
git clone https://github.com/jman4162/athletevalue
|
|
7
|
+
cd athletevalue
|
|
8
|
+
uv sync --group dev
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Checks CI runs on every push:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
uv run ruff check . && uv run ruff format --check .
|
|
15
|
+
uv run mypy src/
|
|
16
|
+
uv run lint-imports
|
|
17
|
+
uv run pytest --cov
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`uv run pytest -m network` fits full seasons from live data. It takes a few minutes
|
|
21
|
+
after the first download.
|
|
22
|
+
|
|
23
|
+
macOS note: if `import athletevalue` fails inside the virtual environment, check
|
|
24
|
+
whether the `.pth` files in `.venv/lib/python3.*/site-packages` carry the `hidden`
|
|
25
|
+
flag (`ls -lO`). Some sync tools set it, and Python 3.12.13 and later skip hidden
|
|
26
|
+
`.pth` files. `chflags nohidden .venv/lib/python3.*/site-packages/*.pth` fixes it.
|
|
27
|
+
The test configuration adds `src` to the path, so pytest is unaffected.
|
|
28
|
+
|
|
29
|
+
## Rules the build enforces
|
|
30
|
+
|
|
31
|
+
1. **No bare constants in modelling code.** A number in `impact`, `wins`,
|
|
32
|
+
`economics`, `market` or `valuation` must come from the assumption registry
|
|
33
|
+
(`src/athletevalue/assumptions/data/*.toml`) with a citation, a rationale or a
|
|
34
|
+
`user_input` basis. `tests/governance` fails otherwise.
|
|
35
|
+
2. **Every registry entry is used.** An entry no code reads is removed.
|
|
36
|
+
3. **Layers.** Modelling packages do no I/O, and no fitting code imports the
|
|
37
|
+
reader for user-supplied restricted data. `lint-imports` checks both.
|
|
38
|
+
4. **Evidence status propagates.** A new estimate takes the weakest status of its
|
|
39
|
+
inputs.
|
|
40
|
+
|
|
41
|
+
## Adding a deal to the registry
|
|
42
|
+
|
|
43
|
+
See `src/athletevalue/data/deal_registry/README.md`. In short: a public URL that
|
|
44
|
+
states the figure for that athlete, no rating-site valuations, no data from sources
|
|
45
|
+
that forbid redistribution, and a signed-off commit (`git commit -s`) licensing the
|
|
46
|
+
row under CC BY 4.0.
|
|
47
|
+
|
|
48
|
+
## Writing
|
|
49
|
+
|
|
50
|
+
Docs and docstrings state what a thing does and what was measured. Avoid adjectives
|
|
51
|
+
that are not measurements.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Disclaimer
|
|
2
|
+
|
|
3
|
+
`athletevalue` produces statistical estimates for research and education.
|
|
4
|
+
|
|
5
|
+
- Estimates are not reports of what any athlete is paid. Market values in v0.1
|
|
6
|
+
allocate average roster budgets published by a third party; they are scenarios.
|
|
7
|
+
- Program values count only the revenue schools attribute to men's basketball in
|
|
8
|
+
federal EADA filings and understate value to a university.
|
|
9
|
+
- Intervals reflect the uncertainty the models can measure, not every way they can
|
|
10
|
+
be wrong.
|
|
11
|
+
- Player names come from public NCAA box scores. The project is not affiliated with
|
|
12
|
+
or endorsed by the NCAA, any conference, school, collective or data provider.
|
|
13
|
+
- Nothing here is financial, legal or employment advice.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 John Hodge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Data license
|
|
2
|
+
============
|
|
3
|
+
|
|
4
|
+
The curated data files under src/athletevalue/data/ (the deal registry, team
|
|
5
|
+
crosswalks and training-source manifests) are licensed under the Creative
|
|
6
|
+
Commons Attribution 4.0 International License (CC BY 4.0):
|
|
7
|
+
https://creativecommons.org/licenses/by/4.0/
|
|
8
|
+
|
|
9
|
+
Attribute as: "athletevalue contributors, https://github.com/jman4162/athletevalue".
|
|
10
|
+
|
|
11
|
+
What this license does not cover
|
|
12
|
+
--------------------------------
|
|
13
|
+
|
|
14
|
+
athletevalue downloads third-party data at runtime into a local cache. That
|
|
15
|
+
data is not part of this repository and keeps its own terms:
|
|
16
|
+
|
|
17
|
+
- SportsDataverse release assets (github.com/sportsdataverse/sportsdataverse-data):
|
|
18
|
+
published from an MIT-licensed repository.
|
|
19
|
+
- EADA (ope.ed.gov/athletics): U.S. federal government work.
|
|
20
|
+
- Bart Torvik team results (barttorvik.com): used only to validate outputs;
|
|
21
|
+
never bundled and never used to fit shipped coefficients.
|
|
22
|
+
|
|
23
|
+
Optional adapters read files that a user supplies from their own authorized
|
|
24
|
+
accounts (for example KenPom or the Knight-Newhouse College Athletics
|
|
25
|
+
Database). Those files, and anything fitted from them, are not distributed by
|
|
26
|
+
this project. A governance test fails the build if fitting code imports those
|
|
27
|
+
adapters.
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Methodology
|
|
2
|
+
|
|
3
|
+
This document describes model `mbb-v0.1.0`. Every constant named here is an entry
|
|
4
|
+
in the assumption registry (`athletevalue assumptions` lists them with their basis,
|
|
5
|
+
citation or rationale). Figures quoted are from the 2025 and 2026 season fits.
|
|
6
|
+
|
|
7
|
+
## 1. Data
|
|
8
|
+
|
|
9
|
+
**Possessions.** SportsDataverse publishes one row per possession for every D1
|
|
10
|
+
men's game from 2011, parsed from stats.ncaa.org play-by-play. Each row names the
|
|
11
|
+
offense team, the points scored, a garbage-time flag and the stats.ncaa.org ids of
|
|
12
|
+
all ten players on the floor. For 2026 the file has 878,168 possessions; 840,040
|
|
13
|
+
remain after dropping garbage time and rows where a D1 team's lineup is incomplete.
|
|
14
|
+
|
|
15
|
+
**Non-D1 opponents.** Their lineups carry no player ids. Each non-D1 lineup enters
|
|
16
|
+
the model as one shared column, so those games still inform D1 players' ratings.
|
|
17
|
+
|
|
18
|
+
**Venues.** ESPN schedules mark neutral sites and NCAA tournament games
|
|
19
|
+
(`tournament_id` 22). From 2023 the possession file carries ESPN game ids. For
|
|
20
|
+
earlier seasons neutral-site and postseason ESPN games are matched to NCAA games
|
|
21
|
+
within one day using token similarity of both team names. Matching recovers 93-99%
|
|
22
|
+
of neutral-site games and 62-67 of 67 tournament games per season.
|
|
23
|
+
|
|
24
|
+
**Program finances.** EADA sport-level files give each institution's reported men's
|
|
25
|
+
basketball revenue (`REV_MEN`) and expense (`EXP_MEN`) by academic year. A curated
|
|
26
|
+
crosswalk maps 369 of 373 stats.ncaa.org team names to IPEDS unit ids. The service
|
|
27
|
+
academies are not in EADA, and New Haven joined D1 after the latest file.
|
|
28
|
+
|
|
29
|
+
## 2. Player impact (RAPM)
|
|
30
|
+
|
|
31
|
+
Possessions are grouped into rows that share a game, an offense team, both
|
|
32
|
+
lineups and a venue. For row *r* with offense lineup *O* and defense lineup *D*:
|
|
33
|
+
|
|
34
|
+
y_r = 100 · pts_r / poss_r
|
|
35
|
+
= μ + h·v_r + Σ_{i∈O} off_i − Σ_{j∈D} def_j + ε_r, Var(ε_r) = σ² / poss_r
|
|
36
|
+
|
|
37
|
+
where *v_r* is +1 when the offense is at home, −1 away and 0 neutral. A positive
|
|
38
|
+
`def_j` means player *j* lowers opponent scoring, so a player's net rating is
|
|
39
|
+
`off + def`. Players with fewer than 100 average possessions share one pooled
|
|
40
|
+
offense and one pooled defense column.
|
|
41
|
+
|
|
42
|
+
Coefficients minimize
|
|
43
|
+
|
|
44
|
+
Σ_r poss_r (y_r − x_r β)² + λ Σ_k p_k (β_k − b0_k)²
|
|
45
|
+
|
|
46
|
+
with *p_k* = 1 for player columns and 0 for the intercept, home court, pooled and
|
|
47
|
+
non-D1 columns. `b0` is a prior mean; v0.1 uses zero. Weighting rows by possession
|
|
48
|
+
count makes `X'WX` identical to the possession-level Gram matrix, so λ means the
|
|
49
|
+
same thing as in a possession-level fit.
|
|
50
|
+
|
|
51
|
+
**Penalty.** λ = 1000, the value in the SportsDataverse model card. Cross-validation
|
|
52
|
+
that holds out whole games picks the same value for 2026:
|
|
53
|
+
|
|
54
|
+
| λ | 100 | 300 | 1000 | 3000 | 10000 |
|
|
55
|
+
| --- | --- | --- | --- | --- | --- |
|
|
56
|
+
| held-out weighted MSE | 5,246 | 5,207 | 5,187 | 5,192 | 5,210 |
|
|
57
|
+
|
|
58
|
+
**Uncertainty.** Posterior variances are exact: `σ̂² · diag(A⁻¹)` with
|
|
59
|
+
`A = X'WX + λP`, from the Cholesky factor. The residual variance is
|
|
60
|
+
`σ̂² = Σ poss_r r_r² / (n_rows − df)` with `df = n_cols − λ Σ_penalized (A⁻¹)_kk`.
|
|
61
|
+
Net-rating SEs include the offense-defense covariance. The fit refuses to report a
|
|
62
|
+
result if `df` is not below the column count, which catches a penalty that was
|
|
63
|
+
silently dropped. A starter's net-rating SE is about 4 points per 100: with
|
|
64
|
+
λ = 1000 the prior SD is `sqrt(13,300 / 1000) ≈ 3.6` per component, and one
|
|
65
|
+
season of college possessions does not move far from it.
|
|
66
|
+
|
|
67
|
+
**Team ratings.** A team's adjusted offense is the possession-weighted average of
|
|
68
|
+
the offensive coefficients it put on the floor; defense likewise. Their sum is the
|
|
69
|
+
team's adjusted net rating relative to an average D1 lineup.
|
|
70
|
+
|
|
71
|
+
**Checks.** See the validation table in the README. Two findings from them:
|
|
72
|
+
|
|
73
|
+
- The pooled low-minute players rate −12.1 (2026) and −9.6 (2025) per 100, far
|
|
74
|
+
below the −2.0 replacement convention borrowed from NBA Box Plus/Minus.
|
|
75
|
+
- The home-court coefficient is 2.9-3.2 per side, a net home edge of about 6 points
|
|
76
|
+
per 100 possessions, or 4 points in a 70-possession game.
|
|
77
|
+
|
|
78
|
+
## 3. Wins above replacement
|
|
79
|
+
|
|
80
|
+
A player's share of team possessions is `s = (off_poss + def_poss) / team lineup
|
|
81
|
+
possessions`. Replacing him with a replacement-level player lowers the team's net
|
|
82
|
+
rating by `Δ = (net − R) · s` with `R = −2.0`.
|
|
83
|
+
|
|
84
|
+
Win probability in each game is
|
|
85
|
+
|
|
86
|
+
P(win) = Φ( (net_team − net_opp + 2h·v) · poss_game / 100 / σ_margin )
|
|
87
|
+
|
|
88
|
+
`σ_margin` is fitted each season as the root-mean-square gap between actual and
|
|
89
|
+
expected margins: 11.7 points in 2026 and 12.2 in 2025. WAR is the sum over the
|
|
90
|
+
team's games of `P(win | net_team) − P(win | net_team − Δ)`, computed for 4,000
|
|
91
|
+
draws of the player's net rating from its posterior. The headline figure is the
|
|
92
|
+
median of those draws.
|
|
93
|
+
|
|
94
|
+
`war_linear` is the derivative of the same sum times Δ. It agrees with the
|
|
95
|
+
simulation for small impacts and understates it for a star on a dominant team,
|
|
96
|
+
where removing the player moves close games into toss-up territory.
|
|
97
|
+
|
|
98
|
+
A Pythagorean exponent fitted on raw season efficiencies is 7.6 (2026) and 7.8
|
|
99
|
+
(2025). Published exponents of 10.25-11.5 use schedule-adjusted efficiencies. The
|
|
100
|
+
package reports the fitted exponent as a check and does not use it for WAR.
|
|
101
|
+
|
|
102
|
+
## 4. Program value
|
|
103
|
+
|
|
104
|
+
**Revenue response.** On school-seasons 2012-2025, excluding 2020 (tournament
|
|
105
|
+
cancelled) and 2021 (attendance limits):
|
|
106
|
+
|
|
107
|
+
log R_st = a_s + g_t + b0·W_st + b1·W_s,t−1 + d0·Bid_st + d1·Bid_s,t−1 + e_st
|
|
108
|
+
|
|
109
|
+
School effects absorb brand, market and conference; season effects absorb league
|
|
110
|
+
growth. Only rows where reported revenue differs from expense enter the fit: 61% of
|
|
111
|
+
D1 rows report the two as equal, which means the school allocates revenue to the
|
|
112
|
+
sport rather than measuring it. The fit uses 1,370 school-seasons from 167 schools
|
|
113
|
+
with at least four usable seasons. A bootstrap over schools gives 400 replicates.
|
|
114
|
+
|
|
115
|
+
| Effect (current + next season) | Median | 80% interval |
|
|
116
|
+
| --- | --- | --- |
|
|
117
|
+
| One win, log revenue | 0.0063 | 0.0037 to 0.0089 |
|
|
118
|
+
| NCAA bid, log revenue | 0.053 | 0.015 to 0.091 |
|
|
119
|
+
|
|
120
|
+
A win is worth `(b0 + b1) · R̄` where `R̄` is the school's mean reported revenue over
|
|
121
|
+
its latest three seasons. For Michigan (`R̄` = $21.0M) that is about $130k a win.
|
|
122
|
+
|
|
123
|
+
**Tournament bids.** A logistic model of bid on win percentage, power-conference
|
|
124
|
+
membership and their interaction, fitted on 2011-2026 except 2020 and 2021. A player's WAR changes his
|
|
125
|
+
team's win percentage by `WAR / games`, which changes the bid probability.
|
|
126
|
+
|
|
127
|
+
**Tournament units.** A conference earns one unit per game a member plays, except
|
|
128
|
+
the championship game; the data give 1.94 units per bid. A unit is worth about
|
|
129
|
+
$2M paid over six years (undiscounted). The school's share defaults to an equal
|
|
130
|
+
split among conference members, a user assumption, which makes this component and
|
|
131
|
+
total program value a scenario.
|
|
132
|
+
|
|
133
|
+
**What is missing.** Conference media distributions, donations and licensing that
|
|
134
|
+
EADA does not attribute to men's basketball, and effects beyond one season. Program
|
|
135
|
+
value is a lower bound on value to the university.
|
|
136
|
+
|
|
137
|
+
## 5. Roster market value
|
|
138
|
+
|
|
139
|
+
No public dataset records what individual college basketball players are paid, so
|
|
140
|
+
v0.1 allocates a reported budget rather than predicting pay.
|
|
141
|
+
|
|
142
|
+
**Budget.** Opendorse's 2025-26 study, as reported in March 2026, gives average
|
|
143
|
+
men's basketball roster spending of $7-10M in the ACC, Big 12, Big East, Big Ten
|
|
144
|
+
and SEC; $2-5M for a "B tier"; and $1-2M for a "C tier". The study does not list
|
|
145
|
+
B-tier members; the package assigns the AAC, Atlantic 10, Mountain West, WCC and
|
|
146
|
+
MVC as a user assumption. Budgets are lognormal with the cited range as the central
|
|
147
|
+
80%. For context, the House settlement caps school revenue sharing at about $20.5M
|
|
148
|
+
across all sports in 2025-26; the budgets above also include collective money.
|
|
149
|
+
|
|
150
|
+
**Roles.** Players are ranked by possessions. The top five are starters, the next
|
|
151
|
+
three are rotation, the rest are bench, and anyone on the floor for under 5% of
|
|
152
|
+
possessions is unpaid. The same study reports rotation players earn 15-25% less than
|
|
153
|
+
starters and bench players 30-55% less; each draw samples a ratio from those ranges.
|
|
154
|
+
|
|
155
|
+
**Impact within a role.** Pay within a role is proportional to
|
|
156
|
+
`max(net − R, 0.5)^κ` with κ = 1, normalized to the role mean so the role ratios
|
|
157
|
+
still hold. Every draw samples the budget, ratios and player ratings.
|
|
158
|
+
|
|
159
|
+
The allocation sums to the budget in every draw. It says what a team spending an
|
|
160
|
+
average budget in its tier would pay if it paid by role and on-court impact. It
|
|
161
|
+
does not see recruiting rank, draft stock, transfer leverage or social following,
|
|
162
|
+
which the study and other research say drive real contracts. That is why it is
|
|
163
|
+
labelled a scenario and why the deal registry exists.
|
|
164
|
+
|
|
165
|
+
## 6. Surplus and quadrant
|
|
166
|
+
|
|
167
|
+
Surplus is program value minus price, draw by draw. When the deal registry holds a
|
|
168
|
+
disclosed figure for the player-season it replaces the allocation as the price.
|
|
169
|
+
|
|
170
|
+
The value-vs-price quadrant compares a player's median program value and price with
|
|
171
|
+
the medians of his paid teammates. It is a within-team comparison, not a league
|
|
172
|
+
ranking.
|
|
173
|
+
|
|
174
|
+
## 7. Reproducing
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
uv sync --group dev
|
|
178
|
+
uv run pytest # offline suite, synthetic seasons
|
|
179
|
+
uv run pytest -m network # full 2025 and 2026 fits against live data
|
|
180
|
+
athletevalue validate --season 2026
|
|
181
|
+
athletevalue fit --season 2026 --cv
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Every download is recorded in `manifest.json` in the cache with its URL, SHA-256,
|
|
185
|
+
size, retrieval time and license.
|