Guest-worth analytics for casino resorts

ResortWorth

Sabermetrics for the resort: a documented library of guest-worth metrics that goes past ADT, behavior-first personas your hosts can actually remember, and an AI analyst that shows its SQL and refuses to guess.

100% synthetic data. Every guest, rating, and offer is generated by a seeded simulator. No real patron data appears anywhere in this project.

The demo is the real dashboard, running on the synthetic warehouse.

Overview · trailing 90 dayssynthetic
Theo win
$4.21M 3.2%
Rated visits
41,882 1.1%
ADT
$58.40 0.9%
RE
0.86× 4.4%
Midnight Floor Loyalists
overnight regulars, metronomic rhythm
6.4% of theo
WI+118
VAW$66
Visits / mo4.6
LTV24$9.4k
Theo win by day3 ms
Win-back queue
RFH 0.9118d out · rhythm 6d
RFH 0.7831d out · rhythm 14d
RFH 0.7244d out · rhythm 21d
Illustration of the demo dashboard. Every figure shown is synthetic.
The metrics library

Fourteen documented metrics, not one opaque score.

The industry still ranks guests on ADT — average daily theoretical — the way baseball once ranked hitters on batting average. It is a single number with no peer context, no sample-size discipline, and no way to tell luck from worth.

Every metric here is documented like a baseball card: a definition, the formula, why it beats the ADT view, and a line on how to act on it. The same registry that computes a metric writes its glossary entry, its tooltips, and the analyst’s description of it — so a CFO can audit any number down to the arithmetic.

Also in the library: LCK, a luck index in game-math standard deviations, which separates a guest who is running bad from a guest who is worth less (and flags the persistent negative tail as possible advantage play). And RE / PEL, which ask the question reinvestment percentage cannot: did the offer buy incremental play, or did it pay someone to do what they were going to do anyway?

WI+Worth Index Plus

Worth indexed to comparable guests. 100 is exactly peer par; 150 is 50% above.

100 × worth-per-active-day ÷ peer average

Why it beats ADT — The OPS+ move. A $60/day local and a $60/day fly-in are not the same asset — peer context is what raw ADT never gives you.

VAWVolatility-Adjusted Worth

Worth per day, shrunk toward the peer mean in proportion to how little we have actually observed.

(n · worth + k · peer_mean) ÷ (n + k), k = 8 active days

Why it beats ADT — Empirical-Bayes shrinkage. Two visits at $400 theo is weak evidence — one hot weekend can’t mint a fake VIP.

RFHRecency-Frequency Hazard

Probability that the current absence already exceeds this guest’s own visit rhythm.

P(gap ≤ days_since_last) under the guest’s own Weibull fit

Why it beats ADT — 21 quiet days is an emergency for a three-times-a-week local and noise for a quarterly visitor. Fixed churn windows miss both.

The persona engine

Clusters your hosts can actually remember.

Guests are clustered on roughly sixteen behavioral features — worth, cadence, game mix, bet level, time fingerprint, promo response — with a Gaussian mixture and soft membership, so a guest can be 60/40 across two personas instead of being forced into one bucket.

Each cluster comes out as a character with a memorable name: Midnight Floor Loyalists, Weekday Video Poker Regulars. Each ships a stat line as percentiles of the whole book, psychographic traits that are always labeled with the behavior they were inferred from, and a playbook of trigger → action → the metric it should move.

Demographics are profiled, never clustered on. Age and distance describe a persona after the fact; they never define one. Clusters are gated on bootstrap stability before they earn a card, and guests with too little observed play are told so rather than being quietly assigned.

Weekday Video Poker Regulars

mid-week grinders, low bet, long sessions

9.1% of theo
ADT$44
WI+127
Visits / mo6.2
PEL0.12

Bars are percentiles of the whole book; the tick is the median.

Psychographics — inferred from behavior
  • high routine-seeking — from inter-visit regularity, TCR 0.84
  • low novelty-seeking — from game concentration, GDE 0.14
  • low promo elasticity — from visit odds on offer vs non-offer days
