PR #565: Wire batted-ball profile into hits + total_bases enrichment#434
Conversation
…otal_bases enrichment - New signal block in prop_enrichment_layer.py after Defense OAA section - hits: LD rate → BABIP boost; GB heavy → infield-hit bonus - total_bases: FB rate + pull rate → XBH upside; GB heavy → drag - _bb_profile_adj flows through adjustment dampener (±4pp max) - bb_profile added to layer_audit JSONB for observability"
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
|
Overall Grade |
Security Reliability Complexity Hygiene |
Code Review Summary
| Analyzer | Status | Updated (UTC) | Details |
|---|---|---|---|
| Docker | May 15, 2026 2:40a.m. | Review ↗ | |
| JavaScript | May 15, 2026 2:40a.m. | Review ↗ | |
| Python | May 15, 2026 2:40a.m. | Review ↗ | |
| SQL | May 15, 2026 2:40a.m. | Review ↗ | |
| Secrets | May 15, 2026 2:40a.m. | Review ↗ |
Important
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 17 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
Code Review
This pull request adds a batted-ball profile signal to the enrichment layer for 'hits' and 'total_bases' props, using Statcast data to adjust probabilities based on ground ball, fly ball, line drive, and pull rates. Review feedback highlights an inefficient local import that should be moved outside the loop and identifies a numerical inconsistency in the fly ball rate average used for total bases calculations, which may introduce bias.
| _b_id_bb = prop.get("player_id") or prop.get("mlbam_id") | ||
| if _b_id_bb: | ||
| try: | ||
| from statcast_static_layer import get_batter_batted_ball as _gbb # noqa: PLC0415 |
There was a problem hiding this comment.
Importing get_batter_batted_ball inside the per-prop loop is inefficient. Although Python caches module imports, the lookup overhead occurs for every prop of type hits or total_bases. It is better to move this import to the top of the enrich_props function, especially since statcast_static_layer is already being imported multiple times in this function.
| # MLB avg air_rate ~0.38 (includes LD + FB) | ||
| if _fb_r > 0: | ||
| _bb_adj += (_fb_r - 0.22) / 0.08 * 0.030 # FB avg ~22% |
There was a problem hiding this comment.
There is a numerical inconsistency between the comments and the adjustment logic for total_bases. Line 1765 states that the average air_rate (LD + FB) is ~0.38. Given that the LD average is cited as 0.22 (line 1755), this implies a FB average of 0.16. However, line 1767 uses 0.22 as the center for the FB adjustment calculation and includes a comment stating FB avg ~22%. This internal contradiction between the air_rate and fb_rate averages will likely result in a systematic bias in the calculated adjustment for league-average hitters.
PR #565 — Batted-ball profile signal for
hits+total_basesWhat
Wires
get_batter_batted_ball()(already loaded frombatted-ball.csvinstatcast_static_layer.py) intoprop_enrichment_layer.pyas a live adjustment signal.Signal design
hitsprops:(ld_rate − 0.22) / 0.06 × 3pp(league avg ~22%)+1pp per 10pp above 48%total_basesprops:(fb_rate − 0.22) / 0.08 × 3pp(pull_rate − 0.38) / 0.10 × 2ppCaps: ±4pp per prop; runs through adjustment dampener (geometric decay with other same-direction signals).
Wiring
prop_type in ("hits", "total_bases") and is_batter_prop_bb_profile_adjadded to dampener_all_adjslist"bb_profile"added to_layer_auditJSONBNo statcast_static_layer changes needed
get_batter_batted_ball()has been in the layer since day 1 — this PR just calls it.Summary by cubic
Adds a batted-ball profile signal to enrich batter
hitsandtotal_basesprops, using GB/FB/LD/pull rates to better model BABIP and XBH upside. Adjustments are capped at ±4pp and flow through the existing dampener with audit visibility.hitsandtotal_bases._bb_profile_adjadded to the dampener andbb_profileadded tolayer_audit.get_batter_batted_ball(); no changes to the static layer.Written for commit 629a099. Summary will update on new commits.