Skip to content

betting_combat.rounds.backtest.fills

Fills from the trade tape: only what is knowable when the order goes out, plus the market’s move while the order travels (research ufc/modeling/execution.py::tape_fills — the version fixed 2026-09-29 — and ufc/modeling/capacity.py::_arrival / _poly).

arrival price the worse of the decision price and every print on our side between the
decision (t, exclusive) and the order's arrival (t + latency, inclusive)
filled if the arrival price is within the limit (decision price + cushion); paid at
the arrival price; else missed
size cap a share of the dollars traded in that market in the window BEFORE the
decision ([t - window, t)); nothing after the decision decides whether or
how much we fill

Tapes. Kalshi: columns fight_id, market, ts, yes_price, dollars, taker (taker ‘yes’ / ‘no’ = the side that crossed). Polymarket: fight_id, kind, ts, yes_price, dollars, yes_dir (+1 = a YES-buying print, -1 = YES-selling). ts and the events’ t_entry are tz-aware timestamps on the same clock.

Parity notes (the numbers depend on these, so they are kept as the research had them):

  • tape_fills puts each Kalshi tape in (ts, trade_id) order (trades.time_order; a tape without trade_id: stable by ts) before summing the window dollars; capacity.instruments sums in the tape’s own row order (the trade tables are already in (fight_id, ts, trade_id) order, so the two agree).
  • tape_fills accepts an arrival up to 1e-9 above the limit (float noise in cents); capacity.instruments and the Polymarket rule compare with no tolerance.

Functions

arrival_price

arrival_price(tape: pd.DataFrame | None, t: pd.Timestamp, side_buys_yes: bool, entry: float, latency_s: float, price_col: str = 'yes_price', dir_col: str | None = None) -> float

The price the order meets on arrival (research capacity._arrival; the same rule inlined in execution.tape_fills): the worse (higher, in our side’s terms) of entry and every print on our side in (t, t + latency]. Kalshi prints are on our side when their taker is our side; Polymarket prints (dir_col) when their direction is ours. A NO price is 1 - the YES print.

kalshi_tapes

kalshi_tapes(trades: pd.DataFrame, sort_by_ts: bool) -> dict[tuple[str, str], pd.DataFrame]

The Kalshi tape split by (fight_id, market), the key columns as strings (research: astype(str) on fight_id, market, taker); trade_id kept when the tape has it. sort_by_ts: tape_fills puts each tape in time order (trades.time_order: ties by trade_id); capacity.instruments keeps the tape’s row order.

polymarket_instrument

polymarket_instrument(bet: Any, kalshi_entry: float, tape: pd.DataFrame | None, t: pd.Timestamp, side_buys_yes: bool, inst: str, config: BacktestConfig) -> dict[str, Any] | None

One Polymarket instrument row for a bet (research capacity._poly), or None.

Quote = the last print on our side in [t - window, t) (the tape’s row order); a quote more than config.stale from Kalshi’s price for the same event (kalshi_entry) is stale and skipped. Filled at the arrival price if within quote + cushion. Fee 0 unless config.poly_fee_as_kalshi.

polymarket_tapes

polymarket_tapes(poly_trades: pd.DataFrame | None) -> dict[tuple[str, str], pd.DataFrame]

The Polymarket tape split by (fight_id, kind), in the tape’s row order; {} if none.

rounds_tape_market

rounds_tape_market(market: str, round_idx: int) -> str

The Kalshi tape a round-system bet fills on: ‘ends this round’ at the start of round round_idx + 1 is the rounds market ‘ends before round round_idx + 2’; everything else fills on the distance market.

tape_fills

tape_fills(events: pd.DataFrame, trades: pd.DataFrame, config: BacktestConfig = BacktestConfig(), tape_market: Callable[[str, int], str] = rounds_tape_market) -> pd.DataFrame

Per event (index idx = the event’s index label): window_dollars (the market’s $ in the window before t) and, per (latency, cushion) in the config’s grid, avail_{lat}_{cush} (1.0 filled / 0.0 missed) and vwap_{lat}_{cush} (the arrival price paid, NaN if missed; one price, the name is the research’s).

events needs fight_id, round_idx, market, t_entry, entry, side; entry is the decision price on the bet’s side (YES: the ask; NO: 1 - the bid).

window_dollars

window_dollars(tape: pd.DataFrame | None, t: pd.Timestamp, minutes: float) -> float

Dollars traded on the tape in [t - minutes, t); 0 without a tape.