LOTTOLOGIC IQ
AI-Powered Lottery Analytics
Initializing...
Market Overview
Real-time analytics engine — updated daily at 6:00 AM ET
Best EV Game
calculating...
Best Score
weighted rank
Top Prizes Left
games w/ jackpot intact
Avg Portfolio ROI
across all scratch-offs
FL Jackpot Pool
scratch-offs only
Powerball
Wed & Sat draw
Expected Value Ranking (EV/$ticket)
Top Prize % Remaining by Game
Scratch-Off Analyzer
📍 Retailer Location Intelligence
PRO
How This Works: The FL Lottery publishes where winning tickets are sold — retailer name, city, ZIP, game, and prize amount. We track every claim and cross-reference it against your location.

Why It Matters: Each scratch-off game is printed as a finite run. When a top prize is claimed at a store near you, that specific game has fewer remaining winners in your area's ticket distribution chain. Other games at the same store are unaffected — a Publix that paid out 500X THE CASH is still clean for GOLD RUSH LEGACY.

What To Do: Enter your ZIP code below. The system calculates a Location-Adjusted Score per game (EdgeScore × Freshness × AreaPenalty × RiskMultiplier) so you know exactly which games to buy where — and when to drive to a different region for a specific game.
PLAY = no nearby wins for this game, fresh in your area MAYBE = mid-tier wins nearby, top prizes still available SKIP = top prizes already claimed in your area for this game
Draw Game Analysis
Loading draw history...
Capital Asset Modeling
Correlation · Cointegration · Drawdown · Sharpe · Kelly · Bell Curves
🧠 AI-Generated Play Strategies
Data-driven recommendations based on current EV, prize depletion, frequency patterns, and CAPM metrics. Updated with each data refresh.
Loading strategies...
Game ROI Correlation Matrix (top 8 games)
Measures EV return correlation between games by prize tier overlap. Higher = similar risk/reward profile. Use for portfolio diversification.
Price vs EV Scatter — All Games
Each dot = one game. Dots above the diagonal line = positive EV relative to price.
Cross-Game Frequency Correlation — Number Overlap Analysis
Measures how number frequency distributions correlate across games. High correlation = similar hot/cold patterns. Based on actual draw history.
Econometric Test Suite — All Draw Games
ADF = Augmented Dickey-Fuller (stationarity) · χ² = Chi-Squared (uniformity) · Pearson ρ = Linear Correlation · E-G = Engle-Granger (Cointegration)
Correlation (ρ) identifies if two games trend together. Cointegration (E-G) confirms if that relationship is a durable, long-run equilibrium.
Loading data... Select Scratch-Offs or Draw Games above.
Engle-Granger Pairwise Cointegration Matrix
Two-step Engle-Granger: OLS regression → ADF on residuals. Green = evidence of cointegration (p < 0.05). Tests whether game frequency patterns share long-run equilibrium.
Number Frequency Cross-Correlation Heatmap
Pearson correlation of number frequency vectors between game pairs. High values indicate similar hot/cold number distributions across games.
🔗 Cross-Game Research: Correlation & Cointegration
QUANT RESEARCH
Amateur tools stop at correlation (do they move together?). We add the Engle-Granger 2-step (is the residual spread stationary?) so we don't act on drifting noise. When a high-correlation, stationary-spread pair shows a wide divergence in the historical record, we flag it as a cross-game research signal — context for the Backtester, not a trading guarantee. Lottery games are statutorily games of chance and every individual ticket remains negative-EV.
Loading cross-game research analysis...
Lottery Sharpe Ratio (Top 10 Games)
Sharpe = (EV − RiskFree) ÷ StdDev(prize distribution). Higher = better risk-adjusted return. Risk-free set to $0 (no-play baseline).
Maximum Drawdown Simulation (200 ticket sessions)
Simulated cumulative P&L over 200 ticket purchases. Drawdown = peak-to-trough decline. Helps model bankroll volatility risk.
Risk-Adjusted Metrics Table
Prize Distribution Bell Curve — Select Game
Expected Outcome Distribution — 50 Ticket Simulation
Kelly Criterion Bet Sizing
Kelly Formula: f* = (bp − q) / b
where b = net odds, p = win prob, q = 1−p
Note: Kelly fractions are typically very small in lottery — this tool uses fractional Kelly (0.1×) for realistic bankroll sizing.
Kelly Bankroll Growth Simulation
EV vs ROI Bubble Chart
Bubble size = ticket price. X = expected value. Y = ROI%. Upper-right = best plays.
Prize Tier Breakdown — Donut Charts
EV CONTRIBUTION %
PRIZES REMAINING %
Unified Probability-Weighted Point System (0–100)
Every game, retailer, and strategy is ranked by a single composite score built from statistically-weighted sub-components. The score drives ALL recommendations across the platform — scratch-off rankings, draw game picks, budget allocations, retailer PLAY/SKIP signals, and strategy tier selections. Hover any score ring for the full breakdown.
Score Distribution — All Games
Component Contribution Breakdown
Master Probability Rankings — Full Table
CAPM Adaptation for Lottery Analytics
In traditional finance: R = Rf + β(Rm − Rf) + α. Here we adapt CAPM to model each scratch-off game as an "asset" where β (Beta) = sensitivity of a game's EV to the overall FL lottery market EV, α (Alpha) = game-specific excess return above what market exposure predicts, and Systematic vs Idiosyncratic risk = how much variance is market-driven vs game-specific. Games with high α and low β are the true edge plays — high return, low correlation to market downturns.
CAPM α (Alpha) — Excess Return vs Market
α > 0 = game outperforms market-predicted EV. Sort by α to find best plays regardless of market conditions.
CAPM β (Beta) — Market Sensitivity
β < 1 = defensive (less volatile than market). β > 1 = aggressive. Jackpot games have higher β.
Security Market Line — α vs β Scatter (Efficient Frontier)
Points above the SML line = underpriced (buy signal). Below = overpriced relative to their risk. X-axis = β (systematic risk). Y-axis = actual EV return. SML = predicted fair return for given β.
CAPM Risk Decomposition Table — Systematic vs Idiosyncratic
R² = systematic risk share. (1−R²) = idiosyncratic (game-specific) risk. High R², low α = market-driven game. Low R², high α = independent edge play.
Multi-State Expansion Architecture — Florida is the template. Each state is added as a new STATE_CONFIG entry with its scraper URL pattern, game ID range, API type, and prize structure. The same CAPM, backtester, hot/cold, and retailer intelligence engines run for every state automatically.
State Comparison — Best EV Game per State
Budget Optimizer
Kelly-weighted recommendations by budget allocation
Configure Session
Quant Note: Severe weather reduces retail foot traffic, mathematically increasing the EV of rolling jackpots by lowering the probability of a split prize. The engine will auto-shift to Conservative sizing if your budget exceeds your Stop-Loss threshold.
QUICK SELECT
Budget Allocation Pie
Area Intelligence — Where to Play
Loading area recommendations...
Hot / Cold Number Engine
Full historical frequency analysis · Hot = above avg · Cold = below avg · Due = longest gap
Number Frequency Heatmap — Last 500 Draws
Frequency Bar Chart with Probability %
🔥 HOT NUMBERS
❄ COLD NUMBERS
⚡ DUE NUMBERS
Note: "Due" is a statistical observation, not a predictor. Each draw is independent.
Number Pair Co-occurrence Frequency
Rolling Window Analysis (last 20/50/100 draws)
AI Number Suggestion Engine
Moderate: balanced approach across all signal types. Conservative optimizes for 2-3 number matches (frequent small wins). Aggressive targets full-match jackpots.
Loading suggestions...
🔒
PRO FEATURE
Upgrade to PRO for AI suggestions
AI Backtester — Historical Performance
ELITE
Loading backtester...
🔒
ELITE FEATURE
Upgrade to ELITE for AI backtesting
🎯 My Numbers Backtester
ELITE
Enter your own number picks for any draw game and see how they would have performed against every historical drawing.
Select a game and enter your numbers to start backtesting.
🔒
ELITE FEATURE
Upgrade to ELITE for My Numbers Backtester + AI Combo Optimizer
Strategy Center
AI-powered ticket stacking, combined scratch + draw plans, and advanced play strategies
SERVER OBSERVABILITY
Data Completeness · last 7 days
Loading completeness data…
DATE EXPECTED GENERATED MISSING COMPLETENESS BY STRATEGY
Loading…
What this measures: Each day the 06:00 ET cron generates picks for every game drawing that day. The total per day varies by day-of-week because Powerball (Mon/Wed/Sat), Mega Millions (Tue/Fri), FL Lotto (Wed/Sat), and JTP (Tue/Fri) only draw on specific days — so Sundays generate 180 picks (10 daily games × 6 strategies × 3 tiers), Mondays 198 (+Powerball), Tuesdays 216 (+MM +JTP), etc. The panel shows whether all expected combinations completed. Missing combinations usually mean insufficient draw history (newly-tracked games < 5 rows), database errors, or worker timeouts. If a date shows < 100%, click 🔧 REPAIR above (admin only) or call /api/forward/generate?date=YYYY-MM-DD manually.
Today's Optimal Ticket Stack
Based on current EV rankings, prize freshness, historical patterns, and Kelly-weighted sizing
Loading ticket stack...
Combined Scratch-Off + Draw Game Plan
60% Scratch / 40% Draw
Loading combined plan...
Timing & Freshness Signals
Loading timing signals...
Advanced Play Strategies
ELITE
Loading advanced strategies...
🔒
ELITE FEATURE
Upgrade to ELITE for advanced strategies
🎭 Contrarian Play Strategy — Collision Minimization Engine
QUANT
The Whale's Edge: Collision Minimization You cannot change the odds of a drawing, but you can change your payout. Over 70% of casual players pick numbers between 1-31 (birthdays/anniversaries) or geometric patterns on the playslip. If the winning numbers fall in those zones, you will likely split the jackpot with dozens of others.

