Week-2 idea: add Draymond Green, drop Fears (+4 pp this week)
12h agoRaises this week's win odds by ~4 pp (we trail 3-6); no measurable season effect either way.
Details
💬 0
No discussion yet.
Loading inbox…
Approve = your yes; the next daily run executes it after re-checking Yahoo.
Raises this week's win odds by ~4 pp (we trail 3-6); no measurable season effect either way.
No discussion yet.
Not now: most of the gain is Denver's playoff-week schedule, and Yeet likely says no.
Approval expired Oct 29, 6:31 PM · “expired without a decision”
requested Oct 29, 7:27 AMapr-2d5b6d621f364ed395828f33770ce19a
No discussion yet.
Re-checked on today's projections: dropping Bailey costs ~2.9 pp of playoff odds, dropping Fears ~0.
No discussion yet.
python scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonpython scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.jsonThis is advisory only: verify current eligibility, availability, waiver timing and roster opening, then obtain owner approval before any move. Do not interpret the IL log as independently verified current Yahoo state; temporary add-without-drop is not evaluated as a permanent 14-player roster.
Reproduction at commit 363facdb323ad3387cbfba3756c605cb50d9b120; roster captured 2026-10-21T02:40:28.335Z, synced 2026-10-21T02:42:08Z, roster SHA256 3da374fdb8c04a74aa7a7a1875c05dc814be791f074019eb5fa21fa6dc88ca0b.
The pre-effective Bailey window is retained; only the player window changes from Oct23 onward. Apply this script-addition diff, rebuild cached local projection sets, and run from repo root:
fantasy data alt-projections --blend market --out var/projections_alt/market.csv
fantasy data alt-projections --blend espn-only --blend-gp espn=1 --out var/projections_alt/espn-only-gp.csv
python scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.json
Projection hashes: {"blend": "6acf9cce425b45e1f0021f267b9c4766e2c9cbb267ad3c883b8c835ea4a896bc", "market": "bb83f45f307fe6e4df9c7d7be0c7d4096def49946815c089669d8d68b27f927e", "stress": "8436dc57540b1a32cd70d823a8bdc7c809ec0064a35e2bcbca1a0dcb0dddda40"}
--- /dev/null
+++ b/scripts/advisor_champagnie_check.py
@@ -0,0 +1,58 @@
+"""Offline paired season reproduction at commit 363facd; no live-state claims.
+
+Run from repository root after rebuilding cached alternative projections:
+ fantasy data alt-projections --blend market --out var/projections_alt/market.csv
+ fantasy data alt-projections --blend espn-only --blend-gp espn=1 --out var/projections_alt/espn-only-gp.csv
+ python scripts/advisor_champagnie_check.py --sims 2000 --seeds 8 --seed-start 101 --effective-date 2026-10-23 --out var/advisor-champagnie.json
+
+The effective date reproduces research section 0.2, not verified Yahoo timing.
+"""
+import argparse, hashlib, json, time
+from datetime import date
+from pathlib import Path
+import numpy as np
+from fantasy.inseason.possim import make_sim
+from fantasy.league.settings import load_settings
+from fantasy.model.lines import load_projections
+from fantasy.sim.context import build_context
+from fantasy.sim.league import from_json
+
+ap=argparse.ArgumentParser()
+ap.add_argument('--sims',type=int,default=2000)
+ap.add_argument('--seeds',type=int,default=8)
+ap.add_argument('--seed-start',type=int,default=101)
+ap.add_argument('--effective-date',type=date.fromisoformat,default=date(2026,10,23))
+ap.add_argument('--out',type=Path,required=True)
+a=ap.parse_args()
+lf=Path('data/manual/league_rosters_2026-27.json'); raw=json.loads(lf.read_text())
+lg=from_json(lf); me=lg.my_team
+st=load_settings().model_copy(update={'num_teams':len(lg.rosters)})
+add,drop='julian-champagnie','ace-bailey'
+assert drop in lg.rosters[me] and not any(add in ps for ps in lg.rosters.values())
+alt=lg.copy();alt.rosters[me]=[*alt.rosters[me],add]
+eff=a.effective_date; windows={drop:(None,eff),add:(eff,None)}
+sets={'blend':Path('data/processed/projections_2026_27.csv'),'market':Path('var/projections_alt/market.csv'),'stress':Path('var/projections_alt/espn-only-gp.csv')}
+res={'commit':'363facdb323ad3387cbfba3756c605cb50d9b120','roster_source':raw['source'],'synced_at':raw['synced_at'],'roster_sha256':hashlib.sha256(lf.read_bytes()).hexdigest(),'effective':eff.isoformat(),'sims_per_seed':a.sims,'seeds':list(range(a.seed_start,a.seed_start+a.seeds)),'sets':{},'assumptions':['Fixed captured rosters; no live Yahoo verification.','Successful claim; incoming starts Oct23 (waiver timing prior); outgoing retained before effective day.','Position-aware season simulator with default IL replacement and season availability, not current-day injury-tag conditioning.','No transaction/waiver-priority cost or future team add/drop reactions modelled.','SE measures Monte Carlo noise only; not model/projection uncertainty.']}
+start=time.monotonic()
+for name,path in sets.items():
+ ctx=build_context(load_projections(path),st,lg.team_ids,schedule_file=Path('data/manual/league_schedule.json'))
+ accum={m:[] for m in ['p_playoffs','p_title','exp_cat_wins']};seed_rows=[]
+ for seed in res['seeds']:
+ sim=make_sim(ctx,a.sims,seed)
+ b=sim.run(lg);c=sim.run(alt,windows)
+ i,k=b.tindex(me),c.tindex(me)
+ arrays={'p_playoffs':(b.playoff[:,i].astype(float),c.playoff[:,k].astype(float)), 'p_title':((b.champion==i).astype(float),(c.champion==k).astype(float)), 'exp_cat_wins':(b.cat_wins[:,i],c.cat_wins[:,k])}
+ sr={'seed':seed}
+ for m,(x,y) in arrays.items():
+ d=y-x;accum[m].append((x,y,d));sr[m]={'before':float(x.mean()),'after':float(y.mean()),'delta':float(d.mean()),'paired_se':float(d.std(ddof=1)/np.sqrt(len(d)))}
+ seed_rows.append(sr)
+ print(json.dumps({'set':name,'seed':seed,'elapsed_s':round(time.monotonic()-start,2)}),flush=True)
+ summary={}
+ for m,rows in accum.items():
+ x=np.concatenate([r[0] for r in rows]);y=np.concatenate([r[1] for r in rows]);d=np.concatenate([r[2] for r in rows])
+ means=np.array([r[2].mean() for r in rows]);seed_ses=np.array([r[2].std(ddof=1)/np.sqrt(len(r[2])) for r in rows])
+ se_paired=float(np.sqrt(np.mean(seed_ses**2))/np.sqrt(a.seeds));se_seed=float(means.std(ddof=1)/np.sqrt(a.seeds)) if a.seeds>1 else se_paired
+ summary[m]={'before':float(x.mean()),'after':float(y.mean()),'delta':float(d.mean()),'paired_pooled_se':float(d.std(ddof=1)/np.sqrt(len(d))),'paired_within_seed_se':se_paired,'between_seed_se':se_seed,'reported_se':max(se_paired,se_seed),'n_paired':len(d)}
+ res['sets'][name]={'projection_sha256':hashlib.sha256(path.read_bytes()).hexdigest(),'summary':summary,'by_seed':seed_rows,'warnings':ctx.warnings}
+ res['elapsed_s']=round(time.monotonic()-start,2);a.out.write_text(json.dumps(res,indent=2))
+ print(json.dumps({'set_complete':name,'summary':summary}),flush=True)Verified reproduction: fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --start 2026-10-23 --end 2026-10-26 --json Verified replacement: fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --window-only 2026-10-23..2026-10-26 --json For actual matchup-aware reviews prefer --date plus explicit captured inputs and uncertainty settings; do not equate the legacy output with a full season-aware recommendation. --- a/docs/integrations/advisor.md +++ b/docs/integrations/advisor.md @@ -21,7 +21,7 @@ fantasy status # local SQLite (var/fantasy.db) is empty in a fresh clone: that's expected fantasy sim season --league-file data/manual/league_rosters_2026-27.json --no-save --json fantasy lineup plan --date 2026-10-22 --allow-stale --json -fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --start 2026-10-23 --end 2026-10-26 --json +fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --window-only 2026-10-23..2026-10-26 --json fantasy inseason trade --league-file data/manual/league_rosters_2026-27.json --partner 5 --give "Player A" --get "Player B" --json fantasy inseason lineup --help ``` --- a/web/src/content/advisor.md +++ b/web/src/content/advisor.md @@ -21,7 +21,7 @@ fantasy status # local SQLite (var/fantasy.db) is empty in a fresh clone: that's expected fantasy sim season --league-file data/manual/league_rosters_2026-27.json --no-save --json fantasy lineup plan --date 2026-10-22 --allow-stale --json -fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --start 2026-10-23 --end 2026-10-26 --json +fantasy inseason stream --league-file data/manual/league_rosters_2026-27.json --window-only 2026-10-23..2026-10-26 --json fantasy inseason trade --league-file data/manual/league_rosters_2026-27.json --partner 5 --give "Player A" --get "Player B" --json fantasy inseason lineup --help ```
pytest tests/test_inseason_scan.py -k test_stream_week_excludes_games_after_stint -vRegression-only diff below, verified to fail on 363facd; no production fix is claimed. A complete fix should share the selected chain player and half-open availability windows with the weekly evaluator. Merely clipping the streamer would omit the replacement player's remaining-week contribution. Do not change the roster based on this test.
--- a/tests/test_inseason_scan.py
+++ b/tests/test_inseason_scan.py
@@ -211,3 +211,37 @@
rs = table[0]["resim"]
assert rs["seeds"] == [11, 12] and rs["by_set"]["blend"]["me"]["p_title"]["n_seeds"] == 2
assert rs["class"] in {"helps", "speculative", "floor_only", "noise", "hurts", "mixed"}
+
+
+@pytest.mark.parametrize("stint_days, expected_games", [(None, 1), (1, 0)])
+def test_stream_week_excludes_games_after_stint(ctx, proj_path, stint_days, expected_games):
+ """A one-day streamer cannot contribute his only game on day two.
+
+ The public --stint-days contract says how long the streamer is kept, not
+ merely how long to charge his season cost. No choice of chain replacement
+ can make the departed streamer's own day-two game eligible.
+ """
+ df, vals = ctx.proj.df, ctx.values
+ ids = list(vals.index)
+ me = _players(ids[1:27:2], df, "AAA")
+ opp = _players(ids[2:27:2], df, "BBB")
+ first = date(2026, 11, 2)
+ days = [first + timedelta(days=i) for i in range(3)]
+ nba = NBASchedule(
+ games=[(d, "AAA", "BBB") for d in days] + [(days[1], "CCC", "DDD")],
+ source="synthetic-stint-regression",
+ )
+ add = ids[0]
+ fa = FreeAgent(add, "Streamer", "CCC", parse_positions(df.loc[add, "positions"]),
+ None, None, "player")
+ report = scan_streams(
+ df, ctx.settings, nba, me, opp, [fa], days,
+ generic_per_game_values(load_projections(proj_path), ctx.settings), vals["value"],
+ StreamParams(week_sims=0, season_sims=0, season_top=1,
+ stint_days=stint_days, waiver_lag=0),
+ drops=[me[-1].player_id],
+ )
+ row = next(r for r in report["pairs"] if r["add"] == add)
+ assert row["add_games"] == expected_games
+ if stint_days == 1:
+ assert row["add_starts"] == 0Approval approved Oct 26, 8:25 AM
No discussion yet.
Approval approved Oct 27, 8:24 AM
requested Oct 27, 7:33 AMapr-226d906ed1554597b706bd3a7b15cdb1
No discussion yet.
Re-checked on today's projections: dropping Bailey costs ~2.9 pp of playoff odds, dropping Fears ~0.
No discussion yet.
Podziemski on IL opened a spot, so Champagnie can play tonight (8 PM ET @DAL) and Bailey still plays Sunday.
Approval approved Oct 24, 11:18 AM
No discussion yet.
Approval approved Oct 24, 11:18 AM
requested Oct 24, 10:47 AMapr-e266dbef6e884ddca1936226f022bf24
No discussion yet.
Only add/drop that helps under both projection sets after today's model fixes.
Approval approved Oct 23, 10:51 PM
No discussion yet.
Approval approved Oct 23, 11:18 PM
requested Oct 23, 11:00 PMapr-771da9487a684cebb0adfefdc2174dc5
No discussion yet.
Approval approved Oct 23, 10:57 PM
requested Oct 23, 10:52 PMapr-b61cc6171de34c148a2dd19793d935c4
No discussion yet.
Small but consistent gain in both projection sets.
Approval expired Oct 22, 9:54 PM · “expired without a decision”
Recommended: helps under all three projection sets.
Approval expired Oct 21, 7:00 PM · “expired without a decision”
Strong yes: helps under all three projection sets, also schedule-neutral.
Approval rejected Oct 21, 7:03 PM
No discussion yet.
Worth offering: helps under all three projection sets.
Approval rejected Oct 21, 7:03 PM
No discussion yet.
Keep the roster as is in week 1.
No discussion yet.
User reported clicking Start Active; re-read all week days: starters already match optimizer targets. Only change: Podziemski O -> IL (pre-authorised).
lineup-0.2.0: today matches Yahoo; 10-21 already set (same starters); 10-22 only Jokic plays -> set in advance
Brunson/Jokic have no game Wed; Podziemski Q (p_play prior 0.5) benched, re-check before GSW tip 10pm ET
recommendations[0] (value_search ok)
deviation: guard rule (user, picks 108+) - took top-5 #1 guard over recommendations[0] DeMar DeRozan; roster has 1 true guard; daily lineup crunch not modelled
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
recommendations[0] (value_search ok)
deviates from recommendations[0] (Bane 5.629, p_next 0.16): top-5 within 0.022 = tie; protocol tie-break prefers lower prob_available_next -> Kawhi 5.633, p_next 0.003
recommendations[0] (back-to-back 36/37)
recommendations[0] (value_search); top-5 within 0.02, lowest p_next 0.063
recommendations[0]; margin 0.064 over Wembanyama