mostlyright.markets.polymarket
Polymarket discovery + settlement (US + international).
Public surface:
discover()— Gamma API discovery, no auth.settle(event_id)()— settlement engine using internalmostlyright.international.daily_extremes()as the resolution source.
Input validation, all enforced before any HTTP fetch or daily-extremes call:
event_idmust match the id pattern ([A-Za-z0-9_-]{1,128}).descriptioncapped at 16 KB (Polymarket descriptions are concise; oversized payloads indicate hostile input).- Resolution-source URLs in the description must resolve to a netloc in
RESOLUTION_SOURCE_ALLOWLIST(Wunderground or weather.gov).
Taipei and Hong Kong-lowest markets raise
mostlyright.international.DeferredMarketError: this SDK has no CWA
or HKO client to read their settlement values from.
Module Attributes
Section titled “Module Attributes”| Attribute | Description |
|---|---|
RESOLUTION_SOURCE_ALLOWLIST | Netloc allowlist for Polymarket resolution-source URLs. |
POLYMARKET_RESOLUTION_SOURCE_TYPES | Enum values for the resolution_source_type column on settlement records. |
label | The polymarket.label namespace singleton (polymarket.label.settlement(...)). |
Functions
Section titled “Functions”| Function | Description |
|---|---|
candles(url_or_slug, *, side, interval, …) | Read one Polymarket outcome’s bucketed price history over a window. |
discover(*[, client, sleep_between, …]) | Discover active Polymarket WEATHER-EVENT markets for the settlement pipeline. |
events(*[, status, event, all]) | Browse Polymarket events — the top tier of this venue’s hierarchy. |
market(url_or_slug) | Look a Polymarket market up by slug or by a pasted polymarket.com link. |
markets(*[, event, status, all]) | List Polymarket markets, narrowed by event or status. |
orderbook(url_or_slug, *, side) | Read one Polymarket outcome’s resting book as it stands right now. |
series(*args, **kwargs) | Always raises: Polymarket has no series tier. |
settle(event_id, *[, description, event, …]) | Resolve a Polymarket weather event to its settlement payload. |
settlement_days(entity, from_date, to_date, *) | The bare Polymarket settlement-day grid (train == live — the skew guard). |
trades(url_or_slug, *, from_time, to_time[, …]) | Read a Polymarket market’s executed prints over a window. |
training_table(entity, from_date, to_date, *) | Polymarket leakage-free supervised table over the label="daily_extremes" target. |
Exceptions
Section titled “Exceptions”| Exception | Description |
|---|---|
PolymarketEventError([message, error_code, …]) | Polymarket event payload is malformed (bad UUID, bad URL, oversized). |
PolymarketSettlementError([message, …]) | Settlement engine couldn’t resolve an event to a bucket. |
PolymarketStrikeError([message, error_code, …]) | A Polymarket event’s contract strike could not be parsed from slug/title. |
TooEarlyToSettleError([message, request_id, …]) | Settlement attempted before the resolution-source’s finalization delay. |
mostlyright.markets.polymarket.POLYMARKET_RESOLUTION_SOURCE_TYPES : tuple[str, …]
Section titled “mostlyright.markets.polymarket.POLYMARKET_RESOLUTION_SOURCE_TYPES : tuple[str, …]”Enum values for the resolution_source_type column on settlement
records. hko and cwa name the Hong Kong Observatory and Taiwan CWA
sources, for which this SDK has no client yet.
exception mostlyright.markets.polymarket.PolymarketEventError(message=”, , error_code=None, source=None, request_id=None)
Section titled “exception mostlyright.markets.polymarket.PolymarketEventError(message=”, , error_code=None, source=None, request_id=None)”Bases: MostlyrightError
Polymarket event payload is malformed (bad UUID, bad URL, oversized).
- Parameters:
- Return type: None
default_error_code: str
Section titled “default_error_code: str”Subclass override — the stable string enum surfaced via error_code.
exception mostlyright.markets.polymarket.PolymarketSettlementError(message=”, , error_code=None, source=None, request_id=None)
Section titled “exception mostlyright.markets.polymarket.PolymarketSettlementError(message=”, , error_code=None, source=None, request_id=None)”Bases: MostlyrightError
Settlement engine couldn’t resolve an event to a bucket.
Reasons: no buckets parseable from description, daily_extremes returned no rows for the resolution station/date, or the parsed value didn’t match any bucket.
- Parameters:
- Return type: None
default_error_code: str
Section titled “default_error_code: str”Subclass override — the stable string enum surfaced via error_code.
exception mostlyright.markets.polymarket.PolymarketStrikeError(message=”, , error_code=None, source=None, request_id=None)
Section titled “exception mostlyright.markets.polymarket.PolymarketStrikeError(message=”, , error_code=None, source=None, request_id=None)”Bases: MostlyrightError
A Polymarket event’s contract strike could not be parsed from slug/title.
outcome=True needs the strike to binarize the observed value; a market
with no parseable above/below/between <n><C|F> clause cannot be settled
to 0/1 and this error is raised loudly (never a silent 0/1).
- Parameters:
- Return type: None
default_error_code: str
Section titled “default_error_code: str”Subclass override — the stable string enum surfaced via error_code.
mostlyright.markets.polymarket.RESOLUTION_SOURCE_ALLOWLIST : frozenset[str]
Section titled “mostlyright.markets.polymarket.RESOLUTION_SOURCE_ALLOWLIST : frozenset[str]”Netloc allowlist for Polymarket resolution-source URLs. Anything else
raises PolymarketEventError to prevent silent settlement
against an unknown / hostile source.
exception mostlyright.markets.polymarket.TooEarlyToSettleError(message=”, , wait_hours, resolution_source_type, request_id=None, error_code=None)
Section titled “exception mostlyright.markets.polymarket.TooEarlyToSettleError(message=”, , wait_hours, resolution_source_type, request_id=None, error_code=None)”Bases: MostlyrightError
Settlement attempted before the resolution-source’s finalization delay.
Carries the wait time so the caller can schedule a retry.
- Parameters:
- Return type: None
default_error_code: str
Section titled “default_error_code: str”Subclass override — the stable string enum surfaced via error_code.
mostlyright.markets.polymarket.candles(url_or_slug, , side, interval, from_time, to_time)
Section titled “mostlyright.markets.polymarket.candles(url_or_slug, , side, interval, from_time, to_time)”Read one Polymarket outcome’s bucketed price history over a window.
Paste the link from the post you are reading, or type the slug, and name
the side you mean. On this venue a price series belongs to an outcome
token rather than to a market, so the slug alone is not enough — the pair
is resolved to a token id internally (_resolve_side_token()), and the
pasted link is parsed offline and never fetched.
There is no volume here, and none is invented. The venue’s price
endpoint serves a timestamp and a price and nothing else, so
volume_contracts and open_interest are NULL on every row and there
is deliberately no column named volume. Absent is not zero: a 0.0
would assert that nothing traded in that bucket, which the venue never
said. The eight bid/ask columns are NULL for the same reason — this
endpoint quotes no book.
The candle is flat by construction. The venue serves a LAST PRICE per
bucket, not an open/high/low/close, so open, high, low and
close all carry that one number. A flat candle here is the data, not a
bug.
“*_native“ equals its probability column. Polymarket’s native unit already IS a probability in [0, 1], so there is nothing to convert. The column exists so a frame from this venue and a frame from Kalshi — whose native unit is cents — concatenate without either side losing its own magnitude.
Timestamps are bucket STARTS, as served. This venue stamps a bucket
with its start where Kalshi stamps the period end, so nothing is subtracted
here; the Kalshi verb subtracts its interval instead and the two frames
agree. That the served t is a start rather than an end is a documented
assumption; this SDK has not verified it against a settled market.
You reach Polymarket under your own relationship with Polymarket. Nothing here is persisted.
- Parameters:
- url_or_slug (
str) – A Polymarket market slug ("new-rhianna-album-before-gta-vi-926") or a polymarket.com market link. The link is parsed offline and never dereferenced. - side (
str) – The outcome you want the price series for, as the venue names it ("yes"/"no", or an option label). Case-insensitive. - interval (
str) – Bucket width —"1m","1h"or"1d". It reaches the venue as itsfidelityparameter, in minutes. - from_time (
datetime) – tz-aware UTC bounds;from_timemust be strictly earlier thanto_time. - to_time (
datetime) – tz-aware UTC bounds;from_timemust be strictly earlier thanto_time.
- url_or_slug (
- Return type:
DataFrame - Returns:
A
schema.markets.candles.v2frame, one row per bucket, ascending bybucket_start_utc. The column set is the same one the Kalshi verb returns, so the two concatenate. A window the venue has no ticks for returns an empty frame carrying the full column set, neverNoneand never[]. - Raises:
- ContractError –
url_or_slugdoes not identify a single market (an EVENT-level link is refused before any request – an event groups many markets and a price series belongs to one), orsideis not one of the market’s outcomes. - SchemaValidationError – the market’s outcome and token arrays disagree in length, so no side can be resolved safely.
- TypeError – either bound is a naive datetime.
- ValueError –
from_timeis not earlier thanto_time. - UnsupportedResolutionError –
intervalis outside the supported set. Raised before any request.
- ContractError –
Example
Section titled “Example”>>> from datetime import UTC, datetime>>> window = candles(... "new-rhianna-album-before-gta-vi-926",... side="yes",... interval="1h",... from_time=datetime(2026, 6, 1, tzinfo=UTC),... to_time=datetime(2026, 6, 2, tzinfo=UTC),... )>>> window["close"].between(0, 1).all()Truemostlyright.markets.polymarket.discover(, client=None, sleep_between=None, backend=‘pandas’, return_type=‘dataframe’)
Section titled “mostlyright.markets.polymarket.discover(, client=None, sleep_between=None, backend=‘pandas’, return_type=‘dataframe’)”Discover active Polymarket WEATHER-EVENT markets for the settlement pipeline.
Not the same verb as mostlyright.discover(), which searches the
cross-domain catalog and answers with catalog entries. This one is
venue-local and weather-only: it walks the Gamma event feed, keeps the
events whose city resolves to a settlement station, and returns the
settlement metadata the Polymarket settle path needs. To browse the venue
hierarchy generally — every category, not just weather — use
events() and markets().
- Parameters:
- Return type:
DataFrame - Returns:
pd.DataFramewith one row per active weather event. Requires the[polymarket]extra (raisesSourceUnavailableErrorotherwise). Columns:event_id(str): Polymarket event id.slug(str): Polymarket slug.title(str): event title.city(str | None): lowercased city key frompolymarket_city_stations.jsonif a match was found, else None.icao(str | None): resolved ICAO for the city (high vs low aware), or None if no city / unknown city.temperature_extreme(str | None):"high"/"low"/"ambiguous"per the per-event resolver, or None if unresolved.end_time(str | None):event.endDateISO timestamp.resolution_source_type(str | None): wunderground / noaa_wrh / other from the description URL.
- Raises:
- httpx.HTTPStatusError – Gamma API returned non-2xx.
- SourceUnavailableError –
[polymarket]extra not installed.
mostlyright.markets.polymarket.events(, status=None, event=None, all=False)
Section titled “mostlyright.markets.polymarket.events(, status=None, event=None, all=False)”Browse Polymarket events — the top tier of this venue’s hierarchy.
An event groups the markets one question resolves across, and on this
venue it is where a browse starts: there is no series above it. The
series_ticker column is NULL on every row for exactly that reason —
see series(), which says so out loud.
status is not a field Polymarket serves. It is derived from the
venue’s own closed / active / acceptingOrders booleans into
the same four words the other venue uses, so one filter reads across both
(_GAMMA_STATUS_MAP is the whole mapping).
- Parameters:
- status (
str|None) – One ofopen/closed/settled/unopened. Rows are matched on the DERIVED status, so the answer never contains a row that reads differently from what was asked for. - event (
str|None) – An event slug, or a pasted polymarket.com event link, to fetch exactly. The link is parsed offline and never dereferenced. - all (
bool) – Accept every event the venue lists. Required when no other filter is given — see the error raised in that case.
- status (
- Return type:
DataFrame - Returns:
A
schema.markets.events.v1frame, one row per event, withopen_time/close_timeas tz-aware UTC instants. A query that matches nothing returns an empty frame with the full column set, neverNone. - Raises:
- ContractError – No filter and no
all=True, an invalidstatus, or aneventthat is not a recognisable slug or link. - RuntimeError – The keyset walk hit the client’s page ceiling. It is deliberately not caught: a capped walk and a complete one must not look alike.
- ContractError – No filter and no
mostlyright.markets.polymarket.label
Section titled “mostlyright.markets.polymarket.label”The polymarket.label namespace singleton (polymarket.label.settlement(...)).
mostlyright.markets.polymarket.market(url_or_slug)
Section titled “mostlyright.markets.polymarket.market(url_or_slug)”Look a Polymarket market up by slug or by a pasted polymarket.com link.
Paste the link from the post you are reading, or type the slug — both identify the same contract and return the same row.
The pasted link is NEVER fetched. It is parsed offline for host and path shape, the slug is pulled out of it, and the venue request is built from the resolved API address, so a lookalike host cannot steer a request anywhere.
An event-level link returns MORE THAN ONE ROW. Polymarket links come
in two shapes, /event/{event}/{market} and the bare
/event/{event}, and the second one is what people usually have to
hand: it is the link the site shows and the link that gets shared.
Refusing it would send the caller back to the site to find a narrower one,
which defeats the point of accepting a link at all. So an event link
resolves the event and returns every market under it, and this verb’s
singular name is a promise about what you ASK for, not about how many rows
come back. Read len(frame) if that matters to you, or pass the
market-level link to guarantee one row.
The returned row carries outcomes and outcome_token_ids as two
positionally aligned comma-joined lists, which is the hand-off to the
verbs that want a side: pick the outcome name you mean from the first,
and its token id is at the matching position in the second.
An unknown slug raises the venue’s 404 rather than returning an empty frame. “No such market” and “no data” are different answers and this verb will not conflate them.
- Parameters:
url_or_slug (
str) – A Polymarket market slug ("new-rhianna-album-before-gta-vi-926"), a market link (/event/{event}/{market}or/market/{market}), or an event link (/event/{event}). - Returns: one row for a market reference, one row per market on the event for an event link.
- Return type:
A
schema.markets.listing.v1frame - Raises:
- ContractError –
url_or_slugis not a recognised slug or a canonical polymarket.com link. Raised before any request exists. - httpx.HTTPStatusError – The venue does not serve that slug.
- ContractError –
mostlyright.markets.polymarket.markets(, event=None, status=None, all=False)
Section titled “mostlyright.markets.polymarket.markets(, event=None, status=None, all=False)”List Polymarket markets, narrowed by event or status.
This is the fetch half of find-then-fetch: it returns exactly what the
caller names, where mostlyright.discover() searches the catalog
fuzzily across domains. (The other discover on this module,
discover(), is the venue-local weather-event verb — a third thing
again.)
Each row carries outcomes and outcome_token_ids as two
comma-joined, POSITIONALLY ALIGNED lists, which is what a caller needs to
pick a side before asking for a book or a price history. Token ids stay
STRINGS: a CLOB token id is roughly 77 digits, and reading one as a number
drops its low-order digits without raising anything.
When those two arrays disagree in length the record cannot be aligned at
all, and this verb emits outcomes with outcome_token_ids NULL. A
listing is a browse: one malformed market should not poison a whole page,
and a null says truthfully that the pairing is unknown. The verbs that
RESOLVE a side raise on the same input instead, because there an
unnoticed misalignment would put a price on the wrong outcome.
Prices are probabilities in [0, 1] so a frame from this venue and a frame
from the other can be concatenated and compared with no unit conversion at
the call site. volume_usd here is venue-served — it is Gamma’s own
volumeNum, not a figure computed here — unlike the trade-tape column
of the same name, which is derived as size times price. The Kalshi-only
columns
(series_ticker, volume_contracts, open_interest) are NULL:
this venue serves no such value, and absent is not zero.
Polymarket’s API answers browser requests directly, which the other
venue’s does not — relevant if you are building a dashboard rather than a
notebook. See docs/market-data-browser-support.md.
You reach Polymarket under your own relationship with Polymarket. Nothing here is persisted.
- Parameters:
- event (
str|None) – An event slug, or a pasted polymarket.com event link, whose markets to return. The link is parsed offline and never dereferenced. - status (
str|None) – One ofopen/closed/settled/unopened, derived from the venue’s booleans (seeevents()). - all (
bool) – Accept the full unnarrowed universe. Required when no other filter is given — see the error raised in that case.
- event (
- Return type:
DataFrame - Returns:
A
schema.markets.listing.v1frame, one row per market. A query that matches nothing returns an empty frame with the full column set. - Raises:
- ContractError – No filter and no
all=True, an invalidstatus, or aneventthat is not a recognisable slug or link. - RuntimeError – The keyset walk hit the client’s page ceiling, which is deliberately not caught.
- ContractError – No filter and no
Example
Section titled “Example”>>> book = markets(event="what-will-happen-before-gta-vi")>>> book["last_price"].between(0, 1).all()Truemostlyright.markets.polymarket.orderbook(url_or_slug, , side)
Section titled “mostlyright.markets.polymarket.orderbook(url_or_slug, , side)”Read one Polymarket outcome’s resting book as it stands right now.
The frame is LONG: one row per price level, with side and level
naming where that row sits. That shape is what lets this book and a book
from another venue concatenate into one frame and stay unit-honest — a
nested bid/ask column pair would have to invent a fill rule for the side
with fewer levels, and would silently pair a bid with an unrelated ask.
level is 0 at the touch (the highest bid, the lowest ask) and counts
outward, assigned here rather than trusted from the wire so the ordering is
identical however the venue happened to sort its arrays.
A book belongs to an outcome token, which is why side is required
and not optional: asking for “the book” of a market would mean two
different books. Note that the side ARGUMENT selects the outcome, while
the side COLUMN says bid or ask within that one outcome’s book — the
two are different axes that happen to share the venue’s word.
A book is a point-in-time read. There is no historical book tier — a
past book cannot be reconstructed from a past price — so captured_at is
one instant, identical across the whole frame. It is the venue’s own
snapshot stamp when it serves one, and the client clock when it does not.
Prices are probabilities in [0, 1] and price_native equals price:
this venue’s native unit already IS probability.
You reach Polymarket under your own relationship with Polymarket. Nothing here is persisted.
- Parameters:
- Return type:
DataFrame - Returns:
A
schema.markets.orderbook.v2frame, one row per level. An outcome with no resting orders returns an empty frame carrying the full column set, neverNoneand never[]. - Raises:
- ContractError –
url_or_slugdoes not identify a single market (an EVENT-level link is refused before any request – an event groups many markets and a price series belongs to one), orsideis not one of the market’s outcomes. - SchemaValidationError – the market’s outcome and token arrays disagree in length, so no side can be resolved safely.
- ContractError –
mostlyright.markets.polymarket.series(*args, **kwargs)
Section titled “mostlyright.markets.polymarket.series(*args, **kwargs)”Always raises: Polymarket has no series tier.
Kalshi groups its recurring contracts into a series above the event, so
markets.kalshi.series() is where a browse of that venue starts.
Polymarket has no such tier at all — its hierarchy is Event -> Market, and
an event is already the top. Start with events() instead.
This verb exists rather than being omitted so the difference is discoverable. A missing attribute teaches nothing; a shared grammar with a silent hole in it teaches something false.
Every argument is accepted and ignored, so a caller copying a Kalshi call across gets the lesson rather than a complaint about a keyword.
- Raises:
VenueCapabilityError – Always. Carries
venue,capability, andremedy, and subclassesContractError, so it is raised before any I/O and existing contract handlers still catch it. - Return type:
NoReturn - Parameters:
mostlyright.markets.polymarket.settle(event_id, , description=None, event=None, client=None, now=None)
Section titled “mostlyright.markets.polymarket.settle(event_id, , description=None, event=None, client=None, now=None)”Resolve a Polymarket weather event to its settlement payload.
- Parameters:
- event_id (
str) – Polymarket event identifier (validated at the boundary). - description (
str|None) – Optional event description. If passed, used in place of the upstream payload (lets tests skip the HTTP call). Still subject to the 16 KB cap + URL allowlist. - event (
dict[str,Any] |None) – Optional preloaded event payload (skips the HTTP call entirely). When omitted, fetched from Gamma byevent_id. - client (
Client|None) – Optionalhttpx.Clientfor connection reuse. - now (
datetime|None) – Override wall-clock for tests. Defaults todatetime.now(UTC).
- event_id (
- Returns:
event_id(str),slug(str),title(str)settlement_date(str,YYYY-MM-DDstation-local).icao(str),temperature_extreme(str): resolution station + high/low.resolution_source_type(str)observed_value_c(float): the relevant daily low or high fromdaily_extremes().observation_count(int): hourly observation count backing the value.observed_source(str): provenance of the observed extreme, from the daily_extremes row.country: pass-through from the daily_extremes row.
- Return type: Settlement payload dict with
- Raises:
- PolymarketEventError – invalid event_id format, oversized description, or resolution URL outside the allowlist.
- ContractError – a Tier-1.5 URL station is denylisted / city-inconsistent / non-registry — refused rather than settling against the wrong station or leaking a bare KeyError.
- DeferredMarketError – resolves to Taipei / HK-low, whose CWA / HKO settlement source has no client in this SDK.
- PolymarketSettlementError – settlement date unparseable, or daily_extremes returned no usable row.
- TooEarlyToSettleError – not enough time has passed since the resolution date for the source to have published.
- httpx.HTTPStatusError – Gamma API returned non-2xx when no
eventwas provided.
mostlyright.markets.polymarket.settlement_days(entity, from_date, to_date, , station_override=None)
Section titled “mostlyright.markets.polymarket.settlement_days(entity, from_date, to_date, , station_override=None)”The bare Polymarket settlement-day grid (train == live — the skew guard).
Two positional dates (inclusive ends). entity is the Polymarket event id (a
UUID/slug — not a station). station_override= pins the settlement station
directly, bypassing event resolution and the network; otherwise the event’s
station is resolved via the shipped resolver. The grid is one row per LST
settlement day with no y columns.
Every returned row keeps its originating entity (the event id) as the
leading column (before station and the date day field), so
concatenating several events never collapses provenance — each day stays
attributable to the event that minted it.
The caller names the contract; PIT-correct rolling-feature transforms are out of scope (computed inside sources or by users downstream at their own risk).
- Return type:
DataFrame - Parameters:
mostlyright.markets.polymarket.trades(url_or_slug, , from_time, to_time, side=None)
Section titled “mostlyright.markets.polymarket.trades(url_or_slug, , from_time, to_time, side=None)”Read a Polymarket market’s executed prints over a window.
Where candles() bucketizes, this returns the tape itself: one row per
fill, oldest first. The window is half-open — a print exactly at
from_time is in, a print exactly at to_time is not — and the bounds
are the same tz-aware from_time / to_time grammar every
window-scoped verb in the SDK uses.
“side“ is optional here, unlike on the other two verbs. The tape
serves every outcome of a market in one stream, so a caller who names no
side gets the whole tape with each row’s own outcome in the side
column. Naming one filters to it — and an outcome this market does not
offer RAISES rather than quietly returning an empty tape, because “no
trades” and “no such outcome” are different answers.
The tape endpoint is addressed by “conditionId“, not by a CLOB token id. That is the reverse of the price-history and book endpoints on the same venue, and passing the wrong identifier class returns an empty array rather than an error — so the two are resolved separately and each verb sends the one its endpoint documents.
“volume_usd“ here is DERIVED, not venue-served. The venue’s size
is a count of shares/contracts and it publishes no USD notional per fill,
so this column is size_contracts * price, computed here.
size_contracts and price both travel on the row so the arithmetic
is auditable rather than hidden, and the column is NULL whenever either
input is missing — a partially-known notional is not a notional. Note that
the identically named column on the LISTING frame is the opposite: there it
is Gamma’s own lifetime figure, served by the venue.
“side“ carries the OUTCOME, not the taker direction. The venue also
publishes a BUY / SELL field; that is a different axis, and the
shared cross-venue trade vocabulary does not carry it.
You reach Polymarket under your own relationship with Polymarket. Nothing here is persisted.
- Parameters:
- url_or_slug (
str) – A Polymarket market slug or a polymarket.com market link. The link is parsed offline and never dereferenced. - from_time (
datetime) – tz-aware UTC bounds;from_timemust be strictly earlier thanto_time. The filter is applied here rather than by the venue, which accepts no window on this endpoint. - to_time (
datetime) – tz-aware UTC bounds;from_timemust be strictly earlier thanto_time. The filter is applied here rather than by the venue, which accepts no window on this endpoint. - side (
str|None) – An outcome to filter to, as the venue names it. Case-insensitive. Omitted, every outcome’s prints come back.
- url_or_slug (
- Return type:
DataFrame - Returns:
A
schema.markets.trades.v2frame, one row per fill, ascending bytraded_at. A quiet window returns an empty frame carrying the full column set, neverNoneand never[]. - Raises:
- ContractError –
url_or_slugdoes not identify a single market (an EVENT-level link is refused before any request), orsideis not one of the market’s outcomes. - SchemaValidationError – the market’s outcome and token arrays disagree in length, so the named side cannot be checked safely.
- TypeError – either bound is a naive datetime.
- ValueError –
from_timeis not earlier thanto_time. - RuntimeError – The tape ran past the client’s page cap. Narrow the window rather than raising the cap — this verb does not swallow it, because a truncated tape that reads as a complete one is worse than an error.
- ContractError –
mostlyright.markets.polymarket.training_table(entity, from_date, to_date, , outcome=False, event=None, features=None)
Section titled “mostlyright.markets.polymarket.training_table(entity, from_date, to_date, , outcome=False, event=None, features=None)”Polymarket leakage-free supervised table over the label="daily_extremes" target.
A thin delegator with no duplicated join logic. entity is the Polymarket
event id. It resolves the event’s settlement station from the Gamma payload,
then forwards the whole feature-composition + join to core
research.dataset with label="daily_extremes" (Polymarket weather
markets resolve on the WU/NOAA-WRH daily extremes, not the NWS CLI product).
Two positional dates.
This is the markets analogue of weather.training_table(); the old
polymarket.dataset() name is a deprecation shim routing here — dataset is
reserved for the catalog noun.
Offline on every path. Station resolution needs the Gamma event payload,
but training_table makes no live Gamma round-trip in either outcome mode
— the caller supplies the payload via event=, symmetric with Kalshi’s
market=. When event= is absent it raises a typed
ContractError naming that argument. Fetch the payload yourself with
the opt-in markets.polymarket.fetch_event_by_id() and pass it as
event=. With outcome=True the per-settlement-date loop reuses that
single cached payload for every settle() call — still no network.
- Parameters:
- entity (
str) – The Polymarket event id (validated at the boundary). - from_date (
str) –YYYY-MM-DDwindow bounds (forwarded verbatim). - to_date (
str) –YYYY-MM-DDwindow bounds (forwarded verbatim). - outcome (
bool) – WhenTrue, append a binarylabel_outcome(Int64, 0/1/NA) column — see the comparison rule in_settle_polymarket_strike(). Requires the daily_extremes label frame (the core DataFrame path) and the event’s strike (parsed from the slug/title). - event (
dict[str,Any] |None) – The preloaded Gamma event payload, required (station resolution and the outcome loop both read it). There is no auto-fetch; when omitted,training_tableraises a typedContractErrornaming this argument. There are noclient/nowinjection parameters; tests mock the module-levelsettle/fetch_event_by_idinstead. - features (
list[str] |tuple[str,...] |None) – Extra core feature names.
- entity (
- Return type:
DataFrame - Returns:
The core
dataset(label="daily_extremes", ...)frame plus, whenoutcome=True, thelabel_outcomecolumn. - Raises:
- ContractError –
event=is absent (the payload is required; there is no hidden Gamma fetch). - PolymarketEventError / DeferredMarketError / PolymarketSettlementError / –
- PolymarketStrikeError – per the settlement + strike-parse contract.
- ContractError –