Our algorithmic engine generates Contrarian Tickets. It explicitly filters out calendar dates, visual patterns, and human biases. The math is undeniable: you have the exact same odds of winning, but a drastically higher Expected Value (EV) because you keep the whole pot when it hits.
Birthday Trap — Numbers 1-31 represent only 44% of the pool but appear in ~70% of human picks
Multiples Trap — Multiples of 5 (5,10,15...) selected 2× more than random
Decade Clump — Players visually cluster ≥3 numbers in same 10-range on slip
Sequential Runs — Patterns like 7,8,9 or 10,20,30 are human favorites
We target — High numbers (32+), non-multiples, spread distribution
Click regenerate to generate tickets...
⚡ Dynamic EV Trigger — When to Play Engine
QUANT
The premise: Most lottery tickets have negative expected value (EV ~$0.40 on a $2 ticket). But as jackpots roll over, the EV improves. The EV Trigger calculates the exact jackpot threshold where cash value × (1 − 0.37 federal tax) ÷ ticket odds > ticket cost — the mathematical "BUY" signal.

FL advantage: No state income tax — your net payout is higher than most states.
❄️ Contrarian (Anti-Split) Strategy — Number Popularity Map
QUANT
The math: If you win a jackpot shared with 3 other players, you receive 25% of the pot. Studies show jackpot splits are 40-60% more common when players use "popular" numbers (birthdays, lucky 7, etc.). This tool maps number popularity so you can deliberately choose Contrarian combinations — same odds of winning, significantly higher expected payout when you do win.
🔴 = overplayed (avoid) · 🟡 = neutral · 🟢 = underplayed (target)
Source: Survey data on human number selection bias + FL historical patterns
Target number range: 32+ (above birthday bias zone)
Avoid: 1-31, multiples of 5/7, sequential runs
Sweet spot: 38-51, 57-63, 67-69 for Powerball
Loading contrarian picks...
Calculating...
📊 Forward Ledger — Daily Strategy P&L
PRO + ELITE SERVER-SIDE · DETERMINISTIC
Simulated Discipline Check · Expected ROI Negative
Every morning at 06:00 ET, the system generates picks for every game drawing that day: 6 strategies × 3 risk tiers × 10–12 game-lines. Per-day totals vary by day-of-week (180 picks Sun/Thu, 198 Mon, 216 Tue/Wed/Fri/Sat) because Powerball, Mega Millions, FL Lotto, and JTP only draw on specific weekdays. Daily games (Fantasy 5 Midday/Evening + Pick 2/3/4/5 Midday/Evening) generate every day. Each pick is locked in before the draw, then graded against the official result. Strategies are Hot Bias · Contrarian · Due · AI Balanced · Gemini Quant · Random Baseline. The Random Baseline is the empirical control — over a sufficient sample, no other strategy should consistently beat it, because lottery games are statutorily i.i.d. random events. Cumulative net P&L is expected to trend negative over time. This ledger exists to show users honestly what each strategy bleeds, not to claim an edge.
Total Picks
Settled
Pending
Total Spent
Total Won
Net P&L
ROI
Win Rate
downward = expected · Random Baseline = empirical control
Strategy Risk Tier Picks Settled Wins Win Rate Spent Won Net ROI
Loading…
Page 1
Issued vs Drawn: Picks are generated 06:00 ET on the Issued date. The Drawn column shows the actual draw — for games that don't draw daily (Powerball Mon/Wed/Sat, Mega Millions & JTP Tue/Fri, FL Lotto Wed/Sat), Drawn is the next scheduled draw at-or-after Issued.
Issued Game Strategy Risk Numbers (pick / draw) Special Cost Drawn Match Prize Net Outcome
Loading…
Disclosure: Lottery games are statutorily games of chance. Every individual ticket remains negative-EV in expectation. This ledger is a simulated discipline check showing what your P&L would have been following each strategy verbatim — it is NOT evidence of a winning edge. Past performance does not predict future outcomes. Subscription fees access analytics only; tickets must be purchased separately at licensed Florida retailers. 18+. 1-888-ADMIT-IT · Florida Council on Compulsive Gambling.
🔒
PRO + ELITE FEATURE
Upgrade to PRO ($25/mo) or ELITE ($40/mo) to access the Forward Ledger — 180–216 daily strategy picks (6 strategies × 3 risk tiers × 10–12 game-lines depending on which games draw that day), server-side scoring, P&L tracking across all active draw game lines.
🎟️ Scratch-Off Execution & Geo-Bounty Tracker
ELITE
How to use the Scratch Ledger: Log your scratch-off purchases here to track your true P&L against the EV math. Geo-Bounty: Enter your Target ZIP. The system continuously scans the FL Lottery database. If a top prize for your watched game is claimed in your region, the status will flash BURNED to prevent you from buying depleted inventory.
Date Logged Game Qty Cost EV at Purchase Geo-Bounty Status Result (Winnings) P&L
No scratch-offs tracked yet.
🔒
ELITE FEATURE
Upgrade to ELITE to track Scratch-Offs
Scraper + API Integration
Production-ready scrapers for Florida Lottery data feeds
// LottoLogicIQ — Node.js Scraper (Puppeteer + Cheerio)
// Scrapes: floridalottery.com/games/scratch-offs + draw results
// Run daily via cron: 0 6 * * * node scraper.js

