This document explains how to consume the repository's public JSON payloads.
The current external JSON contract covers:
- input files accepted by
predictandcandidates - input files accepted by
backtest predictoutput (FairProbsOutput)candidatesoutput (OrdersOutput)backtestoutput (BacktestOutput)
The internal DecisionRecord shape exists in code for order-engine reasoning, but it is not emitted by the default CLI today and is not part of the external CLI contract yet.
pm_edge_engine is still in 0.x, so the project is early-stage. The intended compatibility policy is:
- Root output object names
resultsandordersare intended to remain stable. - Current field names inside
FairProbResultandOrderare intended to remain stable unless a release note says otherwise. - Additional fields may be added over time; downstream consumers should ignore unknown keys.
- Example numeric values are not a compatibility promise. They move with model state, data freshness, and configuration.
- Breaking JSON changes should be called out in
CHANGELOG.mdand in the relevant tagged release notes.
The CLI currently accepts either of these root shapes:
[ { "...": "market row" } ]or:
{ "markets": [ { "...": "market row" } ] }Input guidance:
market_slugshould be unique within a payload.outcomesandpricesshould stay aligned by index.start_time_utcshould be an RFC 3339 / ISO 8601 timestamp when present.- Unknown input keys are tolerated today, but downstream examples in this repository only document the core fields shown in the schemas.
backtest accepts a root object:
{
"tail_window": {
"min_minutes_to_start": 5,
"max_minutes_to_start": 15,
"require_start_time": true
},
"overrides": {
"engine": {
"min_time_to_event_minutes": 5
},
"model": {
"poisson_min_matches": 200
}
},
"matches": [ { "...": "match row" } ],
"odds": [ { "...": "odds row" } ],
"snapshots": [
{
"as_of_utc": "2026-02-18T12:00:00Z",
"markets": [ { "...": "market row" } ]
}
]
}Input guidance:
snapshotsis required and should be ordered or orderable byas_of_utc.matchesis optional; if omitted, the CLI falls back to the local sqlite match cache.oddsis optional; if provided, rows are matched by league/team names and event time, then filtered to records fetched at or before the replay snapshot.tail_windowis optional; it can restrict replay to markets within a chosen pre-kickoff minute range.overridesis optional; it applies replay-only config changes without mutating the runtimeconfig.toml.matches[*]uses the same field names asMatchRecordin code.odds[*]uses league/team names,datetime_utc, one-x-two prices, andfetched_at_utc.snapshots[*].markets[*]uses the same field names as the standardmarkets_fileinput.as_of_utcshould be an RFC 3339 / ISO 8601 timestamp.- If
matchesis provided inline, it should contain enough historical rows to support both model training and market mapping for the requested replay window.
backtest also accepts a manifest root:
{
"tail_window": {
"min_minutes_to_start": 5,
"max_minutes_to_start": 15,
"require_start_time": true
},
"overrides": {
"engine": {
"min_time_to_event_minutes": 5
}
},
"matches_files": ["backtest_batch/matches.json"],
"odds_files": ["backtest_tail_batch/odds.json"],
"snapshot_files": [
"backtest_batch/2026-02-18T12-00-00Z.json",
"backtest_batch/2026-02-18T22-00-00Z.json"
]
}Manifest guidance:
matches_filesandsnapshot_filesmay be combined with inlinematchesandsnapshots.odds_filesmay be combined with inlineodds.overridesmay be specified once at the manifest root and applies to every replay snapshot in that run.- Relative file paths resolve from the manifest file location.
- Match files may be either a raw array of
MatchRecordrows or{ "matches": [...] }. - Odds files may be either a raw array of odds rows or
{ "odds": [...] }. - Snapshot files may be either a single snapshot object or
{ "snapshots": [...] }. - The merged snapshot list is sorted by
as_of_utcbefore replay.
predict returns:
{"results":[{"market_slug":"...","fair_probs":[0.5,0.5]}]}Notes:
results[*].market_slugis the stable join key back to the originating market row.fair_probsaligns to the inputoutcomesorder.- Probability values are model outputs, not static fixtures.
candidates returns:
{"orders":[{"market_slug":"...","side":"BUY","outcome_index":0,"limit_price":0.42,"size_usd":5.0,"order_type":"maker"}]}Notes:
- An empty
ordersarray is a valid and expected result. outcome_indexpoints back to the input market'soutcomesarray.- Current examples only emit maker
BUYorders; consumers should still avoid hard-coding assumptions about future order-side expansion without checking release notes.
backtest returns:
{
"summary": {
"snapshots": 2,
"trades_entered": 1,
"settled_trades": 1,
"tail_window_applied": true,
"replay_overrides_applied": false,
"total_pnl_usd": 1.5
},
"snapshots": [
{
"as_of_utc": "2026-02-18T12:00:00Z",
"tail_filtered_markets": 0,
"buy_count": 1,
"wait_count": 0,
"new_orders": 1
}
],
"by_entry_date": [
{
"entry_date_utc": "2026-02-18",
"trades_entered": 1,
"hit_rate_pct": 100.0,
"total_pnl_usd": 1.5
}
],
"by_league": [
{
"league": "PL",
"trades_entered": 1,
"hit_rate_pct": 100.0,
"total_pnl_usd": 1.5
}
],
"by_minutes_to_start": [
{
"bucket": "10-14",
"trades_entered": 1,
"hit_rate_pct": 100.0,
"total_pnl_usd": 1.5
}
],
"trades": [
{
"market_slug": "...",
"minutes_to_start_at_entry": 10,
"odds_fusion_used": true,
"settlement_status": "WIN",
"pnl_usd": 1.5
}
]
}Notes:
summaryis the top-level aggregate for bankroll and realized replay outcomes.summary.replay_overrides_appliedtells downstream tooling whether replay-only config loosening/tightening was active.snapshots[*]gives point-in-time execution counts after replaying eachas_of_utc.by_entry_date[*]attributes trades to the UTC calendar date on which they were entered.by_league[*]groups trades by the mapped match league, orUNKNOWNwhen no league is available.by_minutes_to_start[*]groups trades by their pre-kickoff entry bucket using the marketstart_time_utc.trades[*]is the realized/open trade ledger keyed bymarket_slug.- Unknown additive fields may appear over time; consumers should ignore what they do not need.
The repository includes lightweight JSON Schema references for tooling and tests:
schemas/markets_input.schema.jsonschemas/fair_probs_output.schema.jsonschemas/orders_output.schema.json
These schemas intentionally describe the required core fields while allowing future additive fields.
Captured outputs under examples/ and docs/DEMO.md are useful for evaluation, but they are not golden snapshots for every clone. If you need strict fixture behavior, prefer purpose-built test fixtures and pin the model/database state in CI.