'use strict'; const devig = require('../../src/utils/devig'); describe('de-vig engine (step 1)', () => { test('american → implied prob (favorite + dog + break-even)', () => { expect(devig.americanToImpliedProb(-110)).toBeCloseTo(0.5238, 3); expect(devig.americanToImpliedProb(+150)).toBeCloseTo(0.4, 3); expect(devig.americanToImpliedProb(+100)).toBeCloseTo(0.5, 3); expect(devig.americanToImpliedProb(0)).toBeNull(); expect(devig.americanToImpliedProb(null)).toBeNull(); }); test('prob → fair american is the inverse', () => { expect(devig.impliedProbToAmerican(0.5)).toBe(100); // +100 at 50% expect(devig.impliedProbToAmerican(0.6)).toBe(-150); expect(devig.impliedProbToAmerican(0.4)).toBe(150); expect(devig.impliedProbToAmerican(0)).toBeNull(); expect(devig.impliedProbToAmerican(1)).toBeNull(); }); test('two-way de-vig strips the vig; fair probs sum to 1', () => { // -110 / -110: each implies .5238, sum 1.0476 (4.76% vig) → fair .5 / .5 const d = devig.devigTwoWay(-110, -110); expect(d.method).toBe('multiplicative'); expect(d.overround).toBeCloseTo(0.048, 2); expect(d.over.fair_prob).toBeCloseTo(0.5, 3); expect(d.under.fair_prob).toBeCloseTo(0.5, 3); expect(d.over.fair_prob + d.under.fair_prob).toBeCloseTo(1, 6); }); test('a juiced book price de-vigs to a fairer number (the story)', () => { // book -145 over vs +115 under const d = devig.devigTwoWay(-145, +115); expect(d.over.fair_prob + d.under.fair_prob).toBeCloseTo(1, 6); // the fair over price is less juiced than the -145 book price expect(d.over.fair_odds).toBeGreaterThan(-145); }); test('only one side priced → fair UNAVAILABLE (never faked)', () => { expect(devig.devigTwoWay(-110, null)).toBeNull(); expect(devig.devigTwoWay(null, -110)).toBeNull(); expect(devig.devigTwoWay(undefined, undefined)).toBeNull(); }); test('EV% at the actual price from the model probability', () => { // model 55% on a +100 line: 0.55*2 - 1 = +10% expect(devig.evPct(0.55, +100)).toBeCloseTo(10, 1); // model 52.38% on -110 (= break-even): ~0 EV expect(devig.evPct(0.5238, -110)).toBeCloseTo(0, 0); // model 50% on -110 → negative (you pay the vig) expect(devig.evPct(0.5, -110)).toBeLessThan(0); expect(devig.evPct(null, -110)).toBeNull(); }); });