What is Paper Trading?
Paper trading (also called “mock trading” or “backtesting”) allows you to run the Simple Kalshi Bot without placing real orders. This is perfect for:
Testing strategies before risking real money
Understanding how the bot behaves
Analyzing strategy performance over time
Developing and debugging new strategies
Paper trading uses real market data from Kalshi but simulates all trade execution locally.
How It Works
The paper trading bot (bot.py) operates in a continuous loop:
Fetch Market Data
Polls Kalshi’s public API to get current market prices and settlement data
Generate Signals
All seven strategies analyze market conditions and generate trading signals
Simulate Trades
Instead of placing real orders, trades are logged to a CSV file
Track Settlements
Monitors when markets settle and calculates profit/loss for each simulated trade
Running Paper Trading
Basic Usage
The bot will start monitoring markets and logging trades to data/mock_trades.csv.
Configuration
Configure the bot using environment variables or a .env file:
# Series to trade
SERIES_TICKER = KXBTC15M
# Stake amount per trade (in USD)
STAKE_USD = 5.0
# Poll interval in seconds
POLL_SECONDS = 5
# CSV output file
TRADES_CSV = data/mock_trades.csv
# Risk management for CONSENSUS strategy
INITIAL_BANKROLL_USD = 500
CONSENSUS_RISK_PCT = 0.01
CONSENSUS_MAX_RISK_PCT = 0.02
CONSENSUS_MAX_PRICE = 0.55
CONSENSUS_DAILY_LOSS_CAP_R = 3
CONSENSUS_WEEKLY_LOSS_CAP_R = 8
Paper trading requires an active internet connection to fetch real-time market data from Kalshi and BTC prices from Coinbase.
Trade Logging
All simulated trades are saved to a CSV file with complete trade details:
CSV Structure
# From bot.py:97-105
fieldnames = [
"time" , # ISO timestamp when trade was placed
"strategy" , # PREVIOUS, MOMENTUM, CONSENSUS, etc.
"previous_ticker" , # Previous market ticker (if applicable)
"previous_result" , # Previous market result or signal info
"buy_ticker" , # Market ticker being traded
"buy_side" , # "yes" or "no"
"stake_usd" , # Amount wagered
"price_usd" , # Price per contract (0.00 to 1.00)
"contracts" , # Number of contracts purchased
"fee_usd" , # Trading fees (for CONSENSUS strategies)
"gross_profit_usd" , # Profit before fees
"outcome" , # "WIN", "LOSS", or empty if pending
"payout_usd" , # Payout received
"profit_usd" # Net profit/loss
]
Example Trade Entry
time, strategy, previous_ticker, previous_result, buy_ticker, buy_side, stake_usd, price_usd, contracts, fee_usd, gross_profit_usd, outcome, payout_usd, profit_usd
2026-03-05T14:30:00, CONSENSUS, KXBTC15M-26MAR05-T2030, PREV=yes MOM=yes, KXBTC15M-26MAR05-T2045, yes, 5.0, 0.52, 9.615, 0.0, 4.615, WIN, 9.615, 4.615
Mock Trade Execution
When a strategy decides to trade, the bot creates a simulated trade:
# From bot.py:589-607
trade = {
"time" : now.isoformat(),
"strategy" : "CONSENSUS" ,
"previous_ticker" : "" ,
"previous_result" : f "PREV= { prev_signal } MOM= { mom_signal } " ,
"buy_ticker" : ticker,
"buy_side" : side,
"stake_usd" : round (stake, 4 ),
"price_usd" : round (price, 4 ),
"contracts" : contracts,
"fee_usd" : "" ,
"gross_profit_usd" : "" ,
"outcome" : "" ,
"payout_usd" : "" ,
"profit_usd" : "" ,
}
trades.append(trade)
save_trades(trades)
Trades are immediately saved to CSV to prevent data loss if the bot crashes.
Settlement Tracking
The bot continuously checks pending trades for settlement:
# From bot.py:323-356
for trade in trades:
if trade.get( "outcome" ):
continue # Already settled
buy_ticker = trade.get( "buy_ticker" )
if not buy_ticker:
continue
try :
m = get_market(buy_ticker)
result = get_settled_side(m)
if result:
buy_side = trade.get( "buy_side" )
contracts = float (trade.get( "contracts" , 0 ))
stake = float (trade.get( "stake_usd" , 0 ))
won = (result == buy_side)
payout = contracts if won else 0
gross_profit = payout - stake
fee = stake * CONSENSUS_FEE_PCT if trade.get( "strategy" ) in ( "CONSENSUS" , "CONSENSUS_2" ) else 0.0
profit = gross_profit - fee
trade[ "outcome" ] = "WIN" if won else "LOSS"
trade[ "payout_usd" ] = round (payout, 4 )
trade[ "gross_profit_usd" ] = round (gross_profit, 4 )
trade[ "fee_usd" ] = round (fee, 4 )
trade[ "profit_usd" ] = round (profit, 4 )
The bot displays real-time performance metrics:
# From bot.py:108-137
def calc_stats ( trades , strategy = None ):
total_staked = 0.0
total_profit = 0.0
wins = 0
losses = 0
pending = 0
for t in trades:
if strategy and t.get( "strategy" ) != strategy:
continue
total_staked += float (t.get( "stake_usd" , 0 ))
profit = t.get( "profit_usd" , "" )
if profit != "" :
p = float (profit)
total_profit += p
if p > 0 :
wins += 1
else :
losses += 1
else :
pending += 1
Console Output
[14:30:15] KXBTC15M-26MAR05-T2045 (420s) | yes=$0.52 no=$0.48 | BTC=94,250 |
P:$+12.50 M:$-8.20 C:$+15.40 M15:$+3.10 P2:$+6.00 C2:$+18.75 A:$+2.30 CB:$518.75
Legend:
P : PREVIOUS strategy P&L
M : MOMENTUM strategy P&L
C : CONSENSUS strategy P&L
M15 : MOMENTUM_15 strategy P&L
P2 : PREVIOUS_2 strategy P&L
C2 : CONSENSUS_2 strategy P&L
A : ARBITRAGE strategy P&L
CB : CONSENSUS bankroll
Analyzing Results
After running the bot, analyze performance using the analysis scripts:
This generates comprehensive statistics for each strategy:
=== FINAL STATS ===
PREVIOUS: $ +12.50 | 15W/8L | 2 pending
MOMENTUM: $ -8.20 | 10W/13L | 2 pending
CONSENSUS: $ +15.40 | 12W/5L | 1 pending
MOMENTUM_15: $ +3.10 | 8W/7L | 2 pending
PREVIOUS_2: $ +6.00 | 9W/6L | 1 pending
CONSENSUS_2: $ +18.75 | 14W/4L | 1 pending
ARBITRAGE: $ +2.30 | 6W/5L | 3 pending
TOTAL: $ +49.85 | 74W/48L
Advantages of Paper Trading
Risk-Free Testing Test strategies without risking real money
Strategy Validation Validate trading logic before going live
No API Keys Required Uses public market data only
Full History Complete trade history in CSV format
Limitations
Paper trading has important limitations compared to real trading:
No execution risk : Real orders may not fill at expected prices
No slippage : Assumes instant execution at market prices
No order book depth : Doesn’t account for available liquidity
Simplified fees : May not match actual Kalshi fee structure
Next Steps
Real Trading Ready to trade with real money? Learn how to deploy the bot with Kalshi API authentication.