const puppeteer = require('puppeteer');
const cheerio = require('cheerio');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

// ── CONFIG ──────────────────────────────────────────────
const CONFIG = {
  baseUrl: 'https://floridalottery.com',
  scratchUrl: 'https://floridalottery.com/games/scratch-offs',
  drawUrl: 'https://floridalottery.com/games/draw-games',
  gameIds: [1555,1562,1590,1594,1597,1604,1606,
            1608,1618,1619,1620,1621,1622,1623,1627],
  outputDir: './data',
  delay: 1500 // ms between requests (be respectful!)
};

// ── SCRAPE SINGLE SCRATCH GAME ──────────────────────────
async function scrapeScratchGame(gameId) {
  const url = `${CONFIG.baseUrl}/games/scratch-offs/view?id=${gameId}`;
  const res = await axios.get(url, {
    headers: { 'User-Agent': 'Mozilla/5.0 (compatible; LottoLogicBot/1.0)' }
  });
  const $ = cheerio.load(res.data);
  const prizes = [];

  // Parse prize table
  $('.odds-prizes-table tr, table tr').each((i, row) => {
    const cells = $(row).find('td');
    if (cells.length >= 3) {
      const prizeText = $(cells[0]).text().replace(/[$,]/g,'').trim();
      const oddsText = $(cells[1]).text().match(/[\d,]+$/)?.[0] || '0';
      const remText = $(cells[2]).text().trim();
      const [rem, total] = remText.split(' of ').map(x => parseInt(x.replace(/,/g,'')));
      if (isNaN(rem)) return;
      prizes.push({ prize: +prizeText, odds: +oddsText.replace(/,/g,''), rem, total });
    }
  });

  const topPrize = $('[data-top-prize], .top-prize').first().text().replace(/[$,]/g,'').trim();
  const topRemaining = $('.top-prizes-remaining').first().text().trim();
  const overallOdds = $('.overall-odds').first().text().replace('1:','').trim();

  return { gameId, topPrize: +topPrize || 0, topRemaining, overallOdds, prizes,
    scrapedAt: new Date().toISOString() };
}

