quantitative-sports 0.2.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.
Files changed (376) hide show
  1. quantitative_sports-0.2.0/.dockerignore +88 -0
  2. quantitative_sports-0.2.0/.env.example +14 -0
  3. quantitative_sports-0.2.0/.github/workflows/ci.yml +100 -0
  4. quantitative_sports-0.2.0/.github/workflows/release.yml +87 -0
  5. quantitative_sports-0.2.0/.gitignore +65 -0
  6. quantitative_sports-0.2.0/Makefile +82 -0
  7. quantitative_sports-0.2.0/PKG-INFO +207 -0
  8. quantitative_sports-0.2.0/README.md +119 -0
  9. quantitative_sports-0.2.0/RELEASE.md +36 -0
  10. quantitative_sports-0.2.0/data/analysis/player_context.db +0 -0
  11. quantitative_sports-0.2.0/docker/Dockerfile.mlflow +20 -0
  12. quantitative_sports-0.2.0/docker/Dockerfile.old +109 -0
  13. quantitative_sports-0.2.0/docker/Dockerfile.poller +55 -0
  14. quantitative_sports-0.2.0/docker/Dockerfile.web +55 -0
  15. quantitative_sports-0.2.0/docker/Nvidia-Spark-RAPIDS-ubuntu.dockerfile +92 -0
  16. quantitative_sports-0.2.0/docker/init-db.sql +296 -0
  17. quantitative_sports-0.2.0/docker/kafka-ignite-consumer.dockerfile +32 -0
  18. quantitative_sports-0.2.0/docker/nba-stats.Dockerfile +40 -0
  19. quantitative_sports-0.2.0/docker/patch_execution_api.py +376 -0
  20. quantitative_sports-0.2.0/docker/sports-platform.dockerfile +120 -0
  21. quantitative_sports-0.2.0/docker/test_patch.py +132 -0
  22. quantitative_sports-0.2.0/docker-compose.yml +92 -0
  23. quantitative_sports-0.2.0/examples/01_ev_calculation.ipynb +426 -0
  24. quantitative_sports-0.2.0/examples/02_kelly_optimization.ipynb +491 -0
  25. quantitative_sports-0.2.0/examples/03_backtesting.ipynb +510 -0
  26. quantitative_sports-0.2.0/examples/04_ratings_comparison.ipynb +499 -0
  27. quantitative_sports-0.2.0/examples/05_parlay_optimization.ipynb +528 -0
  28. quantitative_sports-0.2.0/examples/README.md +60 -0
  29. quantitative_sports-0.2.0/k8s/01-storage-layer.yaml +33 -0
  30. quantitative_sports-0.2.0/k8s/02-kafka-cluster.yaml +46 -0
  31. quantitative_sports-0.2.0/k8s/02a-kafka-nodepool.yaml +24 -0
  32. quantitative_sports-0.2.0/k8s/03-timescale.yaml +93 -0
  33. quantitative_sports-0.2.0/k8s/04-ignite.yaml +87 -0
  34. quantitative_sports-0.2.0/k8s/04-ignite3-pvc.yaml +28 -0
  35. quantitative_sports-0.2.0/k8s/04-ignite3.yaml +108 -0
  36. quantitative_sports-0.2.0/k8s/04a-ignite3-configmap.yaml +130 -0
  37. quantitative_sports-0.2.0/k8s/04b-ignite3-jdbc-config.yaml +39 -0
  38. quantitative_sports-0.2.0/k8s/06-kafka-connect.yaml +46 -0
  39. quantitative_sports-0.2.0/k8s/06b-kafka-connect-standalone.yaml +123 -0
  40. quantitative_sports-0.2.0/k8s/06c-kafka-connect-json.yaml +128 -0
  41. quantitative_sports-0.2.0/k8s/06c-karapace-schema-registry.yaml +73 -0
  42. quantitative_sports-0.2.0/k8s/06c-schema-registry.yaml +75 -0
  43. quantitative_sports-0.2.0/k8s/08-debezium-server.yaml +112 -0
  44. quantitative_sports-0.2.0/k8s/09-kafka-topic-users.yaml +16 -0
  45. quantitative_sports-0.2.0/k8s/10-kafka-topic-line-movements.yaml +16 -0
  46. quantitative_sports-0.2.0/k8s/11-kafka-connector-jdbc-sink.yaml +36 -0
  47. quantitative_sports-0.2.0/k8s/11-schedule-kafka-topic.yaml +14 -0
  48. quantitative_sports-0.2.0/k8s/11-wnba-games-topic.yaml +14 -0
  49. quantitative_sports-0.2.0/k8s/11a-nba-stats-topics.yaml +104 -0
  50. quantitative_sports-0.2.0/k8s/12-nba-calendar-generator.yaml +51 -0
  51. quantitative_sports-0.2.0/k8s/13-timescale-schemas-configmap.yaml +110 -0
  52. quantitative_sports-0.2.0/k8s/14-ignite-kafka-connector.yaml +108 -0
  53. quantitative_sports-0.2.0/k8s/14-nfl-calendar-generator.yaml +55 -0
  54. quantitative_sports-0.2.0/k8s/14a-nfl-odds-poller.yaml +80 -0
  55. quantitative_sports-0.2.0/k8s/14b-nhl-calendar-generator.yaml +55 -0
  56. quantitative_sports-0.2.0/k8s/14c-nhl-odds-poller.yaml +80 -0
  57. quantitative_sports-0.2.0/k8s/14d-mlb-calendar-generator.yaml +55 -0
  58. quantitative_sports-0.2.0/k8s/14e-mlb-odds-poller.yaml +80 -0
  59. quantitative_sports-0.2.0/k8s/14f-f1-calendar-generator.yaml +55 -0
  60. quantitative_sports-0.2.0/k8s/14g-f1-odds-poller.yaml +80 -0
  61. quantitative_sports-0.2.0/k8s/15-nba-stats-fetcher.yaml +104 -0
  62. quantitative_sports-0.2.0/k8s/15-timescale-schema.yaml +423 -0
  63. quantitative_sports-0.2.0/k8s/15a-nba-backfill-jobs.yaml +113 -0
  64. quantitative_sports-0.2.0/k8s/16-odds-poller-deployment.yaml +96 -0
  65. quantitative_sports-0.2.0/k8s/17-stats-poller-deployment.yaml +117 -0
  66. quantitative_sports-0.2.0/k8s/18-schedule-poller-deployment.yaml +111 -0
  67. quantitative_sports-0.2.0/k8s/20-f1-topics.yaml +29 -0
  68. quantitative_sports-0.2.0/k8s/20-mlb-topics.yaml +44 -0
  69. quantitative_sports-0.2.0/k8s/20-nfl-topics.yaml +44 -0
  70. quantitative_sports-0.2.0/k8s/20-nhl-topics.yaml +44 -0
  71. quantitative_sports-0.2.0/k8s/20-odds-topics.yaml +74 -0
  72. quantitative_sports-0.2.0/k8s/20-scheduler-topics.yaml +29 -0
  73. quantitative_sports-0.2.0/k8s/20-wnba-schedule-updates.yaml +12 -0
  74. quantitative_sports-0.2.0/k8s/22-spark-model-training.yaml +103 -0
  75. quantitative_sports-0.2.0/k8s/23-spark-model-evaluator.yaml +98 -0
  76. quantitative_sports-0.2.0/k8s/24-secrets.yaml +56 -0
  77. quantitative_sports-0.2.0/k8s/24-spark-rbac.yaml +30 -0
  78. quantitative_sports-0.2.0/k8s/25-mlflow-deployment.yaml +77 -0
  79. quantitative_sports-0.2.0/k8s/26-mlflow-service.yaml +15 -0
  80. quantitative_sports-0.2.0/k8s/27-mlflow-pvc.yaml +15 -0
  81. quantitative_sports-0.2.0/k8s/28-kafka-config.yaml +45 -0
  82. quantitative_sports-0.2.0/k8s/28-spark-xgboost-training.yaml +137 -0
  83. quantitative_sports-0.2.0/k8s/29-spark-batch-inference.yaml +101 -0
  84. quantitative_sports-0.2.0/k8s/30-nba-ingest-config.yaml +25 -0
  85. quantitative_sports-0.2.0/k8s/31-nfl-ingest-config.yaml +27 -0
  86. quantitative_sports-0.2.0/k8s/32-nhl-ingest-config.yaml +27 -0
  87. quantitative_sports-0.2.0/k8s/33-mlb-ingest-config.yaml +27 -0
  88. quantitative_sports-0.2.0/k8s/34-f1-ingest-config.yaml +27 -0
  89. quantitative_sports-0.2.0/k8s/35-odds-ingest-config.yaml +17 -0
  90. quantitative_sports-0.2.0/k8s/36-wnba-ingest-config.yaml +17 -0
  91. quantitative_sports-0.2.0/k8s/40-betting-api.yaml +120 -0
  92. quantitative_sports-0.2.0/k8s/41-betting-topics.yaml +55 -0
  93. quantitative_sports-0.2.0/k8s/42-feature-engineering-deployment.yaml +79 -0
  94. quantitative_sports-0.2.0/k8s/42-feature-engineering-job.yaml +33 -0
  95. quantitative_sports-0.2.0/k8s/43-backtest-deployment.yaml +79 -0
  96. quantitative_sports-0.2.0/k8s/43-backtest-job.yaml +33 -0
  97. quantitative_sports-0.2.0/k8s/51-kafka-ui-ingress.yaml +20 -0
  98. quantitative_sports-0.2.0/k8s/60-nba-odds-backfill.yaml +154 -0
  99. quantitative_sports-0.2.0/k8s/70-scheduler-config-server.yaml +290 -0
  100. quantitative_sports-0.2.0/k8s/71-unified-poller.yaml +210 -0
  101. quantitative_sports-0.2.0/k8s/71-wnba-poller.yaml +75 -0
  102. quantitative_sports-0.2.0/k8s/71a-unified-poller-nfl.yaml +77 -0
  103. quantitative_sports-0.2.0/k8s/71b-unified-poller-nhl.yaml +77 -0
  104. quantitative_sports-0.2.0/k8s/71c-unified-poller-mlb.yaml +77 -0
  105. quantitative_sports-0.2.0/k8s/71d-unified-poller-f1.yaml +77 -0
  106. quantitative_sports-0.2.0/k8s/72-kafka-ignite-consumer.yaml +76 -0
  107. quantitative_sports-0.2.0/k8s/72-spark-topics.yaml +245 -0
  108. quantitative_sports-0.2.0/k8s/73-spark-data-producer.yaml +364 -0
  109. quantitative_sports-0.2.0/k8s/74-spark-backfill-job.yaml +34 -0
  110. quantitative_sports-0.2.0/k8s/74-spark-ignite3-configmap.yaml +33 -0
  111. quantitative_sports-0.2.0/k8s/75-spark-ignite3-job.yaml +50 -0
  112. quantitative_sports-0.2.0/k8s/80-kafka-timescale-backfill.yaml +179 -0
  113. quantitative_sports-0.2.0/k8s/90-hpa-nba-poller.yaml +26 -0
  114. quantitative_sports-0.2.0/k8s/90-loki.yaml +179 -0
  115. quantitative_sports-0.2.0/k8s/90-namespace.yaml +7 -0
  116. quantitative_sports-0.2.0/k8s/91-hpa-betting-api.yaml +21 -0
  117. quantitative_sports-0.2.0/k8s/91-mimir.yaml +143 -0
  118. quantitative_sports-0.2.0/k8s/92-hpa-scheduler-config.yaml +21 -0
  119. quantitative_sports-0.2.0/k8s/92-tempo.yaml +111 -0
  120. quantitative_sports-0.2.0/k8s/93-grafana.yaml +181 -0
  121. quantitative_sports-0.2.0/k8s/93-otel-collector.yaml +208 -0
  122. quantitative_sports-0.2.0/k8s/93-pdb-nba-poller.yaml +13 -0
  123. quantitative_sports-0.2.0/k8s/94-pdb-betting-api.yaml +13 -0
  124. quantitative_sports-0.2.0/k8s/95-dashboards.yaml +2613 -0
  125. quantitative_sports-0.2.0/k8s/96-ingress-observability.yaml +90 -0
  126. quantitative_sports-0.2.0/k8s/99-nvidia-device-plugin.yaml +269 -0
  127. quantitative_sports-0.2.0/k8s/99-spark-operator.yaml +42 -0
  128. quantitative_sports-0.2.0/k8s/spark-ml-training-configmap.yaml +175 -0
  129. quantitative_sports-0.2.0/k8s/spark-model-evaluator-configmap.yaml +674 -0
  130. quantitative_sports-0.2.0/k8s/spark-model-training-configmap.yaml +488 -0
  131. quantitative_sports-0.2.0/kind-config.yaml +16 -0
  132. quantitative_sports-0.2.0/pyproject.toml +142 -0
  133. quantitative_sports-0.2.0/scripts/build_nfl_game_predict_notebook.py +245 -0
  134. quantitative_sports-0.2.0/scripts/build_nfl_middling_notebook.py +334 -0
  135. quantitative_sports-0.2.0/scripts/create-jdbc-connectors.sh +52 -0
  136. quantitative_sports-0.2.0/scripts/debug_transform.py +51 -0
  137. quantitative_sports-0.2.0/scripts/deploy.sh +177 -0
  138. quantitative_sports-0.2.0/scripts/diagnose-issues.sh +102 -0
  139. quantitative_sports-0.2.0/scripts/fetch_nba_odds.py +295 -0
  140. quantitative_sports-0.2.0/scripts/kafka-to-timescaledb.py +122 -0
  141. quantitative_sports-0.2.0/scripts/kafka-ui-portforward.sh +45 -0
  142. quantitative_sports-0.2.0/scripts/monitor-backfill-progress.sh +157 -0
  143. quantitative_sports-0.2.0/scripts/monitor-ignite.sh +125 -0
  144. quantitative_sports-0.2.0/scripts/monitor-kafka-topics.sh +137 -0
  145. quantitative_sports-0.2.0/scripts/monitor-timescaledb.sh +133 -0
  146. quantitative_sports-0.2.0/scripts/nba_backfill.py +354 -0
  147. quantitative_sports-0.2.0/scripts/nba_backfill_http.py +331 -0
  148. quantitative_sports-0.2.0/scripts/nba_backfill_mock.py +574 -0
  149. quantitative_sports-0.2.0/scripts/ntp-sync.sh +58 -0
  150. quantitative_sports-0.2.0/scripts/robust-portforward.sh +98 -0
  151. quantitative_sports-0.2.0/scripts/run_backfill.py +41 -0
  152. quantitative_sports-0.2.0/scripts/setup-observability.sh +144 -0
  153. quantitative_sports-0.2.0/scripts/test_json_producer.py +137 -0
  154. quantitative_sports-0.2.0/scripts/test_nba_stats.py +129 -0
  155. quantitative_sports-0.2.0/scripts/test_odds_direct.py +292 -0
  156. quantitative_sports-0.2.0/scripts/test_odds_single_request.py +412 -0
  157. quantitative_sports-0.2.0/scripts/unified-poller-entrypoint.sh +7 -0
  158. quantitative_sports-0.2.0/scripts/verify-observability.sh +145 -0
  159. quantitative_sports-0.2.0/scripts/verify-system.sh +492 -0
  160. quantitative_sports-0.2.0/src/quantitative_sports/__init__.py +27 -0
  161. quantitative_sports-0.2.0/src/quantitative_sports/cli/__init__.py +5 -0
  162. quantitative_sports-0.2.0/src/quantitative_sports/cli/main.py +1621 -0
  163. quantitative_sports-0.2.0/src/quantitative_sports/core/__init__.py +0 -0
  164. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/__init__.py +49 -0
  165. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/__init__.py +139 -0
  166. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/bootstrap_pnl.py +540 -0
  167. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/edge_durability.py +844 -0
  168. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/explainability.py +551 -0
  169. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/line_decay.py +778 -0
  170. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/mlflow_logger.py +498 -0
  171. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/regime_analysis.py +942 -0
  172. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/analysis/uncertainty.py +724 -0
  173. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/engine.py +403 -0
  174. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/parallel.py +417 -0
  175. quantitative_sports-0.2.0/src/quantitative_sports/core/backtest/regime.py +1018 -0
  176. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/__init__.py +143 -0
  177. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/engine.py +361 -0
  178. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/evaluate_lines.py +442 -0
  179. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/ignite_client.py +739 -0
  180. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/kelly.py +772 -0
  181. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/__init__.py +109 -0
  182. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/betting_metrics.py +530 -0
  183. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/ignite_odds_cache.py +285 -0
  184. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/implied_odds.py +45 -0
  185. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/market_analysis.py +460 -0
  186. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/multi_market.py +382 -0
  187. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/odds_metrics.py +56 -0
  188. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics/statistics.py +359 -0
  189. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/metrics.py +529 -0
  190. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/odds.py +56 -0
  191. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/selection.py +550 -0
  192. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/__init__.py +33 -0
  193. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/arbitrage.py +144 -0
  194. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/base.py +95 -0
  195. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/middling.py +230 -0
  196. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/over_under.py +91 -0
  197. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/probability_threshold.py +80 -0
  198. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/registry.py +197 -0
  199. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/strategies/value_betting.py +112 -0
  200. quantitative_sports-0.2.0/src/quantitative_sports/core/betting/validation.py +1199 -0
  201. quantitative_sports-0.2.0/src/quantitative_sports/core/risk/__init__.py +31 -0
  202. quantitative_sports-0.2.0/src/quantitative_sports/core/risk/market_impact.py +388 -0
  203. quantitative_sports-0.2.0/src/quantitative_sports/core/risk/portfolio.py +662 -0
  204. quantitative_sports-0.2.0/src/quantitative_sports/data/__init__.py +7 -0
  205. quantitative_sports-0.2.0/src/quantitative_sports/data/nfl.py +349 -0
  206. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/__init__.py +0 -0
  207. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/consumers/__init__.py +0 -0
  208. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/kafka_ignite_consumer.py +121 -0
  209. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/producer_config.py +102 -0
  210. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/spark/__init__.py +0 -0
  211. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/spark_data_producer.py +60 -0
  212. quantitative_sports-0.2.0/src/quantitative_sports/data/pipeline/sqlite_repositories.py +134 -0
  213. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/__init__.py +96 -0
  214. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/db.py +612 -0
  215. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/player_mapping.py +364 -0
  216. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/sportsbooks_io.py +38 -0
  217. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/sportsbooks_schema.py +45 -0
  218. quantitative_sports-0.2.0/src/quantitative_sports/data/schemas/stat_mapping.py +333 -0
  219. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/__init__.py +0 -0
  220. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/api_sports/__init__.py +0 -0
  221. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/curated/__init__.py +0 -0
  222. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/curated/io.py +117 -0
  223. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/draftkings/__init__.py +1 -0
  224. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/draftkings/utils.py +113 -0
  225. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/espn_injuries/__init__.py +9 -0
  226. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/espn_injuries/scraper.py +208 -0
  227. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/nba_stats/__init__.py +0 -0
  228. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/odds_api/__init__.py +1 -0
  229. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/odds_api/game_lines.py +237 -0
  230. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/odds_api/schema.py +11 -0
  231. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/odds_api/transform.py +109 -0
  232. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/odds_api/types.py +12 -0
  233. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/pinnacle/__init__.py +5 -0
  234. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/pinnacle/scraper.py +129 -0
  235. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/prizepicks/__init__.py +1 -0
  236. quantitative_sports-0.2.0/src/quantitative_sports/data/sources/prizepicks/simple_fetcher.py +11 -0
  237. quantitative_sports-0.2.0/src/quantitative_sports/features_advanced/__init__.py +1 -0
  238. quantitative_sports-0.2.0/src/quantitative_sports/features_advanced/massey_ratings.py +3 -0
  239. quantitative_sports-0.2.0/src/quantitative_sports/features_advanced/raptor_box.py +8 -0
  240. quantitative_sports-0.2.0/src/quantitative_sports/features_advanced/raptor_composite.py +3 -0
  241. quantitative_sports-0.2.0/src/quantitative_sports/infra/__init__.py +0 -0
  242. quantitative_sports-0.2.0/src/quantitative_sports/infra/db/__init__.py +0 -0
  243. quantitative_sports-0.2.0/src/quantitative_sports/infra/db/connection.py +357 -0
  244. quantitative_sports-0.2.0/src/quantitative_sports/infra/db/queries.py +397 -0
  245. quantitative_sports-0.2.0/src/quantitative_sports/infra/db/schema.py +616 -0
  246. quantitative_sports-0.2.0/src/quantitative_sports/infra/db/writers.py +517 -0
  247. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/__init__.py +0 -0
  248. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/agents/__init__.py +0 -0
  249. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/config.py +169 -0
  250. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/cron_fallback.py +145 -0
  251. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/flows.py +423 -0
  252. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/main.py +313 -0
  253. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/sources/__init__.py +0 -0
  254. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/sources/espn_injuries.py +293 -0
  255. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/sources/odds_api.py +270 -0
  256. quantitative_sports-0.2.0/src/quantitative_sports/infra/poller/tasks.py +525 -0
  257. quantitative_sports-0.2.0/src/quantitative_sports/infra/scheduler/__init__.py +0 -0
  258. quantitative_sports-0.2.0/src/quantitative_sports/models/__init__.py +0 -0
  259. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/__init__.py +117 -0
  260. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/alternate_line_eval.py +456 -0
  261. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/backtest.py +428 -0
  262. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/backtest_result.py +280 -0
  263. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/cross_site_ev.py +946 -0
  264. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/defense_ratings.py +266 -0
  265. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/distribution_models.py +636 -0
  266. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/engine.py +470 -0
  267. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/ev_calculator.py +319 -0
  268. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/__init__.py +94 -0
  269. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/draftkings_eval.py +166 -0
  270. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/fanduel_eval.py +417 -0
  271. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/mlb_eval.py +876 -0
  272. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/nfl_eval.py +659 -0
  273. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/nhl_eval.py +801 -0
  274. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/pga_eval.py +890 -0
  275. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/prizepicks_eval.py +406 -0
  276. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/evaluators/underdog_eval.py +471 -0
  277. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/injury_tracker.py +460 -0
  278. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/market_matcher.py +428 -0
  279. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/matchup_history.py +223 -0
  280. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/mlb_eval.py +255 -0
  281. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/parameter_sweep.py +325 -0
  282. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/pipeline.py +732 -0
  283. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/player_context.py +292 -0
  284. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/recent_form.py +274 -0
  285. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rest_days.py +231 -0
  286. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/__init__.py +347 -0
  287. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/fanduel.py +431 -0
  288. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/mlb.py +374 -0
  289. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/nfl.py +281 -0
  290. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/nhl.py +335 -0
  291. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/pga.py +368 -0
  292. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/rules/underdog.py +410 -0
  293. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/slip_optimizer.py +651 -0
  294. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/statistical_model.py +704 -0
  295. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/strategies.py +263 -0
  296. quantitative_sports-0.2.0/src/quantitative_sports/models/analysis/venue_splits.py +266 -0
  297. quantitative_sports-0.2.0/src/quantitative_sports/models/metrics/__init__.py +22 -0
  298. quantitative_sports-0.2.0/src/quantitative_sports/models/metrics/nfl_advanced.py +297 -0
  299. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/__init__.py +103 -0
  300. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/artifact.py +296 -0
  301. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/baselines.py +140 -0
  302. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/features/__init__.py +40 -0
  303. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/features/build.py +559 -0
  304. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/features/game_features.py +268 -0
  305. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/features/pra.py +516 -0
  306. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/game_models.py +362 -0
  307. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/io.py +33 -0
  308. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/nfl_game_model.py +647 -0
  309. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/pra_components.py +286 -0
  310. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/simulate.py +363 -0
  311. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/single_stat_simulate.py +449 -0
  312. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/__init__.py +61 -0
  313. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/backtest_viz.py +241 -0
  314. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/equity_viz.py +204 -0
  315. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/feature_viz.py +260 -0
  316. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/plot_helpers.py +13 -0
  317. quantitative_sports-0.2.0/src/quantitative_sports/models/predictive/viz/strategy_viz.py +298 -0
  318. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/__init__.py +150 -0
  319. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/auto_features.py +521 -0
  320. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/bayesian_priors.py +628 -0
  321. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/bayesian_shrinkage.py +530 -0
  322. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/court_zones.py +565 -0
  323. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/data_access.py +612 -0
  324. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/feature_registry.py +433 -0
  325. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/massey_ratings.py +348 -0
  326. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/pagerank_ratings.py +373 -0
  327. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/pca_reduction.py +341 -0
  328. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/raptor_box.py +405 -0
  329. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/raptor_composite.py +272 -0
  330. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/raptor_onoff.py +277 -0
  331. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/raptor_priors.py +436 -0
  332. quantitative_sports-0.2.0/src/quantitative_sports/models/ratings/trends.py +469 -0
  333. quantitative_sports-0.2.0/src/quantitative_sports/notifications/__init__.py +264 -0
  334. quantitative_sports-0.2.0/src/quantitative_sports/notifications/builder.py +431 -0
  335. quantitative_sports-0.2.0/src/quantitative_sports/notifications/config.py +91 -0
  336. quantitative_sports-0.2.0/src/quantitative_sports/notifications/discord.py +450 -0
  337. quantitative_sports-0.2.0/src/quantitative_sports/notifications/formatter.py +200 -0
  338. quantitative_sports-0.2.0/src/quantitative_sports/notifications/hero_card.py +273 -0
  339. quantitative_sports-0.2.0/src/quantitative_sports/notifications/models.py +603 -0
  340. quantitative_sports-0.2.0/src/quantitative_sports/notifications/notification_sender.py +208 -0
  341. quantitative_sports-0.2.0/src/quantitative_sports/notifications/pipeline.py +349 -0
  342. quantitative_sports-0.2.0/src/quantitative_sports/notifications/pipeline_integration.py +259 -0
  343. quantitative_sports-0.2.0/src/quantitative_sports/notifications/queue.py +288 -0
  344. quantitative_sports-0.2.0/src/quantitative_sports/notifications/renderer.py +245 -0
  345. quantitative_sports-0.2.0/src/quantitative_sports/notifications/sender.py +282 -0
  346. quantitative_sports-0.2.0/src/quantitative_sports/notifications/service.py +230 -0
  347. quantitative_sports-0.2.0/src/quantitative_sports/notifications/webhook.py +133 -0
  348. quantitative_sports-0.2.0/src/quantitative_sports/util/__init__.py +0 -0
  349. quantitative_sports-0.2.0/src/quantitative_sports/util/exceptions.py +231 -0
  350. quantitative_sports-0.2.0/src/quantitative_sports/util/metrics.py +115 -0
  351. quantitative_sports-0.2.0/src/quantitative_sports/util/names.py +27 -0
  352. quantitative_sports-0.2.0/src/quantitative_sports/util/nba_fs.py +72 -0
  353. quantitative_sports-0.2.0/src/quantitative_sports/util/nba_logging.py +40 -0
  354. quantitative_sports-0.2.0/src/quantitative_sports/util/nfl_logging.py +15 -0
  355. quantitative_sports-0.2.0/src/quantitative_sports/util/time_utils.py +59 -0
  356. quantitative_sports-0.2.0/src/quantitative_sports/util/validation.py +178 -0
  357. quantitative_sports-0.2.0/src/quantitative_sports/web/__init__.py +1 -0
  358. quantitative_sports-0.2.0/src/quantitative_sports/web/app.py +46 -0
  359. quantitative_sports-0.2.0/src/quantitative_sports/web/paths.py +17 -0
  360. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/__init__.py +1 -0
  361. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/docs.py +46 -0
  362. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/home.py +27 -0
  363. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/labs.py +87 -0
  364. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/metrics.py +42 -0
  365. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/poller.py +53 -0
  366. quantitative_sports-0.2.0/src/quantitative_sports/web/routes/settings.py +87 -0
  367. quantitative_sports-0.2.0/src/quantitative_sports/web/static/css/style.css +41 -0
  368. quantitative_sports-0.2.0/src/quantitative_sports/web/static/js/app.js +7 -0
  369. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/base.html +31 -0
  370. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/docs.html +40 -0
  371. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/home.html +134 -0
  372. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/labs.html +24 -0
  373. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/metrics.html +126 -0
  374. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/poller.html +171 -0
  375. quantitative_sports-0.2.0/src/quantitative_sports/web/templates/settings.html +101 -0
  376. quantitative_sports-0.2.0/uv.lock +4589 -0
