Keep Market Identifiers Consistent Across Research Artifacts
A backtest that says "this strategy worked on the NYC high-temperature market" is almost useless six weeks later. Which NYC high-temperature market? Which day? Which strike? Which side? If your saved result does not pin down the exact instrument, you will eventually compare two different contracts as if they were one, and you will not notice until the numbers stop making sense.
Kalshi's own data model gives you the vocabulary to avoid this. The fix is to record the full identity chain next to every artifact, not just a human-readable title. Here is how the levels work and what to persist.
The four levels of identity
Kalshi organizes everything in a three-level hierarchy, and a market carries one more distinction below it: which side you hold.
The series is the top-level object. A series is a template for recurring events that follow the same format and rules, for example a monthly jobs report or daily NYC weather. Series define the structure, settlement sources, and metadata applied to each recurring event.
An event is a collection of markets and the basic unit members interact with. An event represents one real-world occurrence, like a specific election, game, or indicator release, and contains one or more markets covering different outcomes or strikes.
A market is a single binary contract within an event. Each event belongs to exactly one series, identified by series_ticker, and each market belongs to exactly one event, identified by event_ticker.
The documented example makes the nesting concrete: a series like KXHIGHNY has an event such as KXHIGHNY-24JAN01, which in turn has a market such as KXHIGHNY-24JAN01-T60. The best practice is to filter and group by the series rather than inferring structure from the string.
- Series ticker, for example KXHIGHNY. Groups recurring events over time.
- Event ticker, for example KXHIGHNY-24JAN01. One real-world occurrence.
- Market ticker, for example KXHIGHNY-24JAN01-T60. One binary contract at a specific strike.
- Outcome side: YES or NO. The same market has two opposite positions with different payoffs.
Do not parse the ticker to infer relationships
It is tempting to split KXHIGHNY-24JAN01-T60 on the hyphens and assume you have recovered the series, event, and strike. Developer guides tracking the current API warn explicitly against parsing ticker strings to infer relationships, and recommend using the API's actual relationship fields instead. Tickers often follow the Series to Event to Market pattern, but categories and subcategories are not part of the ticker convention, and the string format is not a contract you should build on.
Store series_ticker, event_ticker, and the market ticker as separate fields that you read from the API response, not substrings you reconstructed. That way a formatting change does not silently corrupt your joins.
Why the outcome side has to be explicit
For a standard binary market the YES and NO sides are complements: the winning side pays out one dollar per contract and the losing side expires worthless. A result that logs "bought the market" without logging the side is ambiguous about the entire payoff.
Do not universalize that one-dollar payoff. Kalshi also runs scalar markets, where both YES and NO can be redeemable at proportional payouts rather than a clean one-or-zero. The market result field takes a third value, scalar, for fractionally-settled markets; a query filtering only on yes or no silently drops them. If your artifact assumes every contract is a $1/$0 binary, it will misprice scalar and exceptional contracts. Record the market type, not just the side.
A title is not an identifier, and listings get replaced
Two markets in the same weather series on different days can share nearly identical titles. Worse, a single market moves through a lifecycle, and the listing you tested against may not be the one you look at later.
Kalshi documents distinct lifecycle statuses: initialized, active, inactive, closed, determined, disputed, amended, and finalized. A disputed result can be re-determined, and an amended market restarts its settlement timer. The API's status filter values (unopened, open, paused, closed, settled) overlap with but are not identical to those underlying states, so treat the filter enum and the lifecycle field as separate things and join on the underlying field.
Close time is also not determination time. A market's close_time marks when trading stops; determination follows only after an official source publishes finalized data. So an artifact that captured a market mid-window is describing a different state than one captured after determination, even for the same ticker.
What to save beside every result
Treat the identity block as mandatory metadata on any backtest or paper record. At minimum:
- series_ticker, event_ticker, and market ticker, each read from the API, not parsed.
- Outcome side (YES/NO) and market result type (binary vs scalar).
- The lifecycle status at the time of observation, plus close time and, if known, determination time.
- The exact timestamp window the data covers, in UTC.
- The data, fill, fee, and valuation model that produced the numbers, since a paper result is evidence under that model, not proof of real execution.
- A content hash or snapshot of the market's rules_primary and settlement sources, so an amended rule is visible later.
If any of these is unknown, record it as unknown rather than guessing. Preserving a missing field is honest; backfilling it from a parsed ticker is how two contracts quietly become one.
Where this shows up in Banger
Banger is a paper-research beta for prediction-market strategies, and its hosted historical backtesting currently supports Kalshi binary markets. The package installs with pip install bangertrades, and its public listing describes it as a paper beta. The same identifier discipline applies: pick and preserve an exact current market ticker for a run rather than trusting that "take the first discovery result" will reproduce tomorrow. A strategy's on_market_tick(self, market, tick, ctx) callback sees a specific market object, and your saved artifact should carry that market's full identity chain alongside whatever fill and fee model produced the paper fills. A paper result is evidence under one model, not a venue execution, so the model itself belongs in the record too.
None of this is glamorous. It is bookkeeping. But the difference between a research archive you can trust and a pile of ambiguous numbers is entirely in whether you wrote down which instrument you were actually looking at.
Sources
- Kalshi Glossary - API Documentation
- Get Series - API Documentation
- Kalshi API Guide 2026: Auth, WebSocket, Candlesticks & SDKs
- Market Lifecycle - API Documentation
- Market Settlement - API Documentation
- How to Trade Kalshi Prediction Markets on Solana Using DFlow
- Market FAQs - Kalshi Help Center
- bangertrades 0.1.7 - PyPI