PP
Predictive Playbook Database
Historical — College Football
Active Opportunities Saved Queries Results Matching Rows Field Reference Numeric Field Stats Query Syntax & Examples

Active opportunities — upcoming games matching a saved system

Loading…

Query (PPQL) — historical_cfb_games

New here? That's just a sample query so you have something to look at — type over it, or use the plain-English box above instead.
Typing after team=, opponent=, conference=, opponentconference=, venue=, lineprovider=, or gametype= pops up matching values — click one, or arrow-key + Enter/Tab to pick it, so you never have to remember the exact spelling.
Run a query to see available columns.
Saved queries

Result significance

Run a query above to see its record, ROI/profit, and per-game averages here.
Record after a loss — how the system does on the very next game, immediately following one of its own losses
—
—
—

Matching rows

Field reference

Browse all fields, live from the server, plus shortcuts — click any field to insert it
Loading field list…

Numeric field stats ?

Count / sum / mean / median / std / variance / quartiles / min / max for every numeric field
FieldCountSumMeanMedianStdVarianceQ1 (25%)Q3 (75%)MinMax

Query syntax & examples

Operators, ranges, prefixes (tpS, p:/n:/o:), shortcut fields (PPG, 3DPCT...), and field coverage notes
Combine with and / or. Ranges: 9.5>=line>=3.5 — the middle term can also be a season-aggregate call, e.g. 28>=tA(points)>=21 or 28>=oA(points)>=21.
Set membership: field in [v1, v2, ...] / field not in [v1, v2, ...] — e.g. team in ['Army','Navy','Air Force'] instead of chaining team='Army' or team='Navy' or team='Air Force' by hand. Works inside prefixes too, e.g. o:team in ['Army','Navy','Air Force'] = today's opponent is one of those teams — combine both to match games where EITHER side is a service academy. Values follow the same quoting rules as a normal comparison (quoted string, number, or bareword) and are typed per-field, so season in [2023,2024] parses each as a number.
classification is 'fbs' or 'fcs' — Division II/III games aren't imported (no betting-market relevance), so those two are the only values you'll see.
rank/opponentrank are this team's and the opponent's AP/committee poll rank entering the game — a query like rank=0 and opponentrank>=1 and opponentrank<=10 finds an unranked team facing a ranked one (there's no dedicated "unranked" flag; an unranked team's rank is simply not populated, so test the field it does have instead).
finalrank is this team's spot in the season's FINAL AP Top 25 (released after bowls) — the SAME value on every one of that team's games that season, since it's a once-a-year fact, not a per-game one; 0 = finished unranked. Combine with gamenumber=1 (this team's actual Week 1 game, bye-proof) and rank to compare preseason vs. final: gamenumber=1 and rank>=1 and rank<=25 and finalrank=0 finds every team that opened in the preseason top 25 but finished the year unranked, e.g. grouped @season for a per-year count. cfprank is the CFB Playoff committee's own weekly rank (separate from rank, which prefers AP/Coaches) — only populated once the committee starts releasing rankings, usually around week 9.
Season lookback: tpS(field) = this team's SUM over its previous season, tppS(field) = two seasons back, tpA(field) / tppA(field) = AVERAGE instead of sum, tpMAX(field) / tppMAX(field) = MAX, tpMIN(field) / tppMIN(field) = MIN — S/A/MAX/MIN are the four aggregate kinds. Two calls can combine with one operator: tpS(passingyards)/tpS(passingattempts)>=8, or e.g. tpMAX(wins)>=6 = won at least 6 games in some previous season. Opponent-anchored shorthand: oA(field)/oS(field)/oMAX(field)/oMIN(field) — same as tA()/etc. but for the same-game OPPONENT's own season, no colon needed (equivalent to the longer o:tA(field) form). Nests: oA(o:points) = what the opponent ALLOWS per game (their own PAPG), while bare oA(points) = what the opponent scores per game.
Previous/next games: p:/pp:/... (back) and n:/nn:/... (forward) — e.g. p:H and pp:H and ppp:H = last 3 games were all home. Head-to-head: P:/PP:/... (previous meeting vs today's opponent) and N:/NN:/... (next meeting). Opponent's own games: op:/opp:/... and on:/onn:/.... Same game, opponent's side: o: — e.g. o:points>=30. Compound (add a trailing "o" to any of the above): reaches the referenced game, THEN that game's own opponent — po:points>=100 = in my previous game, the team I played scored 100+; opo:points>=24 = in my current opponent's own previous game, the team THEY played scored 24+.
Numeric shortcut for any of the above: a count instead of repeating the letter — p3: = ppp:, p7: = ppppppp:, op5: = oppppp:, N2: = NN: — e.g. p7:points>=24 instead of spelling out seven p's.
All accept the H/A/N/W/L shortcuts (home/away/neutral site, win/loss) — these also work bare at the top level of a query, e.g. team='Alabama' and H and W. Windowed count: tS(cond,N=k) — e.g. tS(W,N=3)>=2 = won at least 2 of its last 3 games.
Previous-season streak: STREAKPREV(N,W) / STREAKPREV(N,L) — matches when this team's LAST N games of its PREVIOUS season were all wins (W) or all losses (L), correctly anchored to the prior season no matter what week of the CURRENT season you're querying from. This is different from p:L and pp:L, which have no season boundary and drift into the current season's own games once enough of them exist (e.g. at week 8, p:L and pp:L means weeks 6-7 of THIS season, not last season's finish) — e.g. STREAKPREV(2,L) = lost its last 2 games of last season, regardless of the current week. W/L here use the same ATS (against-the-spread) definition as the bare W/L shortcuts, not straight-up.
Season-long condition (no field name required — a whole comparison instead): tS(cond) = COUNT of games this season/prior season where cond holds, tA(cond) = the FRACTION (0-1) of such games — same tp/tpp lookback and opponent-anchor shorthand as the field form. E.g. tpA(atsmargin>0)*100>=65 = covered the spread in at least 65% of last season's games (note: field names have no underscore — atsmargin, not ats_margin — and this returns a 0-1 fraction unless you add *100, same convention as 3DPCT below). tpS(atsmargin>0)>=11 = covered at least 11 games last season.
A prefix can also be used as a VALUE instead of a whole condition — field>prefix:field2 — e.g. points>o:points = outscored the opponent, line<=p:line = today's line is at or below the previous game's.
A field can be compared against a number times ANOTHER field — field OP number*field2 (either order) — e.g. -line>=.4*total = the favorite is laying at least 40% of the total.
Group by any field right in the query text with @field instead of the dropdown below — e.g. season=2023 @conference = one row per conference for the 2023 season.
Shortcut fields: PPG = points scored per game this season, PAPG = points ALLOWED per game (defense), YPPT = total yards per point (season), 3DPCT/4DPCT/COMP = third-down/fourth-down/completion conversion percentage (season — an actual percentage, use >=45, not >=.45; COMP is passingcompletions over passingattempts). All work as a bare comparison (PPG>=27, COMP>=64) or inside a prefix (o:PPG>=27 = what today's opponent scores on offense). No RZPCT here — this table has no red-zone tracking columns (CFBD's team-stats data doesn't expose them), unlike the NFL table.
Matchup shortcuts: CONF/NCONF = team and today's opponent do/don't share a conference. Unlike the shortcuts above these are whole boolean conditions, not values — use them bare, e.g. team='Ohio State' and NCONF or CONF and line>=3. No DIV/NDIV here — this table has no division field the way the NFL table does. Same result either as conference!=o:conference (the general same-game-opponent join, works on any field) or the simpler opponentconference!=conference (this table already stores the opponent's own conference directly on every row — no join needed).
gamenumber is this team's real Nth game of the season — different from week, which can skip a number on a bye week.
Full field list is above, under "Field reference" (fetched live from the server, so it always matches what the parser actually accepts) — click any field to insert it.
Data coverage: the college football import is ongoing and expanding backward season by season, so which years have data (and how complete each season's box-score/betting-line coverage is) will keep growing over time — a season with no matching rows simply returns an empty result, not an error.
siq ("scored in quarter") is the count of quarters this team scored in — 4 if they scored in every regulation quarter, 5 if they also scored in OT (any number of OT periods — CFB combines them into one number, so 5 is still the max). Works like any other numeric field, e.g. siq=4, siq>=3, or tA(siq)>=3.5 for a season-to-date average.
Use the grouping dropdown to break a query's record out by season/team/conference/etc. instead of one combined total. Click any breakdown row to drill into the individual games behind it.

Add a new algorithm