Skip to content

betting_combat.rounds.market.breaks

Group 6 of the round dataset: Kalshi and Polymarket prices at each round start.

Ported from the research (ufc/dataset/markets.py: KalshiBreaks, _swap, poly_breaks; the fights KalshiBreaks.method_prices takes from ufc/joint.py contexts). Rows are (fight_id, round_idx) like the dataset’s, A-framed. The row time for round_idx r is the last completed minute at start + 6r minutes (the end of the break); for round_idx 0 the minute before the start. A fight’s rows stop at the first row time missing from its minute frame (no cut at the winner market’s snap, which is only known afterwards; the dataset keeps the rounds that started).

kalshi_timing how the clock was anchored (finish_anchor / bell_anchor / break_template)
kalshi_p_a A's win probability: the mean of A's mid and 1 - B's mid
kalshi_bid_a / kalshi_ask_a / kalshi_spread_a A's winner book
kalshi_vol5 winner contracts traded in the 5 minutes to the row time
kalshi_p_dec the distance market's mid (2026 on)
kalshi_mov_* method-of-victory mids, A-framed (2026 on)
poly_p_a Polymarket's price for A (a print within 5 minutes)

Functions

kalshi_breaks

kalshi_breaks(fights: pd.DataFrame, winner_minutes: Mapping[str, list[dict[str, Any]]], clock: FightClock, a_slot: Mapping[str, int], extra: Mapping[str, Mapping[str, pd.DataFrame]]) -> tuple[pd.DataFrame, dict[str, pd.Timestamp]]

Kalshi’s prices at each round start (research KalshiBreaks.build).

Returns the rows (:data:KALSHI_COLUMNS; a fight Kalshi listed twice appears twice, the caller keeps the first) and fight_id -> start (a fight listed twice keeps its LAST listing’s start, as the research’s starts).

Args: fights: :func:~.listing.fight_ids rows. winner_minutes: the winner markets’ 1-minute candles by ticker. clock: the fight clock. a_slot: fight_id -> the UFCStats slot (1 or 2) of fighter A; a fight missing from it is framed as if fighter A were slot 2. extra: :func:method_prices.

method_prices

method_prices(fights: pd.DataFrame, winner_minutes: Mapping[str, list[dict[str, Any]]], side_minutes: Mapping[str, list[dict[str, Any]]], mov: Iterable[Mapping[str, Any]], mof: Iterable[Mapping[str, Any]], rounds_: Iterable[Mapping[str, Any]], vic: Iterable[Mapping[str, Any]], distance: Iterable[Mapping[str, Any]], clock: FightClock) -> dict[str, dict[str, pd.DataFrame]]

event_ticker -> {name: minute frame} for the distance and the six method-of-victory markets (Kalshi-A-framed names), for the fights the joint model priced: 2026 cards whose six MOV minute frames all cover the minute 3 minutes before the start (research KalshiBreaks.method_prices over joint.contexts; the joint model’s finish curves, which filter nothing, are not built).

Args: fights: :func:~.timing.build_fights rows. winner_minutes: the winner markets’ 1-minute candles by ticker. side_minutes: the side and distance markets’ candles by ticker, merged in the research’s order (KXUFCMOV, KXUFCMOF, KXUFCROUNDS, KXUFCVICROUND, distance). mov, mof, rounds_, vic: the KXUFCMOV, KXUFCMOF, KXUFCROUNDS, KXUFCVICROUND markets. distance: the KXUFCDISTANCE markets. clock: the fight clock.

poly_breaks

poly_breaks(kalshi_rows: pd.DataFrame, starts: Mapping[str, pd.Timestamp], history: Mapping[str, Any], a_slot: Mapping[str, int]) -> pd.DataFrame

Polymarket’s price for A at the Kalshi rows’ minutes (research poly_breaks): the last print at or before the row time, if within 5 minutes.

Args: kalshi_rows: :func:kalshi_breaks rows (fight_id, round_idx). starts: :func:kalshi_breaks starts. history: Polymarket price histories by fight_id (polymarket_ufc.json’s history; a fight missing or None has no price). a_slot: fight_id -> the UFCStats slot (1 or 2) of fighter A.

row_time

row_time(start: pd.Timestamp, round_idx: int) -> pd.Timestamp

The row’s minute: the minute before the start (round_idx 0), else the end of the break before round round_idx + 1.

swap_mov

swap_mov(name: str) -> str

mov_a_ko <-> mov_b_ko when Kalshi’s fighter A is our B.