// ── SCRAPE ALL GAMES ─────────────────────────────────────
async function scrapeAll() {
  console.log('[LottoLogic] Starting scrape...', new Date().toISOString());
  const results = {};

  for (const id of CONFIG.gameIds) {
    try {
      results[id] = await scrapeScratchGame(id);
      console.log(`  ✓ Game #${id} — ${results[id].prizes.length} prize tiers`);
    } catch (e) {
      console.error(`  ✗ Game #${id}:`, e.message);
    }
    await new Promise(r => setTimeout(r, CONFIG.delay));
  }

  const outPath = path.join(CONFIG.outputDir, `scratch_${Date.now()}.json`);
  fs.writeFileSync(outPath, JSON.stringify(results, null, 2));
  console.log(`[LottoLogic] Saved to ${outPath}`);
  return results;
}

// ── SCRAPE DRAW RESULTS ──────────────────────────────────
async function scrapeDrawResults() {
  const browser = await puppeteer.launch({ headless: 'new' });
  const page = await browser.newPage();
  await page.goto('https://floridalottery.com/games/draw-games/winning-numbers');
  await page.waitForSelector('.winning-numbers', { timeout: 10000 });

  const drawData = await page.evaluate(() => {
    const results = [];
    document.querySelectorAll('.draw-result-row').forEach(row => {
      const game = row.querySelector('.game-name')?.textContent;
      const date = row.querySelector('.draw-date')?.textContent;
      const nums = [...row.querySelectorAll('.ball')].map(b => +b.textContent);
      results.push({ game, date, numbers: nums });
    });
    return results;
  });

  await browser.close();
  return drawData;
}

