|
Download README.md from ThreeSixNine/poker-risk-engine: direct link, hf CLI and curl.
- Browser
- Download file 2.76 kB
-
https://huggingface.co/ThreeSixNine/poker-risk-engine/resolve/main/README.md
- Command line
-
hf download hf://ThreeSixNine/poker-risk-engine/README.md
-
curl -L -o README.md https://huggingface.co/ThreeSixNine/poker-risk-engine/resolve/main/README.md
2.76 kB
| title: Poker decision engine with a calibrated risk knob | |
| license: mit | |
| tags: | |
| - ml-intern | |
| - poker | |
| - decision-engine | |
| - risk-control | |
| - monte-carlo | |
| # poker-risk-engine | |
| A poker decision engine where **risk appetite is a single, calibrated scalar | |
| knob** `r ∈ [0,1]` — the piece our survey found missing from every public poker | |
| agent: levers exist in the literature, but nobody ships an aggression dial with | |
| measured, monotone response curves. | |
| ## The knob | |
| `r` simultaneously and monotonically controls: calling threshold | |
| (`pot_odds − 0.20·r`), raise threshold (`0.62 − 0.10·r`), bet threshold | |
| (`0.60 − 0.12·r`), and bet sizing (`0.45 + 0.55·r` of pot). Equity is Monte | |
| Carlo vs uniform opponents (treys). | |
| ## Calibration (120 seeded scenarios, eval_knobs.py) | |
| | r | VPIP | PFR | Aggr. rate | Bet/pot | | |
| |---|---|---|---|---| | |
| | 0.0 | 0.36 | 0.00 | 0.15 | 0.91 | | |
| | 0.5 | 0.55 | 0.06 | 0.19 | 1.35 | | |
| | 1.0 | 0.72 | 0.16 | 0.22 | 1.82 | | |
| All four aggression metrics are monotone in r (script-verified). **Honest | |
| caveat:** heuristic mean EV rises monotonically to r=1.0 with no interior peak — | |
| under a fold-equity-only EV model, aggression is never penalized, so the EV | |
| curve reflects the EV model's known weakness, not an uncalibrated knob. An EV | |
| model with value-realization dynamics would likely produce the expected | |
| interior peak; that's the next refinement. | |
| ## Misread injection: perception noise costs money | |
| Corrupt card reads (rank or suit swaps) at probability p, re-decide at r=0.5: | |
| | p | Action flip rate | Mean EV loss (chips) | | |
| |---|---|---| | |
| | 0.00 | 0.025 | 2.19 | | |
| | 0.05 | 0.042 | 3.86 | | |
| | 0.10 | 0.075 | 8.75 | | |
| | 0.20 | 0.083 | 13.12 | | |
| | 0.30 | 0.167 | **34.26** | | |
| A 30% misread rate costs ~15× more EV than the clean-read baseline — the | |
| quantitative bridge between the perception stack | |
| ([ThreeSixNine/poker-table-perception-eval](https://huggingface.co/datasets/ThreeSixNine/poker-table-perception-eval), | |
| detector in | |
| [ThreeSixNine/yolo11n-poker-table-cards](https://huggingface.co/ThreeSixNine/yolo11n-poker-table-cards)) | |
| and decision quality. | |
| ## Limitations (v0, by design) | |
| Uniform random opponent model (no reads/ranges); single-street decisions (no | |
| future-street planning, no ICM); heuristic EV used only for policy comparison; | |
| preflop is pure equity MC (no charts). See `LIMITATIONS` in decision_engine.py. | |
| ## Usage | |
| ```python | |
| from decision_engine import RiskEngine, TableState | |
| eng = RiskEngine(n_sims=1500) | |
| st = TableState(hero=["AS", "KD"], board=["AH", "7S", "2D"], pot=160, | |
| stack=1000, to_call=40, n_players=3, position="BTN", | |
| street="flop") | |
| print(eng.decide(st, r=0.7)) # {"action": "raise", "amount": ...} | |
| ``` | |
| Reproduce: `python eval_knobs.py --n-scenarios 120 --sims 1500` | |