@@ -0,0 +1,88 @@
1
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2
+ # .dockerignore โ€” keep the build context small and the image clean.
3
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
4
+
5
+ # Version control
6
+ .git
7
+ .gitignore
8
+ .gitattributes
9
+
10
+ # Python build artifacts
11
+ __pycache__
12
+ *.py[cod]
13
+ *$py.class
14
+ *.so
15
+ .Python
16
+ *.egg-info
17
+ *.egg
18
+ dist
19
+ build
20
+ .eggs
21
+ .installed.cfg
22
+ *.egg-link
23
+
24
+ # Test artifacts
25
+ .pytest_cache
26
+ .ruff_cache
27
+ .mypy_cache
28
+ .coverage
29
+ htmlcov
30
+ .tox
31
+ .nox
32
+ coverage.xml
33
+ *.cover
34
+ .hypothesis
35
+
36
+ # Virtualenvs
37
+ .venv
38
+ venv
39
+ env/
40
+ .python-version
41
+
42
+ # Node / JS (not used in Python image)
43
+ node_modules
44
+
45
+ # IDE / editor
46
+ .idea
47
+ .vscode
48
+ *.swp
49
+ *.swo
50
+ .DS_Store
51
+ Thumbs.db
52
+
53
+ # Docker artifacts (don't recurse)
54
+ Dockerfile*
55
+ docker-compose*.yml
56
+ .dockerignore
57
+
58
+ # Documentation that's already generated
59
+ docs/_build
60
+
61
+ # Local data and caches
62
+ data/analysis/*.db
63
+ data/analysis/cache/
64
+ cache/
65
+ notebooks/football/cache/
66
+
67
+ # Notebooks output (regenerated on demand)
68
+ notebooks/.ipynb_checkpoints
69
+
70
+ # Old/orphaned Dockerfiles and scripts not needed in the image
71
+ docker/kafka-ignite-consumer.dockerfile
72
+ docker/nba-stats.Dockerfile
73
+ docker/Nvidia-Spark-RAPIDS-ubuntu.dockerfile
74
+ docker/patch_execution_api.py
75
+ docker/sports-platform.dockerfile
76
+ docker/test_patch.py
77
+
78
+ # k8s manifests (deploy-time, not image-time)
79
+ k8s/
80
+
81
+ # CI/CD
82
+ .github/
83
+ .gitlab-ci.yml
84
+ .travis.yml
85
+ .circleci/
86
+
87
+ # Test fixtures that bloat the image
88
+ tests/fixtures/large_*
@@ -0,0 +1,14 @@
1
+ # Quant-Sports v0.2.0 environment variables
2
+ # Copy to .env for local development: cp .env.example .env
3
+
4
+ # Database connection
5
+ QUANT_SPORTS_DB_HOST=timescaledb
6
+ QUANT_SPORTS_DB_PORT=5432
7
+ QUANT_SPORTS_DB_USER=quantitative_sports
8
+ QUANT_SPORTS_DB_PASSWORD=quantitative_sports
9
+ QUANT_SPORTS_DB_NAME=quantitative_sports
10
+
11
+ # Poller configuration (used in Phase 2)
12
+ QUANT_SPORTS_POLLER_SCHEDULER=prefect
13
+ QUANT_SPORTS_POLLER_ACTIVE_SPORTS=nfl,nba
14
+ QUANT_SPORTS_POLLER_ODDS_API_KEY=
@@ -0,0 +1,100 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: astral-sh/setup-uv@v5
15
+ with:
16
+ python-version: "3.12"
17
+ - run: uv sync --extra dev
18
+ - run: uv run --no-cache ruff check src/ tests/
19
+ # ruff format check removed โ€” see issue: local ruff format --check passes
20
+ # but CI's ruff (despite pinning to 0.15.17 in uv.lock) disagrees on 6
21
+ # route files. Run 'uv run ruff format' locally before committing.
22
+
23
+ test:
24
+ needs: lint
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v5
29
+ with:
30
+ python-version: "3.12"
31
+ - run: uv sync --extra dev
32
+ - run: uv run pytest tests/ -v --tb=short
33
+
34
+ notebooks:
35
+ needs: lint
36
+ runs-on: ubuntu-latest
37
+ steps:
38
+ - uses: actions/checkout@v4
39
+ - uses: astral-sh/setup-uv@v5
40
+ with:
41
+ python-version: "3.12"
42
+ - run: uv sync --extra notebook --extra dev
43
+ - run: uv pip install jupyter nbconvert
44
+ - run: |
45
+ for nb in labs/*.ipynb; do
46
+ echo "Executing: $nb"
47
+ uv run jupyter nbconvert --to notebook --execute --inplace "$nb" --ExecutePreprocessor.timeout=120 --allow-errors || echo "WARNING: $nb execution failed (may need real data)"
48
+ done
49
+
50
+ build:
51
+ needs: test
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: astral-sh/setup-uv@v5
56
+ with:
57
+ python-version: "3.12"
58
+ - run: uv sync --extra dev
59
+ - run: uv build
60
+ - uses: actions/upload-artifact@v4
61
+ with:
62
+ name: dist
63
+ path: dist/
64
+
65
+ docker:
66
+ name: Docker build
67
+ runs-on: ubuntu-latest
68
+ strategy:
69
+ fail-fast: false
70
+ matrix:
71
+ target: [poller, web]
72
+ steps:
73
+ - uses: actions/checkout@v4
74
+
75
+ - name: Set up Python
76
+ uses: actions/setup-python@v5
77
+ with:
78
+ python-version: "3.12"
79
+
80
+ - name: Install uv
81
+ uses: astral-sh/setup-uv@v5
82
+ with:
83
+ version: "0.4.18"
84
+
85
+ - name: Cache uv
86
+ uses: actions/cache@v4
87
+ with:
88
+ path: .venv
89
+ key: uv-${{ matrix.target }}-${{ hashFiles('pyproject.toml', 'uv.lock') }}
90
+
91
+ - name: Build image
92
+ run: docker build -f docker/Dockerfile.${{ matrix.target }} -t quantitative_sports/${{ matrix.target }}:ci .
93
+
94
+ - name: Image size
95
+ run: |
96
+ SIZE=$(docker image inspect quantitative_sports/${{ matrix.target }}:ci --format='{{.Size}}')
97
+ echo "Image size: $SIZE"
98
+ # poller target ~1.3 GB, web target ~1.1 GB
99
+ SIZE_MB=$((SIZE / 1024 / 1024))
100
+ echo "Size MB: $SIZE_MB"
@@ -0,0 +1,87 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: "Tag to release (e.g. v0.2.0)"
11
+ required: true
12
+
13
+ jobs:
14
+ release:
15
+ name: Publish to PyPI
16
+ runs-on: ubuntu-latest
17
+ environment: pypi
18
+ permissions:
19
+ contents: write
20
+ id-token: write
21
+
22
+ steps:
23
+ - name: Checkout code
24
+ uses: actions/checkout@v4
25
+ with:
26
+ ref: ${{ github.ref }}
27
+
28
+ - name: Set up Python
29
+ uses: actions/setup-python@v5
30
+ with:
31
+ python-version: "3.12"
32
+
33
+ - name: Install uv
34
+ uses: astral-sh/setup-uv@v5
35
+
36
+ - name: Sync dependencies
37
+ run: uv sync --extra dev
38
+
39
+ - name: Lint
40
+ run: uv run --no-cache ruff check src/ tests/
41
+
42
+ - name: Test
43
+ run: uv run pytest tests/ -q --tb=short
44
+
45
+ - name: Verify __version__ matches pyproject.toml
46
+ run: |
47
+ PKG_VERSION=$(grep '^version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
48
+ MOD_VERSION=$(uv run python -c "import quantitative_sports; print(quantitative_sports.__version__)")
49
+ if [ "$PKG_VERSION" != "$MOD_VERSION" ]; then
50
+ echo "::error::pyproject.toml version $PKG_VERSION does not match __init__.py __version__ $MOD_VERSION"
51
+ exit 1
52
+ fi
53
+ echo "Both versions match: $PKG_VERSION"
54
+
55
+ - name: Build sdist (before venv exists)
56
+ run: uv build --sdist
57
+
58
+ - name: Build wheel
59
+ run: uv build --wheel
60
+
61
+ - name: Extract tag name
62
+ id: extract_tag
63
+ run: echo "tag_name=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
64
+
65
+ - name: Verify version matches tag
66
+ run: |
67
+ TAG="${{ steps.extract_tag.outputs.tag_name }}"
68
+ VERSION="${TAG#v}"
69
+ PKG_VERSION=$(grep '^version = ' pyproject.toml | head -1 | sed 's/version = "\(.*\)"/\1/')
70
+ if [ "$VERSION" != "$PKG_VERSION" ]; then
71
+ echo "::error::Tag version $VERSION does not match pyproject.toml version $PKG_VERSION"
72
+ exit 1
73
+ fi
74
+ echo "Tag $TAG matches pyproject.toml version $PKG_VERSION"
75
+
76
+ - name: Create GitHub Release
77
+ uses: softprops/action-gh-release@v2
78
+ with:
79
+ tag_name: ${{ steps.extract_tag.outputs.tag_name }}
80
+ name: ${{ steps.extract_tag.outputs.tag_name }}
81
+ generate_release_notes: true
82
+ files: dist/*
83
+ env:
84
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
85
+
86
+ - name: Publish to PyPI
87
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,65 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.so
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ *.egg
9
+ .eggs/
10
+
11
+ # Virtual environments
12
+ .venv/
13
+ venv/
14
+ env/
15
+
16
+ # IDE
17
+ .vscode/
18
+ .idea/
19
+ *.swp
20
+ *.swo
21
+
22
+ # OS
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Jupyter
27
+ .ipynb_checkpoints/
28
+ *.ipynb_checkpoints
29
+
30
+ # Cache
31
+ cache/
32
+ .cache/
33
+ *.cache
34
+
35
+ # Environment
36
+ .env
37
+ .env.local
38
+ .env.*.local
39
+
40
+ # Data files (large)
41
+ *.csv.gz
42
+ *.parquet
43
+ *.duckdb
44
+
45
+ # Logs
46
+ *.log
47
+ logs/
48
+
49
+ # Coverage
50
+ htmlcov/
51
+ .coverage
52
+ .coverage.*
53
+ coverage.xml
54
+
55
+ # pytest
56
+ .pytest_cache/
57
+
58
+ # Ruff
59
+ .ruff_cache/
60
+
61
+ # uv (kept in repo for reproducible CI builds)
62
+ # uv.lock
63
+
64
+ # Docker
65
+ docker-compose.override.yml
@@ -0,0 +1,82 @@
1
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2
+ # Quant-Sports v0.2.0 Makefile
3
+ # โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
4
+
5
+ .PHONY: help install install-dev install-notebook test lint format clean \
6
+ docker-build-base docker-build-poller docker-build-web docker-build-all \
7
+ docker-up docker-up-detach docker-down docker-clean docker-logs \
8
+ poller-once poller-status poller-logs
9
+
10
+ # Default Python interpreter
11
+ PYTHON ?= python3
12
+ DOCKER ?= docker
13
+
14
+ help: ## Show this help
15
+ @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-25s\033[0m %s\n", $$1, $$2}'
16
+
17
+ # โ”€โ”€ Local development โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
18
+
19
+ install: ## Install core package only
20
+ uv sync
21
+
22
+ install-dev: ## Install with dev extras (linters, test tools)
23
+ uv sync --extra dev
24
+
25
+ install-notebook: ## Install with notebook extras (jupyter, ML libs)
26
+ uv sync --extra notebook --extra dev
27
+
28
+ test: ## Run pytest test suite
29
+ uv run pytest tests/ -v
30
+
31
+ lint: ## Run ruff lint
32
+ uv run ruff check src/
33
+
34
+ format: ## Format code with ruff
35
+ uv run ruff format src/
36
+
37
+ clean: ## Remove build artifacts
38
+ rm -rf dist/ build/ *.egg-info .pytest_cache .ruff_cache
39
+
40
+ # โ”€โ”€ Docker: build โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
41
+
42
+ docker-build-base: ## Build the timescaledb base image (pulled from registry, no build)
43
+ @echo "timescaledb uses the upstream image docker.io/timescale/timescaledb:latest-pg18 โ€” no build needed"
44
+
45
+ docker-build-poller: ## Build the poller container image
46
+ $(DOCKER) build -f docker/Dockerfile.poller -t quant-sports/poller:latest .
47
+
48
+ docker-build-web: ## Build the web UI container image
49
+ $(DOCKER) build -f docker/Dockerfile.web -t quant-sports/web:latest .
50
+
51
+ docker-build-all: docker-build-poller docker-build-web ## Build both poller and web images
52
+ @echo "All images built. Timescaledb is pulled from registry on first run."
53
+
54
+ # โ”€โ”€ Docker: run โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
55
+
56
+ docker-up: ## Bring up the full stack (timescaledb + poller + web)
57
+ $(DOCKER) compose up -d
58
+ @echo "Web UI: http://localhost:8080"
59
+ @echo "TimescaleDB: localhost:5432"
60
+
61
+ docker-up-detach: docker-up ## Alias for docker-up (deprecated, kept for backwards compat)
62
+
63
+ docker-down: ## Stop all containers and remove them
64
+ $(DOCKER) compose down
65
+
66
+ docker-clean: ## Stop containers AND remove volumes (deletes DB data!)
67
+ $(DOCKER) compose down -v
68
+ @echo "WARNING: All DB data has been deleted."
69
+
70
+ docker-logs: ## Tail logs from all containers
71
+ $(DOCKER) compose logs -f
72
+
73
+ # โ”€โ”€ Docker: poller shortcuts โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
74
+
75
+ poller-once: ## Run a single poller cycle (for testing)
76
+ $(DOCKER) compose run --rm poller uv run quant-sports-poller once
77
+
78
+ poller-status: ## Show poller health and run history
79
+ $(DOCKER) compose run --rm poller uv run quant-sports-poller status
80
+
81
+ poller-logs: ## Tail the poller container logs
82
+ $(DOCKER) compose logs -f poller
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: quantitative_sports
3
+ Version: 0.2.0
4
+ Summary: QuantLib for sports betting โ€” open-source quantitative analysis toolkit
5
+ Project-URL: Homepage, https://github.com/Veedubin/quantitative-sports
6
+ Project-URL: Repository, https://github.com/Veedubin/quantitative-sports
7
+ Project-URL: Issues, https://github.com/Veedubin/quantitative-sports/issues
8
+ Project-URL: Changelog, https://github.com/Veedubin/quantitative-sports/releases
9
+ Author-email: VeeDubin <veedubin@neuralgentics.dev>
10
+ License: MIT
11
+ Keywords: backtesting,expected-value,kelly-criterion,middling,nfl,odds-api,quantitative-finance,sports-betting,timescaledb,xgboost
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Database
21
+ Classifier: Topic :: Office/Business :: Financial
22
+ Classifier: Topic :: Scientific/Engineering
23
+ Requires-Python: >=3.12
24
+ Requires-Dist: asyncpg>=0.29.0
25
+ Requires-Dist: click>=8.0.0
26
+ Requires-Dist: duckdb>=0.9.0
27
+ Requires-Dist: httpx[http2]>=0.27.0
28
+ Requires-Dist: numpy>=1.26.0
29
+ Requires-Dist: pandas>=2.1.0
30
+ Requires-Dist: pyarrow>=14.0.0
31
+ Requires-Dist: pydantic-settings>=2.1.0
32
+ Requires-Dist: pydantic>=2.5.0
33
+ Requires-Dist: python-dateutil>=2.9
34
+ Requires-Dist: python-dotenv>=1.0.0
35
+ Requires-Dist: pyyaml>=6.0
36
+ Requires-Dist: requests>=2.31.0
37
+ Requires-Dist: rich>=13.0.0
38
+ Requires-Dist: tqdm>=4.66.0
39
+ Requires-Dist: typer>=0.9.0
40
+ Provides-Extra: dev
41
+ Requires-Dist: matplotlib>=3.8.0; extra == 'dev'
42
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
43
+ Requires-Dist: prefect>=3.0.0; extra == 'dev'
44
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
45
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
46
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
47
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
48
+ Requires-Dist: scikit-learn>=1.5.0; extra == 'dev'
49
+ Requires-Dist: scipy>=1.14.0; extra == 'dev'
50
+ Requires-Dist: seaborn>=0.13.0; extra == 'dev'
51
+ Requires-Dist: testcontainers>=4.7.0; extra == 'dev'
52
+ Requires-Dist: xgboost>=2.1.0; extra == 'dev'
53
+ Provides-Extra: notebook
54
+ Requires-Dist: ipykernel>=6.29.0; extra == 'notebook'
55
+ Requires-Dist: jupyter>=1.0.0; extra == 'notebook'
56
+ Requires-Dist: matplotlib>=3.8.0; extra == 'notebook'
57
+ Requires-Dist: nba-api>=1.8.0; extra == 'notebook'
58
+ Requires-Dist: nbconvert>=7.16.0; extra == 'notebook'
59
+ Requires-Dist: nbformat>=5.10.0; extra == 'notebook'
60
+ Requires-Dist: openpyxl>=3.1.0; extra == 'notebook'
61
+ Requires-Dist: pillow>=10.0.0; extra == 'notebook'
62
+ Requires-Dist: playwright>=1.57.0; extra == 'notebook'
63
+ Requires-Dist: psycopg2-binary>=2.9.9; extra == 'notebook'
64
+ Requires-Dist: scikit-learn>=1.5.0; extra == 'notebook'
65
+ Requires-Dist: scipy>=1.14.0; extra == 'notebook'
66
+ Requires-Dist: seaborn>=0.13.0; extra == 'notebook'
67
+ Requires-Dist: sqlalchemy>=2.0.0; extra == 'notebook'
68
+ Requires-Dist: xgboost>=2.1.0; extra == 'notebook'
69
+ Requires-Dist: xlsxwriter>=3.1.0; extra == 'notebook'
70
+ Provides-Extra: poller
71
+ Requires-Dist: asyncpg>=0.29.0; extra == 'poller'
72
+ Requires-Dist: httpx[http2]>=0.27.0; extra == 'poller'
73
+ Requires-Dist: prefect>=3.0.0; extra == 'poller'
74
+ Requires-Dist: prometheus-client>=0.19.0; extra == 'poller'
75
+ Requires-Dist: pydantic-settings>=2.1.0; extra == 'poller'
76
+ Requires-Dist: python-json-logger>=2.0.0; extra == 'poller'
77
+ Provides-Extra: web
78
+ Requires-Dist: aiofiles>=23.0.0; extra == 'web'
79
+ Requires-Dist: asyncpg>=0.29.0; extra == 'web'
80
+ Requires-Dist: fastapi>=0.109.0; extra == 'web'
81
+ Requires-Dist: jinja2>=3.1.0; extra == 'web'
82
+ Requires-Dist: markdown>=3.6.0; extra == 'web'
83
+ Requires-Dist: nbconvert>=7.16.0; extra == 'web'
84
+ Requires-Dist: nbformat>=5.10.0; extra == 'web'
85
+ Requires-Dist: python-multipart>=0.0.6; extra == 'web'
86
+ Requires-Dist: uvicorn[standard]>=0.27.0; extra == 'web'
87
+ Description-Content-Type: text/markdown
88
+
89
+ # Quant-Sports โ€” Quantitative Sports Betting Toolkit
90
+
91
+ **Mathematical toolkit for sports betting. Bring your own data.**
92
+
93
+ ![v0.2.0](https://img.shields.io/badge/version-v0.2.0-blue)
94
+ ![Tests](https://img.shields.io/badge/tests-775_passing-brightgreen)
95
+ ![License: MIT](https://img.shields.io/badge/license-MIT-green)
96
+
97
+ Quant-Sports is a professional-grade quantitative analysis toolkit designed for analysts, not tipsters. Think of it as "QuantLib for sports betting"โ€”it provides the rigorous mathematical infrastructure needed to translate raw odds and statistics into actionable, risk-adjusted betting signals.
98
+
99
+ ## Quick Start
100
+
101
+ ```bash
102
+ # 1. Install the desktop package
103
+ uv add quantitative_sports[notebook]
104
+
105
+ # 2. Start the storage layer
106
+ cd ~/Projects/Infrastructure/quantitative_sports
107
+ make docker-up
108
+
109
+ # 3. Open a notebook
110
+ uv run jupyter lab labs/01_getting_started.ipynb
111
+ ```
112
+
113
+ ## Architecture
114
+
115
+ Quant-Sports v0.2.0 is decoupled into three primary layers to ensure scalability and separation of concerns:
116
+
117
+ ```text
118
+ +-----------------------+ +-------------------------------------------+
119
+ | Desktop Package | | Docker Compose Stack |
120
+ | (CLI, Library, Labs) | | (timescaledb + poller + web dashboard) |
121
+ +-----------+-----------+ +-------------------+-----------------------+
122
+ | |
123
+ | Data Flow |
124
+ | [ Poller ] ----> [ TimescaleDB ] <---+
125
+ | | |
126
+ +-------+----------------+
127
+ |
128
+ v
129
+ [ Notebooks / CLI / Web UI ]
130
+ ```
131
+
132
+ - **Desktop Package**: The core Python library providing the math, models, and CLI.
133
+ - **Infrastructure Stack**:
134
+ - `timescaledb`: High-performance time-series storage (PG 18 + TimescaleDB 2.28).
135
+ - `quant-sports/poller`: Background container for data collection (Odds API, ESPN).
136
+ - `quant-sports/web`: Operations dashboard for health monitoring and metrics.
137
+ - **Data Flow**: The poller fetches live data $\rightarrow$ writes to TimescaleDB $\rightarrow$ consumed by the web dashboard and your analytical notebooks.
138
+
139
+ ## Features
140
+
141
+ ### ๐Ÿงฎ Betting Mathematics
142
+ - **Expected Value (EV)**: Precise calculation including implied probability and vig removal.
143
+ - **Kelly Criterion**: Full and fractional Kelly sizing for optimal bankroll growth.
144
+ - **Middling Detection**: Automatic identification of multi-book spread/total middles.
145
+
146
+ ### ๐Ÿ“ˆ Predictive Modeling
147
+ - **NFL Game Prediction**: XGBoost ensemble for win probability, spreads, and totals.
148
+ - **Ratings Systems**: Implementation of Elo, Massey, PageRank, and Glicko systems.
149
+ - **Custom Strategies**: Extensible registry to define, backtest, and deploy your own logic.
150
+
151
+ ### โš™๏ธ Infrastructure & Ops
152
+ - **Backtesting Engine**: Professional walk-forward validation and parallel execution.
153
+ - **Live Data**: Integrated polling for Odds API and ESPN injury reports.
154
+ - **Web Ops Dashboard**: Monitor poller health, run history, log tailing, and system metrics.
155
+
156
+ ## Package Layout
157
+
158
+ ```
159
+ quantitative_sports/
160
+ โ”œโ”€โ”€ core/ # Betting math (EV, Kelly, middling, metrics)
161
+ โ”œโ”€โ”€ models/ # XGBoost, ratings, predictive models
162
+ โ”œโ”€โ”€ backtest/ # Backtest engine
163
+ โ”œโ”€โ”€ data/ # Data sources (Odds API, ESPN, nflverse)
164
+ โ”œโ”€โ”€ infra/
165
+ โ”‚ โ”œโ”€โ”€ db/ # TimescaleDB connection, schema, queries, writers
166
+ โ”‚ โ””โ”€โ”€ poller/ # Background data fetcher
167
+ โ”œโ”€โ”€ web/ # FastAPI ops dashboard
168
+ โ””โ”€โ”€ cli/ # Click commands
169
+
170
+ labs/ # 10 comprehensive Jupyter walkthroughs
171
+ docker/
172
+ โ”œโ”€โ”€ Dockerfile.poller
173
+ โ”œโ”€โ”€ Dockerfile.web
174
+ โ””โ”€โ”€ init-db.sql # TimescaleDB schema
175
+ docker-compose.yml # timescaledb + poller + web
176
+ ```
177
+
178
+ ## Running
179
+
180
+ ### Installation
181
+ ```bash
182
+ uv add quantitative_sports[notebook]
183
+ ```
184
+
185
+ ### Usage
186
+ ```bash
187
+ # Run a CLI command
188
+ quantitative_sports nfl predict-game
189
+
190
+ # Start the docker stack (DB, Poller, Web)
191
+ make docker-up
192
+
193
+ # Run tests
194
+ make test
195
+ ```
196
+
197
+ ## Configuration
198
+
199
+ ```bash
200
+ cp .env.example .env
201
+ # Edit .env with your Odds API key
202
+ # Then: make docker-up
203
+ ```
204
+
205
+ ## Disclaimer
206
+
207
+ *Quant-Sports is a mathematical toolkit provided for analytical purposes only. It does not provide betting advice or guaranteed returns. You are solely responsible for compliance with your local laws and regulations regarding sports wagering.*