Billing Overhaul, Crypto Payments, Model Accuracy Leap, Google Ads Attribution
NBA Model Retrained with Team Stats: Brier improved 0.131 → 0.127 (3.2%). Added ORtg/DRtg/pace features that were trained but never fed real data at inference — the cache was empty for NBA and NHL. Fixed, rebuilt, retrained as Split-Phase model with 16 features including momentum.
NHL Model Retrained: Brier improved 0.205 → 0.157 (23.6%). Biggest single-model accuracy jump ever. Same root cause: team stats cache was NCAAMB-only. NHL now has ortg/drtg/pace/pp_pct/pk_pct/save_pct/faceoff_pct flowing at inference.
NHL Injury System: New nhl_injuries.py with 44 tracked skaters (McDavid 12%, Draisaitl 10%, Makar 9%, etc). Live ESPN API, goalie-excluded (handled by separate GOALIE_QUALITY overlay), ±12% cap. First real data: Carolina 7 skaters out → NYR +12% adjustment.
Live Recalibration System: New live_recalibrator.py — rolling isotonic regression on last 500 resolved predictions per sport. Auto-refits every 25 new samples. Persists to JSONL. Activates after 50 resolved trades. Catches calibration drift without full retraining.
MLB Bullpen Quality Overlay: New mlb_bullpen.py with 30-team bullpen ERA rankings. Time-scaled: 0% impact in innings 1-4, scales to 100% in 8th-9th. ATL/LAD/HOU elite (3.10-3.20 ERA) vs COL/CWS weak (4.40-4.45). Capped ±5%.
Momentum Ablation Test: Confirmed momentum features (run_diff_120s/300s) improve NBA Brier by 1.1% (0.12655 with vs 0.12794 without). Keeping them.
Crypto Payments (NowPayments): Bitcoin, Ethereum, USDC, USDT, and 350+ coins now accepted. 10% crypto discount on all products. "Pay with crypto" CTA on every pricing card and checkout interstitial. Email validation prevents empty-email invoices. Full billing event tracking + admin dashboard integration.
Abandoned Cart Recovery: Stripe after_expiration.recovery enabled on every session. 60-minute session expiry (was 24 hours). Webhook handler sends "Your trial is waiting" recovery email with Stripe's recovery URL. 212 recovery emails sent on first day.
Google Ads Attribution Fix: Conversion events were reporting $0 value (Stripe trial = $0 charge). Now passes plan sticker price ($49) as expected LTV. Added Enhanced Conversions (email hashing for cross-device attribution). Added begin_checkout GA4 event on every interstitial page load (150/day top-of-funnel signal). New GCLIDMiddleware captures gclid/gbraid/wbraid as first-party cookies (90-day TTL).
Real MRR Dashboard: New /admin/revenue page with honest numbers — Real MRR (status=active only), At-Risk MRR (no-card trials), Projected MRR, Cash Collected. 30-day Stripe vs Crypto rail-split stacked bar chart (inline SVG, no JS library). Daily Discord MRR ping at 09:03 UTC.
Admin Support Tool: New /admin/support/mint-link — paste a customer email + pick a product → generates a fresh Stripe hosted checkout URL pre-filled with their email. For customers who can't get through the normal checkout (IAB browsers, etc).
Middleware Security Overhaul: Converted 5 BaseHTTPMiddleware classes to pure ASGI (eliminated LocalProtocolError: Too much data for declared Content-Length — 200 crashes/day → 0). GZipMiddleware moved to outermost position. CSP tightened with explicit form-action allowlist for Stripe + NowPayments + Coinbase Commerce hosts.
IAB Interstitial Improvements: Added "Continue in this browser anyway" escape hatch (tracked via inapp_browser_override event). Trimmed IAB fragments list (removed Messenger/LinkedIn/Reddit/Pinterest — they work fine with Stripe). Added STRIPE_CHECKOUT_IAB_MODE env var (block/warn/allow).
Stripe Key Rotation: Migrated from standard sk_live_ to restricted rk_live_ key (smaller blast radius). Consolidated secrets into single /opt/fairprob/.env (was split across two files). Scrubbed old key from 4 backup/staging locations.
Cron Observability: New cron_heartbeat.py — every cron writes start/ok/error to an append-only JSONL ledger. Fixed retention_emails cron (ModuleNotFoundError for 7+ days). Fixed run_campaigns.sh strict mode. Logrotate split: copytruncate for api.log, create for cron logs.
Campaign Drip Fix:run_campaigns.sh was silently broken (SyntaxError in heredoc). Manual recovery sent 98 backlogged Day 2/Day 5 emails. Backfilled campaign_state.jsonl to prevent duplicate sends.
Card-Required Experiment: Flipped STRIPE_API_STARTER_NO_CARD_TRIAL_PCT from 50% → 0% (all signups require card). Discovered 5 of 7 trialing customers had no card on file. Conversion dropped from 3.4% to 0% — root cause was audience/pricing mismatch, not the card requirement itself.
File Ownership Sweep: 4,742 files on VPS were owned by macOS uid 501/staff (rsync artifact). Chowned to root:root. Deploy scripts now exclude *.jsonl to prevent state-file clobber.
Test Coverage: 200+ new tests across 7 test files (ads attribution, billing health, stripe MRR, admin mint-link, IAB interstitial, Dodo billing, checkout dedup). Full regression: 174+ passing.
v9.0April 6, 2026
Model Intelligence Upgrade — All 5 Bots Improved
NBA Model Retrained: Calibration improved 44% (ECE 0.103 → 0.057). Switched from XGB+Isotonic to tuned XGBoost. Dynamic edge thresholds enabled — early-game requires higher edges (model uncertainty 18.7c), late-game accepts smaller edges (4c).
NBA Injury Integration: Real-time ESPN injury API + 35-player star impact table. Jokic out = -16% WP, LeBron = -12%. Applied after model prediction, before edge calculation. Capped at ±15%.
CS2 Combined Model: Map-specific CT win rates (Nuke 57%, Dust2 51%, 9 maps). 4-tier economy system (>15K gap = +20% round advantage). Conditional dampening: 0.75 for combined model, 0.70 for Elo-only. Team rank confidence modulates Elo trust.
CS2 Filters Optimized: min_edge 10→8c (5-10c bucket has 71.4% WR), max_edge added at 25c (20c+ edges have 36% WR — model overconfident), entry range 30-65c (sweet spot from backtest).
LoL ML Model Trained: Was running Elo-only despite full ML pipeline existing. Trained XGBoost on gold diff (39% importance), kills, towers, dragons, barons. Brier improved 47.8% (0.256→0.134), AUC from 0.575→0.890. +5K gold at 20min now correctly predicts 82% WP instead of ~55%.
Tennis WTA Calibration: Split serve rates for ATP vs WTA (WTA hard: 58% vs ATP 64%). Set dominance momentum: 6-0 win → +4% WP boost, tiebreak → no adjustment, comeback → +2% bonus.
MLB Model Hash Fixed: MLB model was SKIPPED due to stale SHA256 hash file. Regenerated — all 7 sports now loading correctly.
Homepage 4-Phase Improvement: Clearer positioning ("ML-powered sports prediction models"), 2 CTAs only above fold, canonical proof block on pricing/results/course, "What can go wrong" risk disclosure.
CS2 Backtest: New backtest_cs2_combined.py using bo3.gg historical data + bookmaker odds. 121 trades, +8.4c/trade net. Economy snapshot trades: 97.1% WR (late-game bias noted).
Google Ads Campaign: New API trial campaign with 15 headlines + 5 long headlines + 4 descriptions. Separate from course campaign.
Bing Webmaster: BingSiteAuth.xml deployed for Bing verification.
v8.0April 4, 2026
Major Platform Overhaul — Infrastructure, Marketing, Security, CS2 Model
Unified Trading Bot: All 5 sport bots (Moneyline, CS2, LoL, Soccer, Tennis) consolidated into single process with shared WS connection, global circuit breaker, and portfolio-level risk management
CS2 bo3.gg Integration: Replaced HLTV (Cloudflare-blocked) with bo3.gg as primary data source. New combined series + map model uses live economy data (equipment values, buy phases). Backtest: 121 trades, +8.4c/trade net
Circuit Breakers on All Bots: Added $20 daily loss limit, 5-loss streak cooldown, 30% rolling WR gate to CS2, LoL, Soccer, Tennis. Fixed cents→dollars bug that was tripping breakers too early
Feed Quality System: New feed_quality.py scores every signal (price freshness, match confidence, spread). warm_start.py blocks trading until 30% of tokens have fresh prices for 15s. execution_queue.py prevents duplicate trades on restart
Email Drip Campaign: 6-step automated funnel (Day 2 calculator → Day 5 feedback → Day 8 results → Day 12 course → Day 20 API → Day 30 winback). 42+ emails sent to 54+ subscribers. Behavior-based triggers for activation reminders
Activation Flow: Dedicated /activate page for passwordless accounts. Full funnel tracking: activated_at, first_dashboard_at, first_progress_at, first_rating_at. Reactivation campaign sent to 23 unactivated users
Backtest Integrity: All 14 backtests graded (production/semi-realistic/research-only). LoL backtest rebuilt with real Polymarket prices. NFL training split fixed (2020-21 season ordering). Honest numbers on all public pages (+2.4c net, not +10.9c)
State-Aware Site: Every page personalized by user state (free/paid/course owner/activated). Recovery actions shown automatically. Pricing CTAs change by tier. Course tab shows personalized next steps
Dashboard UX: Game detail drawer (click any row), mobile card layout, sticky filter bar, min-edge filter, human clock format, signal flash animation, freshness indicator, sport filters on games tab
Results Page: Ledger status bar (freshness, quality), sport filters, expandable trade rows, clear Live/Open/Backtest sections with "Simulated" badge
Research Paper: Published white paper at /research — 4 revision cycles, statistical significance tests, baseline comparisons, threats to validity. Email-gated PDF download
5 Monitoring Agents: Reconciliation, strategy allocator, claim integrity, entitlement QA, deployment drift — all running daily via cron with Discord alerts
Cache Pipeline: Stale pruning (-1/+14 days), sport normalization, active cache (48h tradable tokens), sport shards, publish quality gate, health summary
12 Blog Posts: 5 new technical posts (Polymarket API, calibration, Elo ratings, WebSocket data, backtesting pitfalls)
Purchase Flow: Every purchase path sends confirmation email. Webhook creates accounts. Bundle buyers get both API + course emails. Re-download section on account page
Growth Automation: Twitter agent posting wins, Discord fill notifications, daily/weekly summaries, metrics agent tracking MRR/users/email analytics — all on autopilot via watchdog.sh
Claim Audit: Backtest table updated from stale v2 data to v4 model results (1,171 trades, 70.9% WR). Numbers synced across course.html, pricing.html, email templates. Source of truth: model v4 + Elo improvements, Mar 2026
Results Page: Renamed to "Filtered Public Ledger" with explicit start date, reconciliation status (healthy/warning), excluded rows count, and clearer scope labels
Dashboard Course Tab: Backend-saved progress (replaces localStorage). Resume/next-step hero CTA. Expandable module workspaces with checklists, common failures, success criteria. Contextual support by module. Live proof panel with per-sport stats
Trade Resolution Cron: Auto-resolves pending trades every 15 minutes via Polymarket settlement API. No more manual PnL corrections
OddsAPI Fix: Retry backoff on 401/failure (was hammering API every 5s). Daily budget tracking. Key updated for 100K/mo plan
Tennis Bot: Added WTT tour support (ATP + WTA + WTT)
Blog: 4 new posts — execution quality deep dive, 5 bots P&L transparency, multi-venue edge guide, hold-to-settlement strategy
Wording: "Sign up" → "Create Account" across all user-facing pages
Model Quality API:/v1/model/performance — Brier score, ROC-AUC, ECE, accuracy, and full conformal calibration tables for all 7 sports
CLV Tracking:/v1/model/clv — live closing line value tracking. Measures how often our entry price beats the final market price
Confidence Intervals: All prediction endpoints now include calibrated prediction bands from conformal prediction tables. Width narrows as games progress
Venue Status:/v1/venues — real-time status of all connected data venues (Polymarket, Kalshi, DraftKings, FanDuel, etc.)
Venue Filter:?venue=kalshi on /v1/games and /v1/edges to filter by specific venue
Intraday WP Snapshots:/v1/snapshots/{sport}/{date} — win probability archived every 30s during live games (Pro+ tier)
Batch Predictions:/v1/predictions/batch — bulk download predictions for up to 90 days (Pro+ tier)
Webhook Push:/v1/webhooks — register URLs to receive edge signals in real-time via signed POST requests (HMAC-SHA256)
Email Drip Campaigns: 6-step automated sequence for launch signups (Day 2 calculator, Day 5 feedback, Day 8 results, Day 12 course, Day 20 API, Day 30 win-back)
Course Rating System: Star ratings + written reviews at /course/rate with social proof widget on course page
5 New Blog Posts: Polymarket API tutorial, model calibration guide, Elo ratings from scratch, WebSocket data guide, backtesting pitfalls
NFL Model Fix: Corrected season ordering bug where 2020-21 test set was older than training data (data leakage eliminated)
Bot Safety: Circuit breaker (daily loss limit + streak detection), bankroll depletion check, WS/ESPN staleness guards, performance dashboard every 10 min
Multi-venue pricing: edges now computed across Polymarket, Kalshi, and 15+ sportsbooks (DraftKings, FanDuel, BetMGM, etc.) via the-odds-api.com
Cross-venue game matching: automatic team name normalization across ESPN, Polymarket, Kalshi, and sportsbook feeds (127 team mappings)
Best venue indicator: dashboard shows which venue has the best price per side for every game
Venue filter: Edge Scanner now filterable by venue (Polymarket, Kalshi, DraftKings, FanDuel)
Prediction API (B2B): /v1/predict/{sport}/live — live win probabilities + multi-venue edges for all active games
Pregame predictions: /v1/predict/{sport}/pregame — Elo-based pregame win probabilities for today's scheduled games
Single game detail: /v1/predict/{sport}/{game_id} — full model output for a specific game
Fair lines endpoint: /v1/fair-lines/{sport} — fair moneylines in American odds format
Usage metering: /v1/usage — monthly request tracking with per-endpoint breakdown
Monthly API caps enforced per tier: Free (100), Starter (10K), Pro (100K), Enterprise (unlimited)
American odds conversion: fair probabilities displayed as moneylines for sportsbook integration
Multiplicative vig removal for sportsbook odds — true implied probability from raw lines
Adaptive sportsbook polling: only fetches odds for sports with active ESPN games, respecting API budget
Graceful degradation: runs Polymarket-only when no ODDS_API_KEY configured
v4.0March 24, 2026
Advanced Elo engine — MOV, dynamic K, surface-specific ratings
Margin-of-Victory (MOV) multiplier for basketball & football Elo — blowouts update ratings more than narrow wins, with autocorrelation correction to prevent double-counting expected outcomes
Dynamic K-factor for basketball & football: new teams converge 1.5x faster, established teams stabilize at 0.8x K
MOV/dynamic K intentionally disabled for low-scoring sports (NHL, MLB) where margin is noise
Combined moneyline backtest: 1,171 trades, 70.9% WR, +11.0c/trade, +$128.88 total
NBA: +8.5c/trade (up from +0.6c pre-Elo) — biggest winner from MOV + dynamic K