← Back to Tools

💰 Betting ROI Calculator

Track your win rate, profit/loss, and ROI over time

Total Bets
0
Win Rate
Total Profit/Loss
$0.00
0 wins, 0 losses
ROI
Return on investment
Avg. Stake
Per bet
No bets tracked yet. Add your first bet above.
How ROI is calculated:
ROI = (Net Profit / Total Staked) × 100.
Positive ROI = profitable bettor. Negative ROI = losing bettor over time.
Tip: Track every bet — winners and losers. Self-awareness is the first step to +EV betting.

For informational purposes only. Not legal gambling advice. Must be 21+ in your jurisdiction.
Gamble responsibly. If you or someone you know has a gambling problem, call 1-800-522-4700.

// Calculator let history = JSON.parse(localStorage.getItem('gameday_history') || '[]'); function americanToDecimal(am) { if (am >= 0) return (am / 100) + 1; return (100 / Math.abs(am)) + 1; } function calcPayout(stake, odds, isWin) { if (!isWin) return 0; return (stake * americanToDecimal(odds)) - stake; } function updateStats() { const total = history.length; const wins = history.filter(b => b.result === 'win').length; const losses = total - wins; const winRate = total > 0 ? ((wins / total) * 100).toFixed(1) + '%' : '—'; let totalStaked = 0, totalReturned = 0; for (const b of history) { totalStaked += b.stake; if (b.result === 'win') { totalReturned += calcPayout(b.stake, b.odds, true) + b.stake; } } const netPL = totalReturned - totalStaked; const roi = totalStaked > 0 ? ((netPL / totalStaked) * 100).toFixed(1) + '%' : '—'; const avgStake = total > 0 ? '$' + (totalStaked / total).toFixed(2) : '—'; document.getElementById('totalBets').textContent = total; document.getElementById('winRate').textContent = winRate; document.getElementById('winRate').className = 'stat-value ' + (winRate === '—' ? '' : parseFloat(winRate) >= 52 ? 'green' : 'red'); const plEl = document.getElementById('totalPL'); plEl.textContent = (netPL >= 0 ? '+$' : '-$') + Math.abs(netPL).toFixed(2); plEl.className = 'stat-value ' + (netPL > 0 ? 'green' : netPL < 0 ? 'red' : ''); document.getElementById('plSub').textContent = wins + ' wins, ' + losses + ' losses'; document.getElementById('roiValue').textContent = roi; document.getElementById('roiValue').className = 'stat-value ' + (roi === '—' ? '' : parseFloat(roi) >= 0 ? 'green' : 'red'); document.getElementById('avgStake').textContent = avgStake; // History list const histEl = document.getElementById('historyList'); if (history.length === 0) { histEl.innerHTML = '
No bets tracked yet. Add your first bet above.
'; } else { histEl.innerHTML = history.slice().reverse().slice(0, 10).map(b => { const payout = b.result === 'win' ? calcPayout(b.stake, b.odds, true) : -b.stake; const sign = payout >= 0 ? '+' : ''; const cls = payout >= 0 ? 'win' : 'loss'; const label = b.result === 'win' ? 'W' : 'L'; return `
${escHtml(b.desc || 'Bet')} · ${label} · $${b.stake.toFixed(0)} @ ${b.odds > 0 ? '+'+b.odds : b.odds} ${sign}$${payout.toFixed(2)}
`; }).join(''); } } function escHtml(s) { return String(s||'').replace(/&/g,'&').replace(//g,'>'); } document.getElementById('addBtn').addEventListener('click', () => { const desc = document.getElementById('betDesc').value.trim(); const odds = parseFloat(document.getElementById('betOdds').value); const stake = parseFloat(document.getElementById('betStake').value); const result = document.getElementById('betResult').value; if (!result) { alert('Select win or loss'); return; } if (isNaN(odds) || isNaN(stake) || stake <= 0) { alert('Enter valid odds and stake'); return; } history.push({ desc, odds, stake, result }); localStorage.setItem('gameday_history', JSON.stringify(history)); document.getElementById('betDesc').value = ''; document.getElementById('betOdds').value = ''; document.getElementById('betStake').value = ''; document.getElementById('betResult').value = ''; updateStats(); // Increment smart bets counter if (window.incrementSmartBets) window.incrementSmartBets(); }); document.getElementById('clearBtn').addEventListener('click', () => { if (history.length === 0) return; if (!confirm('Clear all bet history?')) return; history = []; localStorage.removeItem('gameday_history'); updateStats(); }); updateStats();