Skip to main content

Overview

The bot.py module implements a multi-strategy paper trading bot that monitors Bitcoin prediction markets on Kalshi. It tracks 7 different trading strategies simultaneously, recording all trades to CSV for backtesting analysis.

Configuration Constants

API_BASE
string
default:"https://api.elections.kalshi.com/trade-api/v2"
Base URL for Kalshi trade API
SERIES_TICKER
string
default:"KXBTC15M"
Market series to monitor (15-minute Bitcoin prediction markets)
POLL_SECONDS
int
default:"5"
Polling interval in seconds between market checks
STAKE_USD
float
default:"5.0"
Stake amount in USD per trade for simple strategies
MOMENTUM_WINDOW_SECONDS
int
default:"60"
Lookback window for momentum strategy (1 minute)
MOMENTUM_15_WINDOW_SECONDS
int
default:"900"
Lookback window for 15-minute momentum strategy
INITIAL_BANKROLL_USD
float
default:"500"
Initial bankroll for consensus strategies (from env)
CONSENSUS_RISK_PCT
float
default:"0.01"
Risk percentage per trade for consensus strategies (from env)

Core Functions

get_btc_price()

Fetch the current Bitcoin spot price from Coinbase.
price
float
Current BTC/USD spot price
btc_price = get_btc_price()
print(f"BTC: ${btc_price:,.2f}")

get_open_market()

Get the next expiring open KXBTC15M market from Kalshi.
market
dict | None
Market object with ticker, yes_ask, no_ask, close_time, or None if no open markets
market = get_open_market()
if market:
    print(f"Trading {market['ticker']}")
    print(f"Prices: yes=${market['yes_ask']/100:.2f} no=${market['no_ask']/100:.2f}")

get_market(ticker)

Get a specific market by ticker symbol.
ticker
string
required
Market ticker (e.g., “KXBTC15M-24DEC05-T1030”)
market
dict
Market object including result field if settled
market = get_market("KXBTC15M-24DEC05-T1030")
if market.get("result"):
    print(f"Settled: {market['result']}")

get_settled_side(market)

Check if a market is settled and return the winning side.
market
dict
required
Market object from Kalshi API
result
str | None
Returns “yes”, “no”, or None if not settled
market = get_market(ticker)
result = get_settled_side(market)
if result:
    print(f"Market resolved: {result}")

Trade Management

load_trades()

Load all trades from the CSV file.
trades
list[dict]
List of trade records with all strategy data
trades = load_trades()
print(f"Loaded {len(trades)} historical trades")

save_trades(trades)

Save all trades to CSV with complete field set.
trades
list[dict]
required
List of trade dictionaries to persist
trades.append(new_trade)
save_trades(trades)

calc_stats(trades, strategy=None)

Calculate performance statistics for trades.
trades
list[dict]
required
List of trade records
strategy
str
Optional strategy name to filter by (e.g., “CONSENSUS”, “MOMENTUM”)
stats
dict
Statistics dict with keys: total_staked, total_profit, wins, losses, pending
stats = calc_stats(trades, "CONSENSUS")
print(f"P&L: ${stats['total_profit']:+.2f}")
print(f"Win rate: {stats['wins']}/{stats['wins'] + stats['losses']}")

Consensus Strategy Functions

consensus_bankroll(trades)

Calculate current consensus strategy bankroll from realized P&L.
trades
list[dict]
required
All trade records
bankroll
float
Initial bankroll plus realized consensus profits
bankroll = consensus_bankroll(trades)
print(f"Consensus bankroll: ${bankroll:.2f}")

consensus_period_pnl(trades, now)

Calculate daily and weekly P&L for consensus strategies.
trades
list[dict]
required
All trade records
now
datetime
required
Current datetime for period calculation
daily_pnl
float
Today’s realized P&L
weekly_pnl
float
This ISO week’s realized P&L
from datetime import datetime, timezone
now = datetime.now(timezone.utc)
daily, weekly = consensus_period_pnl(trades, now)
print(f"Today: ${daily:+.2f} | Week: ${weekly:+.2f}")

rolling_consensus_metrics(trades)

Calculate rolling performance metrics and break-even win rate.
trades
list[dict]
required
All trade records
metrics
dict
Dict with keys: sample_size, win_rate, break_even_win_rate
metrics = rolling_consensus_metrics(trades)
if metrics['sample_size'] >= 30:
    wr = metrics['win_rate'] * 100
    be = metrics['break_even_win_rate'] * 100
    print(f"Win rate: {wr:.1f}% (need {be:.1f}% to break even)")

Trading Strategies

The bot implements 7 simultaneous paper trading strategies:
  1. PREVIOUS: Buy the same side as the previous market’s result
  2. MOMENTUM: Buy based on BTC price direction over 60 seconds
  3. CONSENSUS: Only trade when PREVIOUS and MOMENTUM agree (with risk management)
  4. MOMENTUM_15: Buy based on BTC direction over 15 minutes
  5. PREVIOUS_2: Wait for PREVIOUS side at price ≤ $0.45
  6. CONSENSUS_2: Wait for CONSENSUS agreement at price ≤ $0.45
  7. ARBITRAGE: Buy immediately then hedge opposite side if profitable
# Example: Running the bot
from bot import main
from dotenv import load_dotenv

load_dotenv()
main()

Main Loop

main()

Main bot loop that monitors markets and executes all strategies.
  • Polls for open markets every POLL_SECONDS
  • Tracks BTC price history for momentum signals
  • Executes trades when strategy conditions are met
  • Checks for settled markets and updates P&L
  • Enforces risk limits for consensus strategies
# Run the bot
python bot.py
The bot will:
  • Load historical trades from CSV
  • Print initial statistics for all strategies
  • Monitor markets continuously
  • Execute trades according to each strategy’s rules
  • Update and save trades as markets settle

Build docs developers (and LLMs) love