Playbook · RFH crosses 0.7 → mid-week free-play tuned to their daypart, not a weekend mailer → should move visits / mo and RE, not just response rate.
A persona card from the demo. Synthetic guests, real method.
The AI analyst

An analyst that shows its SQL — and admits what it can’t answer.

Ask in plain language. The analyst matches the question against a curated catalog over a semantic layer, extracts the slots it needs — dates, metrics, personas, top-N — runs parameterized SQL, and narrates the result deterministically.

The query is always on screen. Numbers come from the warehouse, never from a language model’s memory of what a number like that usually looks like.

Off-catalog questions get a straight refusal plus the nearest questions it can answer. A model that says “I don’t have that data” is worth more than one that produces a confident, unfalsifiable paragraph — especially when someone is about to spend reinvestment budget on the answer.

Which personas have the best reinvestment efficiency this quarter?

Weekday Video Poker Regulars lead at RE 1.42 — $1.42 of incremental worth per comp dollar. Midnight Floor Loyalists trail at 0.31: their offers are largely paying for visits that would have happened anyway.

Weekday Video Poker Regulars1.42
Reel Loyalists0.94
Midnight Floor Loyalists0.31
▾ SQL — always shown
select persona_name,
       round(sum(incr_worth) / nullif(sum(comp_cost), 0), 2) as re
from marts.patron_360
where last_active between $start and $end
group by persona_name
order by re desc
deterministic engine · confidence 0.94 · 4 ms

Which guests are most likely to book a spa package?

I can’t answer that. This warehouse has no spa or hotel folio data, and I don’t guess at numbers. Here is what I can answer:

Who is most movable by offers?Which personas are lapsing fastest?How is theo trending?
Responsible gaming

Protection wired into the marketing engine, not bolted onto it.

Five behavioral flags — session escalation, loss chasing, frequency spikes, late-night concentration, stake drift — each carrying the evidence that triggered it, composited into a risk tier a human can review.

Guests at the Elevated tier are automatically excluded from frequency-stimulating offers. That exclusion lives inside the persona playbooks, in the pipeline, not in the memory of whoever pulls the list this month.

Flags are evidence for a conversation, not a verdict. Every one of them shows the behavior and the window that produced it, so the person acting on it can see exactly what the model saw.

Guest 4482-1179
Midnight Floor Loyalists · 14 months tenure
RG Elevated
risk 0.78
  • session escalation
    median session 41 → 96 min over 8 weeks
  • loss chasing
    re-buy within 20 min in 3 of the last 4 losing trips
  • late-night concentration
    63% of play 12am–6am, up from 28%
Guardrail

Auto-excluded from frequency-stimulating offers. The exclusion is enforced in the persona playbook itself — it is not left to whoever pulls the mailing list.

Illustrative flag card. The guest, the flags, and the evidence are synthetic.
Where this goes

Today the gaming floor. The architecture is the whole property.

The demo measures gaming worth, because gaming is what the simulator generates today. Everything you can click on is floor data: trips, ratings, theo, comps, offers.

The warehouse, the metric registry, and the persona engine were built to take hotel folios, F&B checks, entertainment, and retail on the same guest key — so the same metrics resolve to one unified guest worth across the resort rather than a gaming number and four spreadsheets.

That is the direction, and it is honest to call it a direction. Property-wide worth is designed for and not yet shipped.

Under the hood
DuckDB
columnar warehouse — the analytics live in SQL, never in the API layer
25,000
synthetic guests, drawn from eight latent behavioral archetypes
2 years
of simulated play: trips, ratings, comps, offers, tiers
1 seed
one command rebuilds the identical warehouse, every time
1–5 ms
typical query time — and every response carries its own

Python, polars, scikit-learn, and DuckDB for the pipeline; FastAPI over a read-only warehouse; Next.js for the dashboard. Determinism is a test, not a promise: the generator’s math invariants, the metric golden values, and the persona stability gates all run in CI.

See it running

The demo is the whole thing: the glossary, the persona gallery, guest 360s, the floor and promotion views, the responsible-gaming queue, and the analyst — all over 25,000 synthetic guests.