v3 Phase A (urgent): bookmaker odds capture — the Model-vs-Market benchmark
- docs/V3-GIGA-PLAN.md: the v3 plan (data lake to 7+GB, GIGA ensemble, scoreboard, UI clarity) with the honest reframe: perfect accuracy = perfect calibration; 'beat the betting sites' = a live public head-to-head, scored with proper rules. - src/lib/odds.ts: American-ml → decimal, de-vig (normalize away the margin), overround; 3 vitest cases incl. tonight's real opening lines. - ESPN core odds adapter (server/src/ingest/espnOdds.ts): captures DraftKings 1X2 moneylines + O/U + spread per fixture; follows $ref pointer items. - odds_history table (insert-if-changed → clean line-movement history); scheduler odds sweep every 3h over a 14-day horizon, first sweep at boot; /api/odds + /api/odds/:num. Odds are a benchmark ONLY — never a model input. - Boot speed-up: fixture↔event mapping skips dates already fully mapped. - Verified: 54 fixtures captured with real moneylines locally. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+8
-1
@@ -9,7 +9,7 @@ import { TournamentState } from './tournament';
|
||||
import { startScheduler } from './ingest/scheduler';
|
||||
import { ModelEngine } from './model';
|
||||
import { buildPreview, buildTeamProfile } from './preview';
|
||||
import { db, healthAll } from './db/db';
|
||||
import { db, healthAll, oddsFor, latestOddsAll } from './db/db';
|
||||
import { canonicalTeam } from '../../src/lib/teams';
|
||||
import type { MatchStatus, ServerMessage } from '../../src/lib/types';
|
||||
|
||||
@@ -57,6 +57,13 @@ export function buildServer() {
|
||||
app.get('/api/snapshot', async () => state.snapshot());
|
||||
app.get('/api/predictions', async () => model.current());
|
||||
app.get('/api/sources/health', async () => ({ sources: healthAll() }));
|
||||
// Bookmaker odds (benchmark for the Model-vs-Market scoreboard; not a model input)
|
||||
app.get('/api/odds', async () => ({ odds: latestOddsAll() }));
|
||||
app.get('/api/odds/:num', async (req, reply) => {
|
||||
const num = Number((req.params as { num: string }).num);
|
||||
if (!Number.isFinite(num)) return reply.code(400).send({ error: 'bad num' });
|
||||
return { history: oddsFor(num) };
|
||||
});
|
||||
app.get('/api/preview/:num', async (req, reply) => {
|
||||
const num = Number((req.params as { num: string }).num);
|
||||
const preview = Number.isFinite(num) ? buildPreview(num, state, model) : null;
|
||||
|
||||
Reference in New Issue
Block a user