Execution¶
From an edge to a recorded trade, to a settled one: signals, the paper broker, the live broker, settlement and re-settlement.
EdgeSignal
dataclass
¶
EdgeSignal(
market_id: str,
city_or_segment: str,
target_date: str,
horizon: str,
outcome_label: str,
direction: str,
gamma_price: float,
model_prob: float,
best_edge: float,
yes_edge: float,
no_edge: float,
question: str = "",
)
A trading signal with computed edge metrics ready for paper-broker ingestion.
from_quote
classmethod
¶
from_quote(
*,
market_id: str,
city_or_segment: str,
target_date: str,
horizon: str,
outcome_label: str,
yes_price: float,
model_prob: float,
costs: CostModel,
stake: float,
directions: tuple[str, ...] = ("yes", "no"),
question: str = "",
) -> EdgeSignal | None
The signal for one outcome label, edges computed as the backtest computes them.
pmlab.core.edge.quote_edges is the one definition of the after-fee edge of each
side; the backtest's live policy calls it too, so a plugin's scan-edge step that
builds its signals here trades the strategy the champion was promoted on.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
yes_price
|
float
|
The label's YES price (recorded as |
required |
model_prob
|
float
|
The probability the label occurs (recorded as |
required |
costs
|
CostModel
|
The champion's cost model. |
required |
stake
|
float
|
The flat stake the broker will trade. |
required |
directions
|
tuple[str, ...]
|
The sides the strategy may take. |
('yes', 'no')
|
Returns:
| Type | Description |
|---|---|
EdgeSignal | None
|
The signal, or None if no allowed side can be bought (a price of 0, or a |
EdgeSignal | None
|
fill pushed to certainty). |
EdgeSignal | None
|
whether it is worth a trade is the caller's |
PaperBroker
¶
PaperBroker(
trades_path: Path,
allowed_segments: set[str] | None = None,
flat_stake: float = 1.0,
taker_bps: float | None = None,
costs: CostModel | None = None,
)
Records paper trades from EdgeSignals with dedup, staleness, and segment filtering.
Record paper trades from EdgeSignals.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trades_path
|
Path
|
JSON file the trade log is appended to. |
required |
allowed_segments
|
set[str] | None
|
Only record signals in these segments (from the
champion's passing gate segments). None means no filtering, and so
does |
None
|
flat_stake
|
float
|
Notional USDC per trade. |
1.0
|
taker_bps
|
float | None
|
Legacy fee-only knob. Mutually exclusive with |
None
|
costs
|
CostModel | None
|
Full |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If both |
costs
instance-attribute
¶
costs = (
costs
if costs is not None
else CostModel(
taker_bps=30.0 if taker_bps is None else taker_bps
)
)
record
¶
record(
signals: list[EdgeSignal],
now_utc: datetime | None = None,
city_timezones: dict[str, str] | None = None,
) -> list[dict[str, Any]]
Process signals and append non-stale, non-duplicate trades.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
signals
|
list[EdgeSignal]
|
List of EdgeSignal objects to process. |
required |
now_utc
|
datetime | None
|
Current time in UTC (injected for testing; defaults to now). |
None
|
city_timezones
|
dict[str, str] | None
|
Mapping of city_or_segment -> tz string (defaults to UTC). |
None
|
Returns:
| Type | Description |
|---|---|
list[dict[str, Any]]
|
List of newly added trade dicts. |
load_trades
¶
load_trades() -> list[dict[str, Any]]
Load existing trades from trades_path, or return empty list.
SettlementEngine
¶
SettlementEngine(plugin: MarketPlugin, trades_path: Path)
Settles open paper trades using plugin truth resolution.
settle_all
¶
settle_all(
specs: list[MarketSpec],
today_str: str | None = None,
now_utc: datetime | None = None,
) -> dict[str, Any]
Settle all unsettled trades that have a final truth available.
Each trade it settles is stamped with settled_at (UTC): when its PnL
became known, which is what lets the watchdog replay an earlier --as-of
without seeing truth that had not arrived yet.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
specs
|
list[MarketSpec]
|
The markets to resolve against. |
required |
today_str
|
str | None
|
|
None
|
now_utc
|
datetime | None
|
The settlement time to stamp (injected for testing; defaults to now). Must be timezone-aware. |
None
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
resettle_trades
¶
resettle_trades(
trades: Sequence[Mapping[str, Any]],
*,
now_utc: datetime,
) -> ResettleResult
Recompute the PnL of settled trades booked before the current settlement version.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trades
|
Sequence[Mapping[str, Any]]
|
The log's trades. Not modified. |
required |
now_utc
|
datetime
|
When the re-settlement happens, stamped as |
required |
Returns:
| Type | Description |
|---|---|
ResettleResult
|
The log with those trades recomputed and stamped with |
ResettleResult
|
counts and per-trade changes that say what happened. |
ResettleResult
dataclass
¶
ResettleResult(
trades: list[dict[str, Any]],
changes: list[Change] = list(),
n_resettled: int = 0,
n_changed: int = 0,
n_open: int = 0,
n_current: int = 0,
n_unrecomputable: int = 0,
unrecomputable: list[str] = list(),
total_before: float = 0.0,
total_after: float = 0.0,
)
The re-settled log, and an account of what was and was not done to it.
unrecomputable
class-attribute
instance-attribute
¶
unrecomputable: list[str] = field(default_factory=list)
LiveBroker
¶
LiveBroker(
api_key: str,
api_secret: str,
api_passphrase: str,
private_key: str = "",
chain_id: int = 137,
signature_type: int = 0,
funder_address: str | None = None,
base_url: str = CLOB_API_BASE,
dry_run: bool = False,
)
Real-money order execution via the Polymarket CLOB API.
Requires
- private_key: L1 ECDSA private key (0x-prefixed hex string)
- api_key / api_secret / api_passphrase: L2 API credentials
In dry_run mode, no requests are made to the API.
LiveBrokerError
¶
Bases: Exception
A live order could not be placed or confirmed (bad credentials, rejected order, API error).
OrderReceipt
dataclass
¶
OrderReceipt(
order_id: str,
token_id: str,
side: str,
price: float,
size: float,
status: str,
placed_at: str = (
lambda: datetime.now(UTC).isoformat()
)(),
)
placed_at
class-attribute
instance-attribute
¶
placed_at: str = field(
default_factory=lambda: datetime.now(UTC).isoformat()
)