scrapeAll().then(data => console.log('Complete', Object.keys(data).length, 'games'));
# LottoLogicIQ — Python Scraper
# pip install requests beautifulsoup4 selenium pandas schedule

import requests, json, time, schedule, logging
from datetime import datetime
from bs4 import BeautifulSoup
import pandas as pd

logging.basicConfig(level=logging.INFO, format='%(asctime)s %(message)s')

BASE_URL = "https://floridalottery.com"
GAME_IDS = [1555,1562,1590,1594,1597,1604,1606,
            1608,1618,1619,1620,1621,1622,1623,1627]
HEADERS = {"User-Agent": "LottoLogic/1.0 (educational research)"}

def scrape_game(game_id: int) -> dict:
    url = f"{BASE_URL}/games/scratch-offs/view?id={game_id}"
    r = requests.get(url, headers=HEADERS, timeout=10)
    r.raise_for_status()
    soup = BeautifulSoup(r.text, "html.parser")

    prizes = []
    for row in soup.select("table tr"):
        cells = row.find_all("td")
        if len(cells) < 3: continue
        prize_str = cells[0].get_text().replace("$","").replace(",","").strip()
        odds_str  = cells[1].get_text().replace(",","").strip()
        rem_str   = cells[2].get_text().strip()
        try:
            rem, total = [int(x.replace(",","")) for x in rem_str.split(" of ")]
            odds_val = int(odds_str.split("-in-")[-1])
            prizes.append({"prize": int(prize_str), "odds": odds_val, "rem": rem, "total": total})
        except: continue

    return {"game_id": game_id, "prizes": prizes,
            "scraped_at": datetime.utcnow().isoformat()}

