Skip to main content

Overview

The feed.py module provides a centralized, thread-safe market data feed that runs in the background and shares real-time market information across all trading bots. It continuously fetches open markets, tracks price history, and monitors settlements.

Classes

MarketSnapshot

Immutable snapshot of a single market’s state at a specific point in time. Attributes:
ticker
str
required
Market ticker symbol
event_ticker
str
required
Parent event ticker
status
str
required
Market status: "open", "closed", or "settled"
result
str
required
Settlement result: "yes", "no", or empty string for unsettled markets
yes_ask
float
required
Yes side ask price in dollars (0.0 - 1.0)
no_ask
float
required
No side ask price in dollars (0.0 - 1.0)
yes_bid
float
required
Yes side bid price in dollars (0.0 - 1.0)
no_bid
float
required
No side bid price in dollars (0.0 - 1.0)
last_price
float
required
Last traded price in dollars (0.0 - 1.0)
volume_24h
float
required
24-hour trading volume
open_interest
float
required
Current open interest
close_time
datetime | None
required
Market close time (None if not set)
category
str
required
Market category (e.g., “politics”, “economics”)
title
str
required
Market title/description
fetched_at
datetime
required
Timestamp when this snapshot was fetched
# Example usage
snap = MarketSnapshot(
    ticker="KXBTC-23DEC31-T50000",
    event_ticker="KXBTC",
    status="open",
    result="",
    yes_ask=0.45,
    no_ask=0.56,
    yes_bid=0.44,
    no_bid=0.55,
    last_price=0.45,
    volume_24h=15000.0,
    open_interest=8000.0,
    close_time=datetime(2023, 12, 31),
    category="crypto",
    title="Will Bitcoin be above $50,000?",
    fetched_at=datetime.now(timezone.utc)
)

MarketHistory

Rolling price history for a single market with automatic size limiting. Attributes:
ticker
str
required
Market ticker symbol
yes_ask_history
list[tuple[datetime, float]]
List of (timestamp, yes_ask_price) tuples. Automatically trimmed to MARKET_HISTORY_MAX_TICKS.
Methods:

append(ts: datetime, yes_ask: float)

Append a new price observation to the history. Automatically trims the list to maintain the maximum size.
ts
datetime
required
Timestamp of the observation
yes_ask
float
required
Yes ask price at this timestamp
history = MarketHistory(ticker="KXBTC-23DEC31-T50000")
history.append(datetime.now(timezone.utc), 0.45)
history.append(datetime.now(timezone.utc), 0.46)

# Access history
for ts, price in history.yes_ask_history:
    print(f"{ts}: ${price:.2f}")

MarketDataFeed

Centralized market data fetcher that runs in its own background thread. All bots read from shared state via public read methods.

__init__(client, poll_interval: float = 30.0)

client
KalshiClient
required
Authenticated Kalshi API client
poll_interval
float
default:"30.0"
Seconds between market data fetches
from kalshi_client import KalshiClient
from genetic.feed import MarketDataFeed

client = KalshiClient()
feed = MarketDataFeed(client, poll_interval=30.0)

start()

Start the background fetch thread.
feed.start()
print("Market data feed running in background...")

stop()

Stop the background fetch thread (blocks up to 10 seconds).
feed.stop()

get_open_markets() → dict[str, MarketSnapshot]

Return a copy of all currently open markets.
markets
dict[str, MarketSnapshot]
Dictionary mapping ticker symbols to market snapshots
markets = feed.get_open_markets()
for ticker, snap in markets.items():
    print(f"{ticker}: ${snap.yes_ask:.2f} (closes {snap.close_time})")

get_market(ticker: str) → MarketSnapshot | None

Get a specific market snapshot (checks both open and settled markets).
ticker
str
required
Market ticker to retrieve
snapshot
MarketSnapshot | None
Market snapshot if found, None otherwise
market = feed.get_market("KXBTC-23DEC31-T50000")
if market:
    print(f"Status: {market.status}, Yes ask: ${market.yes_ask:.2f}")

get_history(ticker: str) → list[tuple[datetime, float]]

Get price history for a specific market.
ticker
str
required
Market ticker to retrieve history for
history
list[tuple[datetime, float]]
List of (timestamp, yes_ask_price) tuples, empty list if ticker not found
history = feed.get_history("KXBTC-23DEC31-T50000")
if len(history) >= 2:
    old_price = history[0][1]
    new_price = history[-1][1]
    change = ((new_price - old_price) / old_price) * 100
    print(f"Price change: {change:+.1f}%")

get_settlement(ticker: str) → str | None

Return settlement result if market is settled.
ticker
str
required
Market ticker to check
result
str | None
"yes" or "no" if settled, None if not settled or not found
result = feed.get_settlement("KXBTC-23DEC31-T50000")
if result:
    print(f"Market settled: {result.upper()}")

get_categories() → list[str]

Return all known market categories.
categories
list[str]
Sorted list of category names (e.g., [“crypto”, “economics”, “politics”])
categories = feed.get_categories()
print(f"Available categories: {', '.join(categories)}")

get_stats() → dict

Return feed statistics and health metrics.
stats
dict
Dictionary with keys:
  • open_markets: Number of currently tracked open markets
  • settled_markets: Number of recently settled markets in cache
  • categories: Number of known categories
  • fetch_count: Total successful fetches since start
  • error_count: Total errors encountered
stats = feed.get_stats()
print(f"Feed status: {stats['open_markets']} markets, "
      f"{stats['fetch_count']} fetches, {stats['error_count']} errors")

check_specific_tickers(tickers: set[str])

Manually check specific tickers for settlement (used for positions we hold). This method queries individual markets directly rather than relying on bulk settlement checks.
tickers
set[str]
required
Set of ticker symbols to check
# Check if any of our open positions have settled
open_positions = {"TICKER1", "TICKER2", "TICKER3"}
feed.check_specific_tickers(open_positions)

# Then check results
for ticker in open_positions:
    result = feed.get_settlement(ticker)
    if result:
        print(f"{ticker} settled: {result}")

Internal State

The feed maintains several internal data structures (thread-safe with RLock):
  • markets: Currently open markets (ticker → MarketSnapshot)
  • histories: Price histories (ticker → MarketHistory)
  • settled: Recently settled markets (kept for 2 hours)
  • event_categories: Event ticker to category mapping
  • known_categories: List of all discovered categories

Configuration

The feed respects these configuration parameters from genetic.config:
  • MARKET_CLOSE_WINDOW_HOURS: Only fetch markets closing within this window
  • MARKET_HISTORY_MAX_TICKS: Maximum price history length per market

Build docs developers (and LLMs) love