- rl_auction_agent.py: Custom Gym-free auction environment with N opponents,
numpy-only Q-network with manual backprop, Double DQN policy with target
network, full training loop with epsilon decay and periodic evaluation,
and baseline comparison vs greedy and MILP strategies.
- set_transformer.py: Team-level valuation model treating roster as an
unordered set. Two modes: full PyTorch Set Transformer with ISAB/PMA
when torch is available, or sklearn Bag-of-Players fallback using
per-role aggregates, pairwise cosine similarities, and position entropy.
- TransferCausalModel(BaseModel): estimates causal effect of roster changes
on team performance using a causal forest (Athey et al., 2019)
- Dual backend: econml.grf.CausalForest (preferred) or pure sklearn fallback
with honest estimation (split on half, estimate on other half)
- predict_effect(): ATE, CATE, and 95% confidence intervals
- predict_individual_effect(): net effect of adding a player to roster
- rank_transfers(): rank candidate pool by predicted causal effect
- analyze_confounders(): identify features that confound transfer effect
- subgroup_effects(): estimate treatment effect by subgroup
- _build_roster_features(): compute roster-level features (role counts,
points, minutes, age, formation entropy, interaction level)
- _build_player_features(): treatment features (projected points, role,
scarcity, value over replacement)
- AuctionEffectAnalyzer: adjusts auction bids based on causal effects
- xG computed from goals using Serie A conversion rates per role:
Forwards 0.85, Mids 0.82, Defenders 0.70
- npxG excludes penalties (Rp column from Fantacalcio stats)
- xA estimated as assists × 2.2 (chance creation proxy)
- Updated players.parquet, player_projections, season_projections
- Verified: Malen xG/90=0.915, Martinez L. 0.667, Dimarco xA/90=1.069
- Note: values are per-game (Pv), not per-90-minutes (no minutes data in Fantacalcio stats)
- Added missing GRIDLINE import to auction page template imports
- New contingency section: per-role backup targets if bids are missed
- Shows up to 12 backup players per role with FV, estimated price, games
- xG values note: synthetic from FBref data (real xG blocked by Cloudflare)
- run_dashboard.sh: one-command launcher with auto warehouse export
- Sets correct working directory and streamlit flags
- All 49 tests passing. 344 dataset files committed.
- Players page: fix regression_chart xg_col default (goals_p90 -> xg_p90)
- charts.py: make regression_chart defensive against missing columns
- All pages: replace use_container_width=True with width='stretch'
- Verified: all 5 pages render with zero errors via Playwright browser test
- Add sys.path.insert at top of app.py and all 5 page files
- Fix .streamlit/config.toml CORS/XSRF conflict
- Remove duplicate st.set_page_config from page files
- Verified: all pages import cleanly, dashboard boots via streamlit run
- All 49 tests passing (31 original + 18 dashboard)
- Updated 26_27_teams.yaml with confirmed teams from live Fantacalcio.it (Venezia,
Frosinone, Sassuolo, Parma, Como — all 20 teams confirmed)
- Fixed FantacalcioScraper HTML roster parser to match live quotazioni page structure
(data-filter-role-classic, player-row tr elements)
- Added 26/27 Quotazioni_Fantacalcio: 505 players with FVM values, QI/QA prices
- Scraped real 25/26 season stats from statistiche-serie-a (663 players)
- Built expert model using real 25/26 FV baselines + home/away adj + opponent strength
- Generated Matchday 1 predictions for 388 matched players
- MCTS lineup optimization: Captain Malen (Roma, 9.67 FV), 98.1 expected pts
- All 31 tests passing
- Reorganization of data folders
- Code adapted for the new Serie A season, also considering only a small number of league games has been played
- Stats from other leagues are considered for players at their first Serie A season (rookies), for now without any adaptation based on league difficulty
- Minor fixes
- Reorganization of data folders
- Code adapted for the new Serie A season, also considering only a small number of league games has been played
- Stats from other leagues are considered for players at their first Serie A season (rookies), for now without any adaptation based on league difficulty
- Minor fixes