BettingLab

Build a No-Vig Fair Odds Calculator in Google Sheets

Marcus Hale
Marcus Hale

If you've ever stared at a two-way line — say, -118 / -108 — and wondered what the book actually thinks the probability is, you're already thinking correctly. The spread between those prices is where the house lives. Strip it out and you get the fair implied probability: the number every serious bettor should be comparing against before placing a bet.

This walkthrough builds a no-vig fair odds calculator in Google Sheets from scratch. You'll get: the core removal formulas, a clean layout you can copy in ten minutes, and — if you want live data — an Apps Script snippet that pulls current lines from the MoneyLine API directly into your sheet. No developer background required. If you can write a VLOOKUP, you can build this.


Why Removing Vig Actually Matters

Sportsbooks don't set lines at true probability. They inflate both sides so the combined implied probability sums to more than 100%. The excess — typically 4–8% for mainstream markets, worse for props — is called the overround or juice. Books collect it as margin regardless of outcome.

When you remove vig, you're asking: if this line had zero margin, what would each side price at? That fair price is your baseline. If you find a book offering the same side at better odds than the fair price, you have positive EV. If every book is worse, you're either beating an inefficient market or you need to look harder.

This is the foundation of EV betting. The no-vig calculator is the lens. Everything else — Kelly sizing, steam detection, line-shopping — depends on getting this number right.


The Core Formulas (No API Needed Yet)

Step 1: Convert American Odds to Implied Probability

Paste your two-way American odds into columns B and C. The formulas below handle both positive and negative lines.

Cell D2 — Implied prob for Side A (American odds in B2):

=IF(B2<0, ABS(B2)/(ABS(B2)+100), 100/(B2+100))

Cell E2 — Implied prob for Side B (American odds in C2):

=IF(C2<0, ABS(C2)/(ABS(C2)+100), 100/(C2+100))

Step 2: Calculate the Overround

Cell F2 — Total overround:

=D2+E2

A fair market sums to exactly 1.00 (100%). Anything above that is vig. A typical -110/-110 game line gives you 0.5238 + 0.5238 = 1.0476, meaning 4.76% juice baked in.

Step 3: Remove the Vig — Fair Probabilities

Divide each side's implied probability by the total overround to normalize to 100%.

Cell G2 — Fair probability Side A:

=D2/F2

Cell H2 — Fair probability Side B:

=E2/F2

These two should always sum to exactly 1.00. Sanity-check with =G2+H2.

Step 4: Convert Fair Probabilities Back to American Odds

Now flip back to American odds so you can line-shop apples-to-apples.

Cell I2 — Fair American odds Side A:

=IF(G2>=0.5, -(G2/(1-G2))*100, ((1-G2)/G2)*100)

Cell J2 — Fair American odds Side B:

=IF(H2>=0.5, -(H2/(1-H2))*100, ((1-H2)/H2)*100)

Step 5: EV Check Against Any Offered Line

You have a fair price. Now compare it to any book offering. Put the book's American odds in column K. The EV formula:

Cell L2 — EV% vs. offered line:

=IF(K2>=0,
  (K2/100)*G2 - (1-G2),
  (1-(G2))*(-100/K2) - G2*(1)
)

Wait — that's harder to read. Cleaner version using decimal odds as an intermediate:

Cell M2 — Offered line as decimal:

=IF(K2>=0, (K2/100)+1, 1-(100/K2))

Cell L2 — EV%:

=(G2*M2) - 1

Positive = you have edge. Negative = you're behind the fair line. Format L2 as a percentage. If it reads above 0%, you're extracting value; below 0%, the book is extracting it from you.

Complete Layout Reference

| Col | Label | Formula | |-----|-------|---------| | B | Side A (American) | manual input | | C | Side B (American) | manual input | | D | Implied Prob A | =IF(B2<0,ABS(B2)/(ABS(B2)+100),100/(B2+100)) | | E | Implied Prob B | =IF(C2<0,ABS(C2)/(ABS(C2)+100),100/(C2+100)) | | F | Overround | =D2+E2 | | G | Fair Prob A | =D2/F2 | | H | Fair Prob B | =E2/F2 | | I | Fair Odds A | =IF(G2>=0.5,-(G2/(1-G2))*100,((1-G2)/G2)*100) | | J | Fair Odds B | =IF(H2>=0.5,-(H2/(1-H2))*100,((1-H2)/H2)*100) | | K | Book Offered Odds | manual input | | M | Offered Decimal | =IF(K2>=0,(K2/100)+1,1-(100/K2)) | | L | EV% | =(G2*M2)-1 |

Drop this across rows 2–50 and you've got a scanner for 49 simultaneous markets.


Pulling Live Odds with Google Apps Script

Manual entry gets old fast. Here's how to wire the sheet to live odds from the MoneyLine API so column B and C populate automatically.

Open Extensions → Apps Script in your Google Sheet and paste this:

