Files
vyndr/src/utils/kelly.js
T
builtbykev d242b11b4b S1 (a1): feature-promise audit — no claim survives unverified
PROMISE-AUDIT.md: every /pricing claim → verified/built/reworded.
BUILT (was vapor): alt line ladder + edge ranking (same-features regrade
at shifted lines, Desk-gated at the API), quarter-Kelly (engine quantile
P(win) x real captured odds — either missing → no sizing), free-tier
kill-condition locked previews. FIXED (was false): analyst 15/day cap vs
the Founder 'Unlimited reads' promise → analyst unlimited; every '40+
factors' claim (real count: 22 named features) reworded truthfully in 7
files. VERIFIED: cascade alerts (real, wired), phi correlation,
leg history, cross-book comparison, WC soccer, real-time feed.
Locked by tests/unit/promiseAudit.test.js. Jest now ignores
.claude/worktrees (parallel agents' suites no longer leak into runs).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 14:24:41 -04:00

42 lines
1.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use strict';
/**
* Quarter-Kelly sizing (Session 62 / A1-S1 — the pricing page promised it;
* now it exists). Pure math, no I/O.
*
* DATA SEMANTICS: Kelly needs a REAL win probability and REAL book odds.
* p comes from the engine's quantile probability estimator (game-log based);
* odds come from the captured book row. Either missing → null — a sizing
* recommendation is never fabricated from confidence scores or defaults.
*/
function americanToDecimal(american) {
const a = Number(american);
if (!Number.isFinite(a) || a === 0) return null;
return a > 0 ? 1 + a / 100 : 1 + 100 / Math.abs(a);
}
/**
* quarterKelly(p, americanOdds) →
* { full, quarter, pct } — fractions of bankroll (pct = quarter × 100,
* rounded to 0.1) — or null when p/odds are unusable or the edge is
* non-positive (Kelly says: no bet).
*/
function quarterKelly(p, americanOdds) {
const prob = Number(p);
if (!Number.isFinite(prob) || prob <= 0 || prob >= 1) return null;
const dec = americanToDecimal(americanOdds);
if (dec == null || dec <= 1) return null;
const b = dec - 1;
const full = (b * prob - (1 - prob)) / b;
if (!Number.isFinite(full) || full <= 0) return null;
const quarter = full / 4;
return {
full: Math.round(full * 1000) / 1000,
quarter: Math.round(quarter * 1000) / 1000,
pct: Math.round(quarter * 1000) / 10, // % of bankroll at quarter-Kelly
};
}
module.exports = { quarterKelly, americanToDecimal };