UNPKG

@neural-trader/sports-betting

Version:

Sports betting for Neural Trader - arbitrage detection, Kelly sizing, syndicate management

518 lines (410 loc) 14.4 kB
# @neural-trader/sports-betting [![npm version](https://img.shields.io/npm/v/@neural-trader/sports-betting.svg)](https://www.npmjs.com/package/@neural-trader/sports-betting) [![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](https://github.com/ruvnet/neural-trader) Advanced sports betting strategies with Kelly Criterion position sizing, arbitrage detection, and risk management for Neural Trader. Optimize bet sizing and find profitable opportunities across bookmakers. ## Features - **Kelly Criterion**: Mathematically optimal bet sizing for long-term growth - **Arbitrage Detection**: Find risk-free betting opportunities across bookmakers - **Syndicate Management**: Coordinate group betting pools with profit distribution - **Multi-Bookmaker Analysis**: Compare odds across 50+ betting providers - **Risk Management**: Position limits, bankroll protection, and drawdown controls - **Real-Time Odds**: Live odds updates and line movement tracking - **Market Analysis**: Identify value bets and market inefficiencies - **Rust Performance**: Sub-millisecond arbitrage detection ## Installation ```bash npm install @neural-trader/sports-betting @neural-trader/core @neural-trader/risk ``` ## Quick Start ### Kelly Criterion Bet Sizing ```typescript import { RiskManager } from '@neural-trader/sports-betting'; const riskManager = new RiskManager({ confidenceLevel: 0.95, lookbackPeriods: 100, method: 'historical' }); // Calculate Kelly Criterion for a bet const kelly = riskManager.calculateKelly( 0.55, // 55% win probability (your model's prediction) 2.0, // 2.0x payout on win (decimal odds) 1.0 // 1.0x loss on lose (stake) ); console.log(`Full Kelly: ${(kelly.kellyFraction * 100).toFixed(2)}%`); console.log(`Half Kelly (recommended): ${(kelly.halfKelly * 100).toFixed(2)}%`); console.log(`Quarter Kelly (conservative): ${(kelly.quarterKelly * 100).toFixed(2)}%`); // For a $10,000 bankroll const bankroll = 10000; const betSize = bankroll * kelly.halfKelly; console.log(`Recommended bet: $${betSize.toFixed(2)}`); ``` ### Arbitrage Detection ```typescript import { ArbitrageDetector } from '@neural-trader/sports-betting'; const detector = new ArbitrageDetector({ minProfitMargin: 0.01, // 1% minimum profit maxStake: 5000, bookmakers: ['bet365', 'draftkings', 'fanduel', 'betmgm'] }); // Find arbitrage opportunities for an NFL game const arbs = await detector.findArbitrage({ sport: 'americanfootball_nfl', market: 'h2h', // moneyline event: 'chiefs-vs-bills' }); for (const arb of arbs) { console.log(`Arbitrage Opportunity: ${arb.profitMargin.toFixed(2)}% profit`); console.log(`Bet ${arb.stakes.outcome1} on ${arb.bookmaker1} (${arb.odds1})`); console.log(`Bet ${arb.stakes.outcome2} on ${arb.bookmaker2} (${arb.odds2})`); console.log(`Guaranteed profit: $${arb.profit.toFixed(2)}`); } ``` ## Real-World Use Cases ### 1. NFL Betting with Kelly Criterion ```typescript import { RiskManager, OddsAnalyzer } from '@neural-trader/sports-betting'; // Your predictive model gives Chiefs 60% win probability const modelProbability = 0.60; const oddsData = await OddsAnalyzer.getOdds('americanfootball_nfl', 'chiefs-vs-bills'); // Best available odds: Chiefs -150 (1.67 decimal) const bestOdds = 1.67; // Calculate implied probability from odds const impliedProbability = 1 / bestOdds; // 0.598 (59.8%) // We have an edge: 60% > 59.8% const edge = modelProbability - impliedProbability; // 0.002 (0.2% edge) // Kelly Criterion calculation const kelly = riskManager.calculateKelly( modelProbability, // 60% win rate bestOdds - 1, // 0.67 (win amount) 1.0 // 1.0 (loss amount) ); // With $50,000 bankroll const bankroll = 50000; const fullKelly = bankroll * kelly.kellyFraction; // $600 (risky) const halfKelly = bankroll * kelly.halfKelly; // $300 (recommended) const quarterKelly = bankroll * kelly.quarterKelly; // $150 (conservative) console.log(`Edge: ${(edge * 100).toFixed(2)}%`); console.log(`Recommended bet (Half Kelly): $${halfKelly.toFixed(2)}`); ``` ### 2. Multi-Leg Arbitrage (Guaranteed Profit) ```typescript import { ArbitrageDetector, SyndicateManager } from '@neural-trader/sports-betting'; const detector = new ArbitrageDetector({ minProfitMargin: 0.02, // 2% minimum maxStake: 10000, bookmakers: ['bet365', 'draftkings', 'fanduel', 'pinnacle'] }); // Tennis match: Djokovic vs Nadal const arb = await detector.findArbitrage({ sport: 'tennis', market: 'h2h', event: 'djokovic-vs-nadal' }); if (arb) { console.log('=== Arbitrage Opportunity ==='); console.log(`Sport: ${arb.sport}`); console.log(`Event: ${arb.event}`); console.log(`Profit Margin: ${(arb.profitMargin * 100).toFixed(2)}%`); // Djokovic at DraftKings: 1.95 console.log(`\nBet 1: ${arb.player1} at ${arb.bookmaker1}`); console.log(`Odds: ${arb.odds1}`); console.log(`Stake: $${arb.stakes.player1.toFixed(2)}`); // Nadal at Bet365: 2.10 console.log(`\nBet 2: ${arb.player2} at ${arb.bookmaker2}`); console.log(`Odds: ${arb.odds2}`); console.log(`Stake: $${arb.stakes.player2.toFixed(2)}`); // Guaranteed profit console.log(`\nTotal Stake: $${arb.totalStake.toFixed(2)}`); console.log(`Guaranteed Profit: $${arb.profit.toFixed(2)}`); console.log(`ROI: ${(arb.roi * 100).toFixed(2)}%`); } ``` ### 3. Syndicate Betting Pool ```typescript import { SyndicateManager } from '@neural-trader/sports-betting'; const syndicate = new SyndicateManager({ id: 'nfl-week-1-pool', name: 'NFL Week 1 Betting Pool', totalCapital: 100000, distributionModel: 'hybrid', // Combines contribution and performance minProfitMargin: 0.01, maxPositionSize: 0.1 // Max 10% per bet }); // Add members with capital contributions await syndicate.addMember({ id: 'member1', name: 'John', email: 'john@example.com', contribution: 40000, role: 'lead-analyst' }); await syndicate.addMember({ id: 'member2', name: 'Sarah', email: 'sarah@example.com', contribution: 30000, role: 'data-scientist' }); await syndicate.addMember({ id: 'member3', name: 'Mike', email: 'mike@example.com', contribution: 30000, role: 'trader' }); // Find best opportunities across bookmakers const opportunities = await syndicate.findOpportunities({ sport: 'americanfootball_nfl', minEdge: 0.02, // 2% minimum edge minProfitMargin: 0.01 }); // Allocate capital using Kelly Criterion const allocation = await syndicate.allocateFunds(opportunities, { strategy: 'kelly_criterion', riskFactor: 0.5 // Half Kelly }); console.log('=== Syndicate Allocation ==='); for (const bet of allocation.bets) { console.log(`${bet.event}: $${bet.stake.toFixed(2)} at ${bet.bookmaker}`); console.log(`Expected ROI: ${(bet.expectedROI * 100).toFixed(2)}%`); } // After week 1: Distribute profits const weeklyProfit = 8500; // $8,500 profit const distribution = await syndicate.distributeProfits(weeklyProfit, { model: 'hybrid', performanceWeight: 0.3, contributionWeight: 0.7 }); console.log('\n=== Profit Distribution ==='); for (const member of distribution.members) { console.log(`${member.name}: $${member.share.toFixed(2)}`); console.log(`ROI: ${(member.roi * 100).toFixed(2)}%`); } ``` ## Kelly Criterion Deep Dive ### Understanding the Formula The Kelly Criterion calculates the optimal bet size as a fraction of your bankroll: ``` f* = (bp - q) / b Where: f* = fraction of bankroll to bet b = odds received (decimal odds - 1) p = probability of winning q = probability of losing (1 - p) ``` ### Kelly Variations ```typescript const kelly = riskManager.calculateKelly(winRate, avgWin, avgLoss); // Full Kelly (maximum growth, high volatility) const fullKelly = kelly.kellyFraction; // Half Kelly (recommended - reduces volatility by 50%) const halfKelly = kelly.halfKelly; // Quarter Kelly (conservative - reduces volatility by 75%) const quarterKelly = kelly.quarterKelly; ``` ### Example Calculations ```typescript // Scenario 1: Strong Edge // 60% win rate, 2.0x odds const strong = riskManager.calculateKelly(0.60, 2.0, 1.0); // Full Kelly: 20% of bankroll // Half Kelly: 10% of bankroll // Scenario 2: Moderate Edge // 52% win rate, 1.95x odds const moderate = riskManager.calculateKelly(0.52, 1.95, 1.0); // Full Kelly: 4% of bankroll // Half Kelly: 2% of bankroll // Scenario 3: Slight Edge // 51% win rate, 2.0x odds const slight = riskManager.calculateKelly(0.51, 2.0, 1.0); // Full Kelly: 2% of bankroll // Half Kelly: 1% of bankroll ``` ## Risk Management Integration ### Position Limits and Drawdown Controls ```typescript import { RiskManager } from '@neural-trader/sports-betting'; import { PortfolioRiskManager } from '@neural-trader/risk'; const portfolioRisk = new PortfolioRiskManager({ maxDrawdown: 0.20, // 20% max drawdown maxPositionSize: 0.10, // 10% max per bet maxDailyLoss: 0.05, // 5% max daily loss maxCorrelation: 0.7 // Limit correlated bets }); const sportsRisk = new RiskManager({ confidenceLevel: 0.95, lookbackPeriods: 100, method: 'historical' }); // Calculate bet with risk constraints async function placeBetWithRiskManagement( event: string, winProbability: number, odds: number, bankroll: number ) { // Kelly calculation const kelly = sportsRisk.calculateKelly(winProbability, odds - 1, 1.0); const rawBetSize = bankroll * kelly.halfKelly; // Check risk limits const riskCheck = await portfolioRisk.validatePosition({ size: rawBetSize, type: 'sports_bet', event: event, expectedReturn: (odds - 1) * winProbability - (1 - winProbability) }); if (!riskCheck.approved) { console.log(`Bet rejected: ${riskCheck.reason}`); return null; } // Adjust bet size based on risk limits const adjustedBetSize = Math.min( rawBetSize, riskCheck.maxSize, bankroll * 0.10 // Hard limit: 10% max ); console.log(`Kelly Recommended: $${rawBetSize.toFixed(2)}`); console.log(`Risk-Adjusted: $${adjustedBetSize.toFixed(2)}`); console.log(`Risk Score: ${riskCheck.riskScore.toFixed(2)}/10`); return { event, betSize: adjustedBetSize, odds, expectedValue: adjustedBetSize * ((odds - 1) * winProbability - (1 - winProbability)) }; } ``` ### Correlation Analysis ```typescript // Avoid overexposure to correlated outcomes const correlationMatrix = await portfolioRisk.analyzeCorrelation([ { event: 'chiefs-vs-bills', bet: 'chiefs_ml' }, { event: 'chiefs-vs-bills', bet: 'over_54.5' }, { event: 'chiefs-vs-bills', bet: 'chiefs_-3' } ]); // These bets are highly correlated - limit total exposure if (correlationMatrix.maxCorrelation > 0.7) { console.log('Warning: High correlation detected'); console.log('Reducing total position size...'); } ``` ## API Reference ### RiskManager ```typescript class RiskManager { constructor(config: RiskConfig); calculateKelly( winRate: number, avgWin: number, avgLoss: number ): KellyResult; calculateVaR( positions: Position[], confidenceLevel: number ): number; calculateExpectedValue( probability: number, odds: number, stake: number ): number; } interface KellyResult { kellyFraction: number; // Full Kelly halfKelly: number; // Recommended quarterKelly: number; // Conservative expectedGrowth: number; // Expected bankroll growth rate risk: number; // Volatility measure } ``` ### ArbitrageDetector ```typescript class ArbitrageDetector { constructor(config: ArbitrageConfig); findArbitrage(options: { sport: string; market: string; event: string; }): Promise<Arbitrage[]>; calculateStakes( odds1: number, odds2: number, totalStake: number ): { stake1: number; stake2: number }; monitorOpportunities( callback: (arb: Arbitrage) => void ): void; } interface Arbitrage { sport: string; event: string; bookmaker1: string; bookmaker2: string; odds1: number; odds2: number; stakes: { outcome1: number; outcome2: number }; profit: number; profitMargin: number; roi: number; } ``` ### SyndicateManager ```typescript class SyndicateManager { constructor(config: SyndicateConfig); addMember(member: Member): Promise<void>; allocateFunds( opportunities: Opportunity[], options: AllocationOptions ): Promise<Allocation>; distributeProfits( totalProfit: number, model: DistributionModel ): Promise<Distribution>; getStatus(): SyndicateStatus; } interface SyndicateConfig { id: string; name: string; totalCapital: number; distributionModel: 'proportional' | 'hybrid' | 'performance'; minProfitMargin: number; maxPositionSize: number; } ``` ## Supported Sports and Markets | Sport | Markets | Bookmakers | |-------|---------|------------| | NFL | Moneyline, Spread, Totals, Props | 50+ | | NBA | Moneyline, Spread, Totals, Props | 50+ | | MLB | Moneyline, Run Line, Totals | 50+ | | Soccer | 1X2, Over/Under, Both Teams Score | 50+ | | Tennis | Moneyline, Set Betting, Game Totals | 40+ | | MMA | Moneyline, Method of Victory | 30+ | ## Performance - **Arbitrage Detection**: <10ms per market scan - **Kelly Calculation**: <1ms per calculation - **Odds Comparison**: 50+ bookmakers in parallel - **Real-Time Updates**: Sub-second latency - **Rust WASM**: 10-50x faster than JavaScript ## Best Practices 1. **Use Half Kelly**: Full Kelly is too aggressive; half Kelly reduces volatility 2. **Verify Edge**: Only bet when you have a proven edge (model accuracy >52%) 3. **Track Performance**: Monitor actual vs expected results 4. **Manage Bankroll**: Never bet more than 5% on a single event 5. **Account for Correlation**: Limit exposure to correlated outcomes 6. **Monitor Limits**: Stay under bookmaker betting limits 7. **Tax Considerations**: Track all bets for tax reporting ## Examples See `/examples` directory for: - `kelly-criterion-nfl.ts` - NFL betting with Kelly sizing - `arbitrage-tennis.ts` - Tennis arbitrage detection - `syndicate-pool.ts` - Group betting pool management - `risk-management.ts` - Advanced risk controls - `correlation-analysis.ts` - Portfolio correlation ## Dependencies - `@neural-trader/core` - Core trading engine - `@neural-trader/risk` - Risk management and VaR - `odds-api` - Real-time odds data - `wasm-pack` - Rust WASM bindings ## License MIT OR Apache-2.0