function fetchNoVigOdds() {
  const API_KEY = "YOUR_MLAPI_KEY"; // get one free at moneylineapp.com
  const BASE_URL = "https://mlapi.bet/v1/odds";

  // Pull MLB moneylines — change sport/market as needed
  const params = {
    sport: "baseball_mlb",
    market: "h2h",
    regions: "us",
    oddsFormat: "american"
  };

  const queryString = Object.entries(params)
    .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
    .join("&");

  const url = `${BASE_URL}?${queryString}`;

  const options = {
    method: "GET",
    headers: {
      "Authorization": `Bearer ${API_KEY}`,
      "Accept": "application/json"
    },
    muteHttpExceptions: true
  };

  const response = UrlFetchApp.fetch(url, options);
  const data = JSON.parse(response.getContentText());

  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NoVig");
  // Clear old data from row 2 down
  sheet.getRange("A2:C100").clearContent();

  let row = 2;
  data.forEach(event => {
    const home = event.home_team;
    const away = event.away_team;

    // Grab the first bookmaker's h2h prices
    if (event.bookmakers && event.bookmakers.length > 0) {
      const book = event.bookmakers[0];
      const market = book.markets.find(m => m.key === "h2h");
      if (market && market.outcomes.length === 2) {
        const homeOdds = market.outcomes.find(o => o.name === home)?.price;
        const awayOdds = market.outcomes.find(o => o.name === away)?.price;

        sheet.getRange(row, 1).setValue(`${away} @ ${home}`);
        sheet.getRange(row, 2).setValue(homeOdds ?? "");
        sheet.getRange(row, 3).setValue(awayOdds ?? "");
        row++;
      }
    }
  });

  SpreadsheetApp.getUi().alert(`Loaded ${row - 2} games.`);
}

Setup steps:

  1. Name one sheet tab NoVig (exactly — the script references it).
  2. Paste the script, replace YOUR_MLAPI_KEY with your actual key from MoneyLine API.
  3. Save, then run fetchNoVigOdds once. Grant the OAuth permissions it asks for.
  4. After the first run, go to Triggers and set fetchNoVigOdds to run every 30 minutes (time-based trigger) so your odds stay fresh without any manual refresh.

Columns A/B/C will now auto-populate. The formulas in D through L do the rest. You're looking at live no-vig fair prices without touching a single input manually.


Reading the Output — What to Do with the Numbers

When Fair Prob Diverges from Book Consensus

If your sheet shows fair probability of 52.4% for the home side, but the sharpest book is pricing it at -108 (implied 51.9%), that's a thin but real edge. The larger the gap, the more interesting the play — especially if multiple books are on the wrong side of your fair line.

Compare your sheet's fair odds against other platforms. Seeing consistent deviation across books suggests either the sharp consensus line you fed in was itself inefficient (common early in the week), or you've found a genuine pricing error. Both are worth tracking. See how this connects to detecting steam moves and sharp-book consensus — the two tools compound each other.

When EV is Positive but Small

A 1–2% EV edge isn't a get-rich-quick play. It's a long-run accumulation game. Kelly criterion says size proportionally to edge divided by odds. Don't overblow small edges. Log them, track them, and let the law of large numbers work. If you're consistently finding positive EV, you're beating the books. If you're not, the sheet will show you that too — brutally.

When Everything is Negative EV

Some days the market is efficient and every line you check is behind the fair price. That's information. Don't force action. The sheet is telling you the books are sharp today. Move on.


Extending the Sheet

A few natural upgrades once the base is working:

These aren't hypothetical upgrades. They're the natural next step once you see the base working. And if you want to push further into arbitrage detection, the no-vig fair price is the anchor you need for that calculation too.


Frequently Asked Questions

What is a no-vig fair odds calculator? It's a tool that removes the sportsbook's built-in margin (the "vig" or "juice") from a two-sided market to reveal the true implied probability each side is priced at. Once you have fair odds, you can compare them against any book's offered price to determine whether a bet has positive expected value.

How do I know if my no-vig formula is right? Sanity check: the two fair probabilities in columns G and H should always sum to exactly 1.00 (100%). If they don't, there's a formula error. Also verify: a standard -110/-110 line should produce a fair probability of exactly 50% on each side after vig removal, since the overround is symmetric.

Can I use this for props, not just game lines? Yes, with a caveat. Prop markets are two-sided (over/under or yes/no), so the same formulas apply. But prop vig is often much higher — 10–15% — which means the fair line can be quite far from the offered line. That inflated overround number in column F is useful information on its own: avoid heavily juiced props unless you have a strong model edge.

What's the MoneyLine API free tier? The free tier gives you 1,000 credits per month. A standard odds request costs a small number of credits per call. For a sheet refreshing every 30 minutes across one sport, you'll stay well within the free limit. Details at the MoneyLine API plan page.

Does this work in Excel, or only Google Sheets? All the formulas are standard and work identically in Excel. The live data integration requires Power Query instead of Apps Script, but the underlying logic is the same. Power Query can hit the https://mlapi.bet/v1/odds endpoint via Get Data → From Web with an API key header. The transformation steps map 1:1 with the Apps Script output.

Build with the same data we use.

MoneyLine API powers BettingLab's edge calculations. Free tier, 1k credits/month.