oak-domain-betting
The betting domain for the OakQuant platform. Right now it is one thing only: a point-in-time odds capture that runs from day one.
pip install -e .
oak-odds snapshot # every open market on every venue, timestamped
oak-odds status # what the corpus holds
Signing in
The domain is capability-gated, fail-closed: a tenant whose enterprise does not
carry betting sees none of it, and never another domain's content instead.
# inside grove, after the package is installed
python -m oak_domain_betting.provisioning.seed_betting_owner --dry-run
python -m oak_domain_betting.provisioning.seed_betting_owner --password-stdin
Creates the oakquant-betting enterprise, grants it the betting capability,
and provisions owner.betting@oakquant.ai as its owner. Idempotent — re-running
never duplicates a row and never deletes one.
⚠️ Never pass a password as an argument. It lands in the process table, in
shell history, and in any transcript. --password-stdin reads from a pipe or a
TTY prompt and never renders it. Omit the flag and the owner stays on the invite
flow.
Why capture comes before the model
Everyone has results. Almost nobody has timestamped odds — and without them there is no point-in-time price, no closing line value, and no honest backtest. An hour of prices not captured cannot be reconstructed at any price. This is the same irreversibility that already cost this platform its macro board history, and it is the only part of the programme that has a deadline of now.
Everything else can be written later against the history this is accumulating today: the de-vig, the hierarchy, the features, the gates.
What it does not do
It does not convert a price into a probability. Removing the overround is Phase B0, and proportional, Shin and power methods disagree materially on longshots. Get it wrong and every number downstream is wrong — silently, and in the flattering direction. So nothing here pretends to have done it.
Quote.mid exists and is documented as not a probability. Polymarket's
outcomePrices already sum to 1 and are deliberately not promoted to the
quote, because a field that looks finished is more dangerous than one that
obviously is not.
The venues, and why these two
| venue | why |
|---|---|
| Kalshi | A regulated exchange, not a risk desk — you are matched against other participants, so winning does not get you closed. Carries real sports (EPL, La Liga, Europa League) as binary markets with a settlement field, so one capture eventually yields both the price and the label. |
| Polymarket | A second independent book on overlapping events. Not redundancy — a control. Two venues disagreeing is information; it is also the only way to notice a feed has gone stale, which from inside one feed looks like a market that stopped moving. |
Both are public and key-free. Nothing here has been paid for, and nothing will be until the retention and use-class terms have been read — a monthly price reads like a purchase and is not one, and a personal-use tier does not cover a billing product.
⭐ Three-way soccer arrives as three binary markets sharing one event ticker.
KXEPLGAME-26SEP20FULMUN has a -FUL, a -MUN and a -TIE, and their three YES
mids sum to more than 1. That excess is the exchange's overround, sitting in the
data, which makes Gate B0 testable the moment the instrument is written: a
harness that cannot reproduce the venue's own cut from quoted prices cannot be
trusted to find an edge.
What lands on disk
$OAK_ODDS_DIR/ # default ~/oakquant-odds
raw/<provider>/<date>/<ts>.json.gz # verbatim. THIS is the asset.
canonical/<date>.jsonl # flat rows. Derived, regenerable.
Raw is written before anything is parsed. If normalisation throws, the irreplaceable half is already safe. Normalisation can be rewritten a year from now and re-run over raw; a field dropped at capture time is simply gone.
⚠️ A skip is not a pass
Five silent losses shipped on this platform in one week, every one the same shape: a loop that skipped records and reported success. So the capture counts what was written, not what was attempted; every skipped market carries a reason; truncation from hitting a page limit is recorded differently from a feed that simply ended; and a run that captures nothing exits non-zero and says so — "NOTHING CAPTURED. This hour is lost and cannot be refetched."
Apache-2.0.
The weekend briefing (local only)
oak-betting-weekend turns a weekend of NFL games into a briefing and a paper
ledger. It is a recorded prediction, not a pick: there is no model (Gate B2 has
not started), so with the shipped policy every game is No bet, and the
briefing says so as a finished answer.
pip install -e '.[weekend]'
oak-betting-weekend brief # this weekend; fresh Kalshi snapshot first
oak-betting-weekend brief --estimate GB=0.45 # record your own probability for a team
oak-betting-weekend record-bet 401872990 --stake 10 --price 43
oak-betting-weekend settle # scores + closing-line value, after the games
- Market line: Kalshi moneyline from the odds corpus, mid-normalised. The bar a bet must clear is the ask plus Kalshi's fee, not the mid.
- Judgments: one
common.services.judgmentcall per game over that game's ESPN injury report and team news, filtered in code. Questions live inweekend/questions.py; every one passes timber's guards with zero findings. - Policy:
weekend/policy.yaml.weightsis empty on purpose. - Ledger:
~/oakquant-betting/ledger/paper-ledger.jsonl(OAK_BETTING_DIR), append-only; only theoutcomeblock is ever filled in later. - Key:
TYPESAFE_API_KEYis fetched from local ranger with grove's canopy client credentials. Nothing goes in your shell. - Schedule:
deploy/com.oakquant.betting-{brief,settle}.plist.
Metadata
Release files for oak-domain-betting 0.5.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| oak_domain_betting-0.5.1.tar.gz | 137.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| oak_domain_betting-0.5.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 257.5 kB
Release files / oak_domain_betting-0.5.1.tar.gz
| Download URL | oak_domain_betting-0.5.1.tar.gz |
|---|---|
| Size | 137.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f4c056c2be150904a1be6bd4c9aec8c7cf50d94acd6995186ca004ae9d0689a4
|
|
BLAKE2b-256 checksum How to use checksums |
27844fb90ed6e09279c304d09bedea78fbe12e2c4ebbd4532acf56887681c792
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency logRelease files / oak_domain_betting-0.5.1-py3-none-any.whl
| Download URL | oak_domain_betting-0.5.1-py3-none-any.whl |
|---|---|
| Size | 119.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ba7aef56b3ef103e96d32208908e7552d4aafc3aba03c0b305b84d7237de341b
|
|
BLAKE2b-256 checksum How to use checksums |
28aa87751e26c6c0ff4ad1f4a5734dcaf4c33fe0e6613c173dbb9561ccec8aac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.
Transparency log