If you've ever looked at a -110/-110 line and wondered what the book actually thinks the true probability is — stripping out their margin — you need a no-vig fair odds calculator in Google Sheets. That's what this post builds, end to end, with real formulas and a live data pull from the MoneyLine API.
The no-vig fair odds calculator is one of the most useful tools a bettor can have. It's the foundation of every EV calculation you'll ever run. Once you know the book's implied probability after the vig is removed, you can compare it against any line on the board and immediately see whether you're getting value or getting fleeced.
We're going to build this in two stages:
- A static sheet that takes two American odds inputs and outputs no-vig fair odds and implied probabilities.
- A live version that pulls the current two-way line for any game directly from the MoneyLine API and populates the sheet automatically.
No developer experience needed. If you can write =IF() formulas, you can follow this.
The Math: How Vig Removal Actually Works
Before touching a cell, you need to understand what's happening. Sportsbooks shade their lines so that the implied probabilities of both sides add up to more than 100%. That excess — the overround — is the house edge. Your job is to scale the implied probabilities back to exactly 100%.
Step 1 — Convert American Odds to Implied Probability
For a favorite (negative American odds like -150):
Implied Prob = |odds| / (|odds| + 100)
For an underdog (positive American odds like +130):
Implied Prob = 100 / (odds + 100)
So a -150 line implies 60% and a +130 line implies 43.48%. Those two sum to 103.48%. The 3.48% is the vig.
Step 2 — Normalize to 100%
Divide each side's implied probability by the total:
No-Vig Prob (side A) = Prob(A) / (Prob(A) + Prob(B))
No-Vig Prob (side B) = Prob(B) / (Prob(A) + Prob(B))
Step 3 — Convert Back to American Odds
For a probability above 50% (favorite):
Fair American Odds = -(prob / (1 - prob)) × 100
For a probability below 50% (underdog):
Fair American Odds = ((1 - prob) / prob) × 100
That's the entire algorithm. Everything in the sheet below is just these three steps wrapped in Sheets syntax.
Building the Static Calculator
Open a blank Google Sheet. Set up these cells:
| Cell | Label | Notes | |------|-------|-------| | A1 | Side A Label | e.g. "Astros" | | B1 | Side A American Odds | Enter -150 | | A2 | Side B Label | e.g. "Angels" | | B2 | Side B American Odds | Enter +130 |
Now add the calculated columns starting at D1:
D1 — Implied Probability, Side A
=IF(B1<0, ABS(B1)/(ABS(B1)+100), 100/(B1+100))
D2 — Implied Probability, Side B
=IF(B2<0, ABS(B2)/(ABS(B2)+100), 100/(B2+100))
D3 — Total Implied Probability (the overround)
=D1+D2
E1 — No-Vig Probability, Side A
=D1/(D1+D2)
E2 — No-Vig Probability, Side B
=D2/(D1+D2)
F1 — Fair American Odds, Side A
This one needs a branch: if the no-vig probability is ≥ 0.5, it's a favorite; otherwise it's a dog.
=IF(E1>=0.5, -(E1/(1-E1))*100, ((1-E1)/E1)*100)
F2 — Fair American Odds, Side B
=IF(E2>=0.5, -(E2/(1-E2))*100, ((1-E2)/E2)*100)
G1 — Vig Percentage
=(D3-1)*100
Format D1:D3 and E1:E2 as percentages. Format F1:F2 as a number with zero decimal places (or one if you want precision).
At this point, type -150 into B1 and +130 into B2. You should see:
- D3: 103.48% (the overround)
- E1: 57.97%, E2: 42.03%
- F1: -138, F2: +138 (approximately)
- G1: 3.48%
That's your baseline no-vig fair line. The book thinks this is roughly a -138 favorite. You posted at -150 — that's 12 cents of extra juice you're paying on Side A.
Adding an EV Column
If you want to see the EV of a bet at the posted odds versus the fair probability, add this at H1:
=(B1-(-100))/(ABS(B1))*E1 - (1-E1)
Wait — that formula isn't right for American odds. Let me give you the correct one. For a $100 bet on Side A:
=IF(B1<0, (100/ABS(B1))*E1 - (1-E1), (B1/100)*E1 - (1-E1))
This gives EV per $1 wagered, expressed as a decimal. Multiply by 100 to see it as a percentage. A negative number means you're paying too much vig for the edge you're getting. For reference, BettingLab's EV primer walks through the same concept from a theory angle if you want the longer treatment.
Pulling Live Odds with Google Apps Script
The static sheet is useful, but the real power is pulling live two-way lines for any game and populating B1/B2 automatically. Here's how to wire that up using Google Apps Script and the MoneyLine API.
Get Your API Key
Sign up at https://www.moneylineapp.com — the free tier gives you 1,000 credits/month, which is plenty for a sheet you refresh manually or on a timer.
The Apps Script
In your sheet, go to Extensions → Apps Script. Paste the following:
const API_KEY = "YOUR_MONEYLINE_API_KEY";
const BASE_URL = "https://mlapi.bet";
function fetchNoVigOdds(eventId) {
const url = `${BASE_URL}/v1/odds?event_id=${eventId}&markets=h2h&limit=1`;
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());
if (!data || !data.data || data.data.length === 0) {
return [["No data", "No data"]];
}
// Grab the first bookmaker's h2h market
const book = data.data[0];
const market = book.markets.find(m => m.key === "h2h");
if (!market || market.outcomes.length < 2) {
return [["No market", "No market"]];
}
const outcomeA = market.outcomes[0];
const outcomeB = market.outcomes[1];
// Convert decimal odds to American
function decimalToAmerican(dec) {
if (dec >= 2.0) {
return Math.round((dec - 1) * 100);
} else {
return Math.round(-100 / (dec - 1));
}
}
const americanA = decimalToAmerican(outcomeA.price);
const americanB = decimalToAmerican(outcomeB.price);
return [[outcomeA.name, americanA], [outcomeB.name, americanB]];
}
function refreshOdds() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// Read event ID from a designated cell — put your event ID in C5
const eventId = sheet.getRange("C5").getValue();
if (!eventId) {
SpreadsheetApp.getUi().alert("Put a MoneyLine event ID in cell C5 first.");
return;
}
const results = fetchNoVigOdds(eventId);
if (results.length >= 2) {
sheet.getRange("A1").setValue(results[0][0]); // Side A name
sheet.getRange("B1").setValue(results[0][1]); // Side A American odds
sheet.getRange("A2").setValue(results[1][0]); // Side B name
sheet.getRange("B2").setValue(results[1][1]); // Side B American odds
}
}
Save it. Back in your sheet, go to Extensions → Apps Script → Triggers and add a time-driven trigger on refreshOdds — every 5 minutes if you want near-live, or every hour for casual use.
Now drop any valid MoneyLine event ID into cell C5, click run once manually, and your B1/B2 odds cells populate. The rest of the no-vig formulas update instantly.
Finding Event IDs
You can browse events via the /v1/events endpoint. A quick call with your API key returns upcoming events with their IDs. The MoneyLine API build docs cover the full events endpoint schema — check there for filtering by sport, date range, and status.
Extending the Sheet: Multi-Book Comparison
Once you have one book's no-vig line, the natural next step is comparing it against several books and finding the sharpest consensus. Here's a pattern for that.
Add a second table below your main one (starting at row 6). In column A, list your books (DraftKings, FanDuel, BetMGM, etc.). In B and C, paste their odds manually or with separate fetchNoVigOdds calls for each book's ID. Then in D6 and E6, compute each book's no-vig prob the same way you did above.
In a summary row, use =AVERAGE(D6:D10) to get the consensus no-vig probability across all books. That consensus line is your sharpest estimate of true probability — sharper than any single book because you're averaging out each book's individual biases.
This consensus approach is related to what I described in the line-shopping context on the arbitrage edge page — the same principle of exploiting price dispersion, just applied analytically rather than mechanically.
FAQ
What is a no-vig fair odds calculator?
A no-vig fair odds calculator removes the sportsbook's built-in margin (the "vig" or "juice") from a two-sided betting line. It outputs the implied true probability of each outcome and converts those probabilities back to fair American odds. This tells you what the book actually thinks the probability is, without the markup.
Why does vig removal matter for betting strategy?
The vig is how books guarantee profit regardless of outcome. Once you remove it, you can compare the book's true implied probability against your own model's probability. If your model says an outcome is 55% likely and the no-vig implied probability is 50%, you have a positive EV bet. Without removing the vig first, your comparison is distorted.
How accurate is the no-vig method for finding true probabilities?
It depends on the book and market. Pinnacle and sharp books price markets efficiently, so their no-vig lines are close to the true probability. Square books may be off by several percentage points. For the most accurate consensus, average no-vig probabilities across three or more books, weighting sharp books more heavily.
Can I use this sheet for parlays or just straight bets?
This sheet handles one game at a time. For parlays, you'd multiply the no-vig probabilities of each leg to get the fair parlay probability, then convert that to American odds and compare it against what the book is offering. Parlay vig stacks multiplicatively, which is why correlated parlay edges (when legs have positive correlation) are so powerful — and why books restrict them.
How many API credits does a live refresh use?
Each call to /v1/odds uses credits based on the number of events and markets returned. With the MoneyLine API free tier at 1,000 credits/month, a single-event refresh every 5 minutes across a 12-hour betting window costs roughly 144 credits per day. Budget accordingly, or switch the trigger to manual refresh on heavy game days.
The no-vig fair odds calculator is table stakes for any serious bettor. If you're making decisions without first establishing the book's true implied probability, you're flying blind. Build this sheet once, wire it to the MoneyLine API, and you'll never again have to guess whether a line is value or trap.