Modules · Simulation
Simulation Engine
Run Monte Carlo simulations on pending offers before approving them. The engine predicts FSR impact, ARPU uplift, and revenue share eligibility — letting you approve with confidence, not guesswork.
Where simulation fits
Simulation is on-demand — call it before approving to see projected FSR impact and statistical confidence. It does not block the approval flow. You can approve without simulating.
Simulate an Approval
Call POST /v1/approvals/:id/simulate on any pending approval. The engine runs 10,000 Monte Carlo trials against the current player population and returns FSR bounds + pass/fail verdict.
# Simulate an approval before approving it in production
curl -s -X POST http://localhost:8005/v1/approvals/{approval_id}/simulate \
-H "Authorization: Bearer <dashboard-jwt>" \
-H "Content-Type: application/json" | jq .
# Response
{
"pass": true,
"pass_rate": 0.84,
"monte_carlo_runs": 10000,
"n_players": 4200,
"aggregate_fsr": 1.24,
"fsr_bounds": {
"lower": 0.97,
"upper": 1.51
},
"genre_context": {
"genre": "rpg",
"healthy_fsr_min": 0.8,
"healthy_fsr_max": 2.0,
"quadrant": "HEALTHY"
}
}FSR Quadrants
The simulation verdict is based on whether the projected FSR lands in a healthy quadrant for your game's genre. Thresholds are NOT universal — they are calibrated per genre.
DEFLATION
Players burn currency faster than they earn it. High churn risk. Increase earn sources or reduce prices.
HEALTHY
Economy is balanced. AI offers are permitted. Revenue share metrics are measured here.
INFLATION
Too much free currency. Devalues IAP. Tighten earn sources or introduce a currency sink.
HYPER_INFL
Severe inflation. AI offers are suppressed (OPA compliance). Immediate economy correction required.
FSR — Faucet/Sink Ratio
Core economy health metric. Powered by economy_ledger (append-only). Genre thresholds are calibrated by M14 — never hardcode 0.9–1.1.
# FSR = Faucet/Sink Ratio
#
# Measures the balance between currency earned and currency spent.
# Computed over the last 7-day rolling window per player cohort.
#
# Formula:
# FSR = total_currency_earned / total_currency_spent
#
# Quadrants (genre-adjusted thresholds — NOT universal 0.9–1.1):
# DEFLATION FSR < genre.healthy_min Players burning faster than earning
# HEALTHY genre.healthy_min ≤ FSR ≤ genre.healthy_max
# INFLATION FSR > genre.healthy_max Too much free currency
# HYPER_INFL FSR > genre.healthy_max × 2.5
#
# Genre thresholds (from M14 calibration — do NOT hardcode 0.9/1.1):
# puzzle: 0.6 – 1.6
# rpg: 0.8 – 2.0
# strategy: 0.7 – 1.8
# casual: 0.5 – 1.4
# hyper_casual: 0.3 – 1.2
# simulation: 0.9 – 2.5
# sports: 0.6 – 1.5
# shooter: 0.7 – 1.9Economy FSR API
Fetches current FSR from ClickHouse (7-day rolling window, daily breakdown, per-currency). Served by python-admin:8000.
# Economy FSR endpoint — genre-adjusted quadrant analysis
curl -s "http://localhost:8000/v1/games/{game_id}/economy/fsr?days=7" \
-H "Authorization: Bearer <dashboard-jwt>" | jq .
# Response
{
"game_id": "33333333-3333-4333-8333-333333333333",
"genre": "rpg",
"period_days": 7,
"fsr": 1.24,
"quadrant": "HEALTHY",
"thresholds": { "min": 0.8, "max": 2.0 },
"daily_fsr": [
{ "date": "2026-03-21", "fsr": 1.18 },
{ "date": "2026-03-22", "fsr": 1.31 },
{ "date": "2026-03-23", "fsr": 1.24 }
],
"currency_summary": [
{ "currency_id": "gold", "earned": 4250000, "spent": 3428000, "fsr": 1.24 }
]
}Holdout ARPU Comparison
Measures whether AI-treated players generate more revenue than the holdout group. Uses Mann-Whitney U (one-sided) — never t-test, as IAP data is power-law distributed and t-test produces false significance.
# Check holdout ARPU uplift (Mann-Whitney U, not t-test)
curl -s http://localhost:8000/v1/games/{game_id}/holdout-arpu \
-H "Authorization: Bearer <dashboard-jwt>" | jq .
# Response
{
"treatment_arpu": 1.42,
"control_arpu": 1.18,
"uplift_pct": 20.3,
"p_value": 0.031,
"n_treatment": 12400,
"n_control": 1380,
"days_live": 47,
"revenue_share_eligible": true,
"ineligible_reasons": []
}Revenue Share — 5 Eligibility Conditions
Revenue share activates only when all 5 data-driven conditions are met. Never on a calendar date. Check eligibility via the API.
| # | Condition | Why |
|---|---|---|
| 1 | n_treatment ≥ 10,000 | Minimum treatment group size for statistical power |
| 2 | n_control ≥ 1,000 | Minimum holdout group size (10% of DAU target) |
| 3 | days_live ≥ 30 | Minimum observation window for seasonality |
| 4 | Mann-Whitney U p < 0.05 | Statistically significant ARPU uplift (one-sided) |
| 5 | arpu_uplift > 0 | Positive direction — treatment earns more than control |
# Revenue share eligibility check (5 conditions)
curl -s http://localhost:8000/v1/games/{game_id}/revenue-share \
-H "Authorization: Bearer <dashboard-jwt>" | jq .
# Response (all 5 conditions must be true for eligibility)
{
"eligible": true,
"conditions": {
"n_treatment_gte_10k": { "value": 12400, "pass": true },
"n_control_gte_1k": { "value": 1380, "pass": true },
"days_live_gte_30": { "value": 47, "pass": true },
"p_value_lt_0_05": { "value": 0.031, "pass": true },
"arpu_uplift_positive": { "value": 0.2034, "pass": true }
},
"rate_pct": 16,
"plan": "grow",
"next_bill": "2026-04-01"
}Revenue Share Rates by Plan
| Plan | Monthly players | Base Fee | Rev Share (on uplift) |
|---|---|---|---|
| Indie | up to 100K | $299/mo | Agreed with you |
| Studio | up to 500K | $799/mo | Agreed with you |
| Scale | up to 2M | $2,499/mo | Agreed with you |
| Enterprise | Unlimited | Custom | Custom |
Revenue share is charged only on measured holdout uplift — not on total revenue. If the AI generates no measurable uplift, you pay only the flat SaaS fee.
⚠ Holdout Group Rules
- •10% permanent holdout — assigned via SHA-256 hash of
player_id + game_id. Deterministic — same player always maps to same group. - •Holdout players NEVER receive AI-generated offers. Offer pipeline returns 204 at Step 4.
- •Holdout group size cannot be changed after launch — changing it invalidates the statistical comparison.
- •Do NOT manually assign VIP players to holdout — this biases the ARPU comparison downward.