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:
- Name one sheet tab
NoVig(exactly — the script references it). - Paste the script, replace
YOUR_MLAPI_KEYwith your actual key from MoneyLine API. - Save, then run
fetchNoVigOddsonce. Grant the OAuth permissions it asks for. - After the first run, go to Triggers and set
fetchNoVigOddsto 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:
- Kelly column:
=L2/(M2-1)gives you fractional Kelly stake as a percentage of bankroll. Add a bankroll input cell and multiply to get dollar size. - Best book column: Instead of pulling one book in Apps Script, pull all books via the
/v1/oddsendpoint and use=MAX(...)across multiple columns to surface the best available price automatically. - Line movement alert: Log the fair odds in a timestamped tab every 30 minutes and flag when fair probability shifts more than 2 points. That's a steam alert, built natively in Sheets.
- Multi-market tabs: Copy the NoVig tab, change the
marketparameter in the script (spreads,totals,player_props), and you've got the same engine running across all bet types.
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.