Skip to main content

pykalshi logo

PyKalshi

PyPI version Python versions Tests License Open In Colab

The Python client for Kalshi prediction markets. WebSocket streaming, automatic retries, pandas integration, and clean interfaces for building trading systems.

Jupyter notebook rich display

from pykalshi import KalshiClient, Action, Side

client = KalshiClient()

# Place a trade
order = client.portfolio.place_order("KXBTC-25MAR15-B100000", Action.BUY, Side.YES, count_fp="10", yes_price_dollars="0.45")
order.wait_until_terminal()  # Block until filled/canceled

Features

  • WebSocket streaming - Real-time orderbook, ticker, and trade data with typed messages
  • Automatic retries - Exponential backoff on rate limits and transient errors
  • Domain objects - Market, Order, Event with methods like order.cancel(), market.get_orderbook()
  • pandas integration - .to_dataframe() on any list of results
  • Jupyter support - Rich HTML display for markets, orders, and positions
  • Local orderbook - OrderbookManager maintains state from WebSocket deltas
  • Type safety - Pydantic models and typed exceptions throughout

Installation

pip install pykalshi

# With pandas support
pip install pykalshi[dataframe]

Get your API credentials from kalshi.com and create a .env file:

KALSHI_API_KEY_ID=your-key-id
KALSHI_PRIVATE_KEY_PATH=/path/to/private-key.key

Quick Start

Interactive demo: examples/demo.ipynb or Open In Colab

Browse Markets

from pykalshi import MarketStatus, CandlestickPeriod

client = KalshiClient()

# Search markets
markets = client.get_markets(status=MarketStatus.OPEN, limit=100)
btc_markets = client.get_markets(series_ticker="KXBTC")

# Get a specific market
market = client.get_market("KXBTC-25MAR15-B100000")
print(f"{market.title}: ${market.yes_bid_dollars} / ${market.yes_ask_dollars}")

# Market data
orderbook = market.get_orderbook()
trades = market.get_trades(limit=50)
candles = market.get_candlesticks(start_ts, end_ts, period=CandlestickPeriod.ONE_HOUR)

Trading

from pykalshi import Action, Side, OrderStatus

# Check balance
balance = client.portfolio.get_balance()
print(f"${balance.balance / 100:.2f} available")

# Place an order. Orders rest on a single YES-denominated book: book_side
# "bid" is long yes, "ask" is long no, and price_dollars is always the YES leg.
order = client.portfolio.place_order(market, book_side="bid", price_dollars="0.50", count_fp="10")

# An ask at 0.17 is the same resting order as buying NO at 0.83 -- no mental
# 1-p conversion needed.
order = client.portfolio.place_order(market, book_side="ask", price_dollars="0.17", count_fp="10")

# Read direction back with book_side / outcome_side. The legacy action/side
# pair is deprecated by Kalshi and means different things on orders vs fills.
assert order.book_side.value == "ask" and order.is_ask

# Manage orders
order.wait_until_terminal()                    # Block until filled/canceled
order.amend(price_dollars="0.45")              # Amend price (YES leg)
order.decrease(reduce_by_fp="5")               # Shrink the resting size
order.cancel()                                 # Cancel

# The legacy vocabulary still works and maps onto the same wire body:
order = client.portfolio.place_order(market, Action.BUY, Side.NO, count_fp="10", no_price_dollars="0.83")

# View portfolio
positions = client.portfolio.get_positions()
fills = client.portfolio.get_fills(limit=100)
orders = client.portfolio.get_orders(status=OrderStatus.RESTING)

Real-time Streaming

from pykalshi import Feed, TickerMessage, OrderbookSnapshotMessage

async with Feed(client) as feed:
    await feed.subscribe_ticker("KXBTC-25MAR15-B100000")
    await feed.subscribe_orderbook("KXBTC-25MAR15-B100000")
    await feed.subscribe_trades("KXBTC-25MAR15-B100000")

    async for msg in feed:
        match msg:
            case TickerMessage():
                print(f"Price: ${msg.price_dollars}")
            case OrderbookSnapshotMessage():
                print(f"Book: {len(msg.yes)} yes levels, {len(msg.no)} no levels")

Local Orderbook

from pykalshi import Feed, OrderbookManager

manager = OrderbookManager()

async with Feed(client) as feed:
    await feed.subscribe_orderbook(ticker)

    async for msg in feed:
        manager.apply(msg)
        book = manager.get(ticker)
        best_bid = book["yes_dollars"][0] if book["yes_dollars"] else None

pandas Integration

# Any list result has .to_dataframe()
positions_df = client.portfolio.get_positions().to_dataframe()
markets_df = client.get_markets(limit=500).to_dataframe()
fills_df = client.portfolio.get_fills().to_dataframe()

# Candlesticks and orderbooks too
candles_df = market.get_candlesticks(start, end).to_dataframe()
orderbook_df = market.get_orderbook().to_dataframe()

Error Handling

from pykalshi import InsufficientFundsError, RateLimitError, KalshiAPIError

try:
    order = client.portfolio.place_order(...)
except InsufficientFundsError:
    print("Not enough balance")
except RateLimitError:
    pass  # Client auto-retries with backoff
except KalshiAPIError as e:
    print(f"{e.status_code}: {e.error_code}")

Examples

See the examples/ directory:

Web Dashboard

A real-time web dashboard is included for browsing markets, viewing orderbooks, and monitoring your portfolio. It serves as both a development tool and a reference implementation.

pip install pykalshi[web]
uvicorn web.backend.main:app --reload

See web/ for details.

Why pykalshi?

pykalshi kalshi-python (official)
WebSocket streaming ✓ —
Automatic retry/backoff ✓ —
Rate limit handling ✓ —
Domain objects ✓ —
pandas integration ✓ —
Jupyter display ✓ —
Local orderbook ✓ —
Typed exceptions ✓ —
Pydantic models ✓ —
Full API coverage — ✓

The official SDK is auto-generated from the OpenAPI spec. pykalshi adds the infrastructure needed for production trading: real-time data, error recovery, and ergonomic interfaces.

Links


This is an unofficial library and is not affiliated with Kalshi.

Metadata

Release files for pykalshi 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pykalshi 2.0.0
File Size Uploaded
pykalshi-2.0.0.tar.gz 123.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pykalshi 2.0.0
File Interpreter ABI Platform
pykalshi-2.0.0-py3-none-any.whl Python 3 none any Details

Total release size: 221.5 kB

Release files / pykalshi-2.0.0.tar.gz

Download URL pykalshi-2.0.0.tar.gz
Size 123.0 kB
Tags Source
SHA-256 checksum
How to use checksums
0430a7f716d630d5b55070ede30b62705840a36d933c058e4b6625be153e7e6c
BLAKE2b-256 checksum
How to use checksums
f2f5f58a9d1c3aa96963db9955fd9873e481de346f466ea9d6fcbb38fef09175
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.23

Release files / pykalshi-2.0.0-py3-none-any.whl

Download URL pykalshi-2.0.0-py3-none-any.whl
Size 98.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0d5b88b7069c33dc0296235dfae90988ee998d65dd2889b6f9a4c378850529a9
BLAKE2b-256 checksum
How to use checksums
487d4aeec7af5485d1e6d66d18261ca87b68afab30d798004b6e2ab57b6b445f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.8.23

Release history Release notifications | RSS feed

This release

2.0.0 This release

2 release files

1.0.6

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page