def calc_ev(game: dict) -> float:
    return sum(p["prize"] * (1/p["odds"]) * (p["rem"]/p["total"]) for p in game["prizes"])

def daily_scrape():
    logging.info("Starting daily FL Lottery scrape...")
    results = {}
    for gid in GAME_IDS:
        try:
            results[gid] = scrape_game(gid)
            ev = calc_ev(results[gid])
            logging.info(f"  Game #{gid}: EV=${ev:.2f}, {len(results[gid]['prizes'])} tiers")
            time.sleep(1.5)
        except Exception as e:
            logging.error(f"  Error game #{gid}: {e}")

    fname = f"data/scratch_{int(time.time())}.json"
    with open(fname, "w") as f:
        json.dump(results, f, indent=2)
    logging.info(f"Saved {len(results)} games to {fname}")

# Schedule daily at 6 AM ET
schedule.every().day.at("06:00").do(daily_scrape)
if __name__ == "__main__":
    daily_scrape()  # run once immediately
    while True: schedule.run_pending(); time.sleep(60)
API Endpoints
MethodEndpointDescription
GET /api/gamesAll active scratch games
GET /api/games/:idGame detail + prize structure
GET /api/ev/:idExpected value calculation
GET /api/rankingsRanked game list by score
GET /api/draw/:gameDraw game history + hot/cold
GET /api/budget/:amountOptimized play plan
POST /api/simulateMonte Carlo simulation
POST /api/alertsSet prize-remaining alert
// Express.js API server — app.js
const express = require('express');
const { scrapeAll, calcEV } = require('./scraper');
const app = express();
app.use(express.json());

// Auth middleware
const auth = (req, res, next) => {
  const key = req.headers['x-api-key'];
  if (!key || !validKeys.has(key))
    return res.status(401).json({ error: 'Invalid API key' });
  next();
};

app.get('/api/games', auth, async (req, res) => {
  const data = loadLatestData();
  res.json(Object.values(data).map(g => ({
    id: g.gameId, ev: calcEV(g).toFixed(2), ...g
  })));
});

app.get('/api/budget/:amount', auth, (req, res) => {
  const b = +req.params.amount;
  res.json(optimizeBudget(b, loadLatestData()));
});

app.post('/api/simulate', auth, (req, res) => {
  const { gameId, tickets, sims } = req.body;
  res.json(monteCarlo(gameId, tickets, sims || 10000));
});

app.listen(3000, () =>
  console.log('LottoLogic API running on :3000'));
# crontab -e  — add this line for daily 6 AM ET scrape:
# 0 11 * * * cd /app && node scraper.js >> logs/scrape.log 2>&1

# GitHub Actions workflow (.github/workflows/daily-scrape.yml):
---
name: Daily FL Lottery Scrape
on:
  schedule:
    - cron: '0 11 * * *'  # 6 AM ET = 11 UTC
  workflow_dispatch:       # allow manual trigger

