DFS Desk — Data Inventory (Mar 28, 2026)
Status: NOT BUILT — Zero tables, zero scrapers
WHAT THIS DESK DOES
Two value streams:
- Win DraftKings DFS contests — Cash (50/50), GPP (tournaments), H2H
- Beat Kalshi player props — use DK salary/ownership as signals for Kalshi prop mispricing
DraftKings is primary platform. FanDuel sportsbook is the sharp anchor for props (not DFS crowd).
EXISTING DATA (from other desks — no new collection needed)
| Existing Table |
Feeds DFS How |
| sports_odds_snapshots (Pinnacle) |
Vegas lines = game environment for all sports |
| DailyFaceoff goalie data |
NHL goalie confirmation |
| MoneyPuck / NaturalStatTrick |
NHL shot metrics, xGF, PP units |
| MLB park factors + weather |
MLB game environment |
| MLB bullpen tracker |
Bullpen fatigue for run scoring |
| NBA/NHL/MLB injury reports |
Late scratches create value |
| Player props (FanDuel via Odds API) |
FD prop lines = sharp anchor for cross-platform signal |
TABLES TO BUILD (panel-approved schemas)
Priority 1 — Salary + Projections
| Table |
Rows Expected |
Purpose |
| dfs_dk_players |
~200/slate, ~600/day |
DK salary, implied FP, ownership, actual results per player per slate |
| dfs_salary_history |
~200/slate cumulative |
Track salary changes across slates for momentum signal |
| dfs_player_distributions |
~500 total (updated rolling) |
Gamma-fit parameters per player per stat type — floor/ceiling/mean/std |
CREATE TABLE dfs_dk_players (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
slate_date TEXT NOT NULL,
player_name TEXT NOT NULL,
team TEXT NOT NULL,
position TEXT NOT NULL,
dk_salary INTEGER NOT NULL,
dk_implied_fp REAL,
projected_ownership REAL,
actual_ownership REAL,
actual_fp REAL,
actual_pts INTEGER, actual_reb INTEGER, actual_ast INTEGER,
fetched_at TEXT DEFAULT (datetime('now')),
UNIQUE(sport, slate_date, player_name)
);
CREATE TABLE dfs_salary_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
player_name TEXT NOT NULL,
slate_date TEXT NOT NULL,
dk_salary INTEGER NOT NULL,
salary_5slate_avg REAL,
salary_momentum REAL,
UNIQUE(sport, player_name, slate_date)
);
CREATE TABLE dfs_player_distributions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
player_name TEXT NOT NULL,
stat_type TEXT NOT NULL,
sample_size INTEGER,
mean REAL NOT NULL,
std_dev REAL NOT NULL,
p10 REAL, p50 REAL, p90 REAL,
gamma_k REAL, gamma_theta REAL, gamma_shift REAL,
updated_at TEXT NOT NULL,
UNIQUE(sport, player_name, stat_type)
);
Priority 2 — Ownership Snapshots + Late-Swap Detection
| Table |
Rows Expected |
Purpose |
| dfs_ownership_snapshots |
~1,200/slate (200 players * 6 snapshots) |
Track ownership changes in final hour for late-swap signal |
CREATE TABLE dfs_ownership_snapshots (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
slate_date TEXT NOT NULL,
player_name TEXT NOT NULL,
snapshot_time TEXT NOT NULL,
minutes_before_lock REAL,
ownership_pct REAL NOT NULL,
UNIQUE(sport, slate_date, player_name, snapshot_time)
);
Priority 3 — Correlations + Stacking
| Table |
Rows Expected |
Purpose |
| dfs_correlations |
~5,000 per sport |
Pairwise DFS score correlations for stack construction |
CREATE TABLE dfs_correlations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
player_a TEXT NOT NULL,
player_b TEXT NOT NULL,
correlation REAL NOT NULL,
sample_size INTEGER,
stack_type TEXT,
updated_at TEXT DEFAULT (datetime('now')),
UNIQUE(sport, player_a, player_b)
);
Priority 4 — Cross-Platform Signals + Results
| Table |
Rows Expected |
Purpose |
| dfs_kalshi_signals |
~20-50/day |
DK-implied prob vs Kalshi price — edge detection |
| dfs_contest_results |
~3-5/day |
Contest outcomes for ROI tracking |
CREATE TABLE dfs_kalshi_signals (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
game_date TEXT NOT NULL,
player_name TEXT NOT NULL,
signal_type TEXT NOT NULL,
dk_salary INTEGER,
dk_implied_prob REAL,
kalshi_ticker TEXT,
kalshi_prop_type TEXT,
kalshi_threshold REAL,
kalshi_price REAL,
kalshi_implied_prob REAL,
fanduel_implied_prob REAL,
edge_estimate REAL,
signal_strength TEXT,
direction TEXT,
acted_on INTEGER DEFAULT 0,
actual_result TEXT,
pnl REAL,
created_at TEXT DEFAULT (datetime('now')),
UNIQUE(sport, game_date, player_name, kalshi_prop_type, kalshi_threshold)
);
CREATE TABLE dfs_contest_results (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sport TEXT NOT NULL,
slate_date TEXT NOT NULL,
platform TEXT DEFAULT 'draftkings',
contest_type TEXT NOT NULL,
entry_fee REAL,
payout REAL,
placement INTEGER,
percentile REAL,
lineup_json TEXT,
total_score REAL,
created_at TEXT DEFAULT (datetime('now'))
);
APPROVED CUSTOM METRICS (from panel ruling)
DFS Contest Metrics
| Metric |
Formula |
Contest Type |
| OAV |
(our_proj - consensus_proj) / projected_ownership |
GPP screening |
| OLR |
(edge / salary) / sqrt(projected_ownership) |
GPP optimization |
| CashScore |
0.7 * Proj + 0.3 * Floor(P10) |
Cash lineup target |
| GPPScore |
0.5 * Proj + 0.5 * Ceiling(P90) - 0.3 * (Own * 100) |
GPP lineup target |
| Sum of Ownership |
sum(Own_i) < 120% |
GPP large-field cap |
| Leverage Score |
p(Optimal_i) - Own_i, target > +5% |
GPP core building blocks |
Kalshi Cross-Platform Signals
| Signal |
Formula |
Threshold |
| Salary-to-Prob |
1 - NormalCDF((T - implied_stat) / std_dev) |
edge >= 5c + FD confirmation |
| Salary Momentum |
(today_salary - 5slate_avg) / 5slate_avg |
> $700 change = 10% shift |
| Ownership Delta |
Own(lock-5min) - Own(lock-60min) |
> ±8% = mass swap signal |
| Signal Combo |
DK + FD + model all agree vs Kalshi |
STRONG = full size |
SPORTS COVERAGE
| Sport |
Season |
DFS Volume |
Priority |
| NBA |
Oct-Jun |
Highest daily |
First to build |
| MLB |
Apr-Oct |
High (daily) |
Second |
| NHL |
Oct-Jun |
Medium |
Third |
| NFL |
Sep-Feb |
Highest per-slate |
Fourth (weekly) |
DATA SOURCES (DFS-specific)
| Source |
What |
Cost |
Priority |
| DraftKings salary pages |
Salaries per slate |
Free (scrape) |
P1 |
| RotoGrinders |
Ownership projections |
Free tier |
P1 |
| NBA Stats API |
Pace, usage, DvP |
Free |
P1 |
| FanGraphs |
MLB splits, wOBA |
Free |
P1 |
| FantasyLabs |
Ownership + projections |
$30-50/mo |
P2 |
| SaberSim |
Optimizer + sims |
$50/mo |
P3 |
PANEL RULING REFERENCE
Full ruling: /home/ubuntu/edgeclaw/results/panel-results/dfs-panel-ruling.md
Panel: Opus + Sonnet + Grok 4.2 + Gemini Pro 3.1 (Mar 28, 2026, Grade: A)
Source: ~/.claude/projects/-home-ubuntu-edgeclaw/memory/dfs-desk-data-inventory.md