The DFS desk has two value streams:
DraftKings is the primary DFS platform. FanDuel sportsbook remains the sharp anchor for player props — DFS crowd wisdom is secondary and generally inefficient (Gemini's critical correction).
| Contest | Goal | Optimization Target |
|---|---|---|
| Cash (50/50) | Beat median | Maximize floor — consistency over upside |
| GPP (Tournament) | Top 1-5% | Maximize ceiling * ownership leverage — differentiate from field |
| H2H | Beat one opponent | Hybrid — cash floor + one swing player |
Cash Score (lineup optimization target):
CashScore = 0.7 * Projection + 0.3 * Floor(P10)
GPP Score:
GPPScore = 0.5 * Projection + 0.5 * Ceiling(P90) - 0.3 * (ProjectedOwnership * 100)
H2H Score:
H2HScore = 0.6 * Projection + 0.25 * Floor(P10) + 0.15 * Ceiling(P90)
Single-point projections are insufficient. Model the full distribution using gamma fit:
Score ~ Gamma(k, theta) + shift
Floor(P10) = gamma.ppf(0.10, k, theta) + shift
Ceiling(P90) = gamma.ppf(0.90, k, theta) + shift
Fit from player's last 30-game DFS score distribution.
Thresholds:
Ownership-Adjusted Value (OAV):
OAV = (our_projection - consensus_projection) / projected_ownership
Ownership Leverage Rating (OLR):
OLR = (edge / salary) / sqrt(projected_ownership)
Thresholds:
Sum of Ownership Cap (Gemini):
Lineup_Own_sum = sum(Own_i for all players)
Keep GPP lineup sum ownership below 120% for large-field tournaments.
Contrarian triggers:
Build pairwise correlation matrices from historical DFS scores. For GPPs, maximize lineup variance through positive correlations. For Cash, minimize variance.
NBA Stacking:
Game_Attractiveness = implied_total * (1 / (1 + abs(spread)))NHL Stacking:
MLB Stacking:
Stack_Score = implied_team_total * (1 - pitcher_quality_pct) * handedness_factorCorrelation thresholds:
Largest underexploited edge in DFS. Most casual players set-and-forget.
Information triggers (ranked by priority):
NBA usage boost:
Dynamic programming for late-swap (Gemini):
NBA:
Pace_Adjusted = base * (matchup_pace / league_avg_pace)Usage_Boost = base * (1 + teammate_absence_usage_increase)UAP = (Usage_Rate * Minutes * 0.4) + Opponent_Defensive_AdjNHL:
PP_TOI_Share is the ceiling driver — PP1 promotion = +15-25% projection jumpLSV = (Line_Shots * Line_GPG * 0.3) + PP_BonusMLB:
BvPE = (wOBA_vs_Handedness * 0.5) + (Park_Factor * 0.2) - xFIP_AdjDFS crowd is NOT smart money. When FanDuel or Kalshi disagrees with DFS ownership, the sportsbook is almost certainly correct. DK data is a SECONDARY signal — FanDuel remains the sharp anchor.
Step 1: Salary-to-FP regression (fit from historical data):
DK_Implied_FP = a * salary + b
NBA example: DK_Implied_FP ≈ 0.0057 * salary - 2.5
Step 2: Decompose FP to individual stats using player's historical distribution:
Implied_Points = DK_Implied_FP * (pts_share / pts_FP_weight)
Step 3: Convert to probability at Kalshi threshold:
P(over T) = 1 - NormalCDF((T - implied_stat) / historical_std_dev)
Use Normal for volume stats (points, rebounds). Poisson for count stats (blocks, steals).
Step 4: Compare to Kalshi:
edge = DK_implied_prob - kalshi_implied_prob
Trade threshold: edge >= 5 cents WITH FanDuel confirmation.
Salary_Momentum = (today_salary - avg_salary_last_5_slates) / avg_salary_last_5_slates
Highest-alpha signal — DK salary changes are proprietary information embedded in pricing.
DFS ownership is actionable ONLY when it confirms the FanDuel sharp anchor:
| Scenario | Action |
|---|---|
| DK ownership + FanDuel + our model all disagree with Kalshi | STRONG trade |
| DK ownership + FanDuel agree, Kalshi differs | MODERATE (60% size) |
| DK ownership disagrees with FanDuel | Trust FanDuel, ignore DFS crowd |
| DK ownership only signal | No trade |
Where DFS crowd is informative: Blowup spots (backup starting), pace environments Where DFS crowd is wrong: Mean reversion, low-volume stats (steals/blocks)
OwnershipDelta = OwnershipAt(lock - 5min) - OwnershipAt(lock - 60min)
Cross-platform execution window: 5-15 minutes. Requires automation — manual is too slow.
If DFS projections for a backup's minutes jump from 12 to 32 → execute immediate BUY on Kalshi for that player's props before market makers adjust.
Same as Player Props desk:
| Source | What | Cost | Priority |
|---|---|---|---|
| DraftKings salary/ownership pages | Salaries, projected ownership | Free (scrape) | P1 |
| RotoGrinders | Ownership projections, consensus projections | Free tier | P1 |
| NBA Stats API | Pace, usage, DvP | Free | P1 |
| FanGraphs | MLB splits, ISO, wOBA | Free | P1 |
| MoneyPuck / NaturalStatTrick | NHL advanced stats (already collecting) | Free | P1 |
| Pinnacle (already collecting) | Vegas lines for game environment | Free via Odds API | P1 |
| FantasyLabs | Ownership + projections | $30-50/mo | P2 |
| SaberSim | Optimizer + ownership sims | $50/mo | P3 |
| Time (ET) | What |
|---|---|
| When DK publishes salaries | Scrape salaries + compute salary momentum |
| 9:00 AM | Ownership projections from RotoGrinders |
| 11:00 AM | Build projections from all data sources |
| 2:00 PM | Updated ownership + projections |
| Lock - 60 min | Start ownership snapshot polling (every 10 min) |
| Lock - 30 min | Final projection run + lineup lock for Cash |
| Lock - 15 min | Late-swap detection active |
| Lock - 5 min | Final late-swap execution |
| Post-contest | Scrape results, record actual ownership, actual stats, ROI |
| Phase | Days | What |
|---|---|---|
| Phase 1 | 1-5 | DK salary scraper, salary-to-stat regression, salary momentum, compare to Kalshi |
| Phase 2 | 6-14 | Ownership collection, ownership snapshots, player distributions (gamma fit), floor/ceiling |
| Phase 3 | 15-30 | Correlation matrix, stack engine, Cash/GPP/H2H optimizer, late-swap automation |
| Phase 4 | Ongoing | Contest results tracking, backtesting, weight calibration, Kalshi signal automation |
Full ruling: /home/ubuntu/edgeclaw/results/panel-results/dfs-panel-ruling.md
Panel: Opus (judge) + Sonnet + Grok 4.2 Reasoning + Gemini Pro 3.1
Date: 2026-03-28, Grade: A
Status: NOT BUILT — add when this desk goes live for execution
Current state: All Kalshi data (prices, order books, trades) is fetched via REST API polling on cron schedules. This is fine for edge detection and monitoring, but NOT sufficient for live trade execution.
Why WebSocket matters:
Note: Sports markets use RFQ (Request for Quote) so the visible order book is usually empty — but the trade feed still matters for freshness signals and the WebSocket is required for order submission. Weather and politics markets DO have real visible order books where this upgrade is even more critical.
Added 2026-03-29 — upgrade REST to WS when desk moves to live execution