jobs:
  scrape:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: node scraper.js
        env:
          DB_URL: ${{ secrets.DATABASE_URL }}
          WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK }}
      - uses: actions/upload-artifact@v4
        with:
          name: scrape-data
          path: data/*.json
          retention-days: 30

# Docker Compose for full stack:
---
version: '3.8'
services:
  api:
    build: .
    ports: ["3000:3000"]
    environment:
      - DB_URL=postgresql://postgres:pass@db:5432/lottoedge
  db:
    image: postgres:16
    volumes: [pgdata:/var/lib/postgresql/data]
  scheduler:
    build: .
    command: node scheduler.js
    depends_on: [db]
volumes:
  pgdata:
// Alert system — sends Discord/Slack/Email when key events occur
const alerts = {
  // Trigger: top prize count drops (someone won!)
  topPrizeClaimed: async (gameId, prizeTier, newCount) => {
    const msg = {
      embeds: [{
        title: `🎰 TOP PRIZE CLAIMED — Game #${gameId}`,
        description: `$${prizeTier.toLocaleString()} prize won! **${newCount} remaining**`,
        color: 0xFF4D6D,
        timestamp: new Date()
      }]
    };
    await axios.post(process.env.DISCORD_WEBHOOK, msg);
  },

  // Trigger: EV crosses threshold (game becomes better value)
  evThreshold: async (gameId, ev, price) => {
    if (ev / price > 0.85) { // 85%+ return threshold
      await axios.post(process.env.SLACK_WEBHOOK, {
        text: `⚡ HIGH EV ALERT: Game #${gameId} at $${ev.toFixed(2)} EV on $${price} ticket`
      });
    }
  },

  // Daily digest email via SendGrid
  dailyDigest: async (topPlays) => {
    await sgMail.send({
      to: process.env.ALERT_EMAIL,
      from: '[email protected]',
      subject: `LottoLogic Daily Brief — ${new Date().toDateString()}`,
      html: buildEmailHTML(topPlays)
    });
  }
};

// Check for changes after each scrape
async function detectChanges(prev, curr) {
  for (const [id, game] of Object.entries(curr)) {
    const p = prev[id];
    if (!p) continue;
    // Top prize claimed?
    if (p.topPrizeCount > game.topPrizeCount)
      await alerts.topPrizeClaimed(id, game.topPrize, game.topPrizeCount);
    // EV improvement?
    await alerts.evThreshold(id, calcEV(game), game.price);
  }
}
Export Center
Download all analytics data as CSV or Excel for offline analysis, Excel modeling, or Python/Pandas import
📊 Scratch-Off Full Analysis
Exports all 15 scratch-off games with: EV, ROI, Sharpe, Kelly fraction, Edge Score, prize structure per tier, top-prize freshness, drawdown estimate, and composite rankings.
🎰 Draw Games Analytics
Exports all draw games with: jackpot amount, ticket cost, EV, expected ROI, hot/cold/due numbers, draw history count, backtester summary (if run), and strategy recommendations.
🤖 Backtester Results
Exports the full backtester history table: draw dates, actual numbers, AI picks per strategy, hit counts, prize amounts, and cumulative ROI. Requires backtest to be run first.
📦 Full Portfolio Report
Master export: scratch-offs + draw games + strategy recommendations + statistical tests + Kelly sizes in one file. Best for Excel modeling or sending to analysts.
🎯 Strategy Recommendations
Exports today's optimal play plan, budget allocations, AI number picks, EV trigger signals, contrarian picks, and anti-split recommendations.
🔥 Hot/Cold Number History
Exports number frequency data per draw game: frequency counts, probability %, chi² deviation, hot/cold classification, gap analysis, and signal composite scores.
Export Preview — Scratch-Off Data
Game IDNamePriceEVROI %Edge ScoreSharpeKelly %Top PrizeTop RemTop TotTop %OddsLaunchedRec
Preview shows first 10 rows of scratch-off export. Actual exports include all rows and additional columns.
Export Notes: CSV files open in Excel, Google Sheets, or any data tool. Excel (.xlsx) exports use multi-sheet format — one sheet per data category. All monetary values are in USD. ROI and probability values are expressed as percentages (%). Data reflects current static + live Supabase values. Re-export after 6 AM ET daily scrape for freshest data.
Choose Your Edge
Professional-grade lottery intelligence for serious players
All subscriptions include 7-day free trial · Cancel anytime · 18+ only · Gambling involves risk · Play responsibly · 1-888-ADMIT-IT
Subscription fees are for analytics access only — not lottery purchases. Tickets must be purchased separately at licensed Florida retailers.