Overview
The GeneticBot class represents a single bot in the evolutionary population. It decodes its genome into trading parameters and executes trades based on its strategy.
GeneticBot Class
Constructor
The bot’s genetic strategy
engine
PaperTradingEngine
required
Paper trading engine
Available market categories
from genetic.bot import GeneticBot
from genetic.genome import Genome
from genetic.feed import MarketDataFeed
from genetic.engine import PaperTradingEngine
from kalshi_client import KalshiClient
client = KalshiClient()
feed = MarketDataFeed(client)
engine = PaperTradingEngine(feed)
genome = Genome.random()
categories = ["Finance", "Politics", "Economics"]
bot = GeneticBot(genome, feed, engine, categories, bankroll=100.0)
print(f"Bot {bot.bot_id} created")
print(f"Strategy: {bot.params['signal_type']}")
Attributes
Bot’s genome (read-only during lifetime)
Reference to shared market feed
Reference to paper trading engine
Decoded trading parameters from genome
Unique bot identifier: f”bot_”
Bot’s paper trading account
Main Methods
tick()
Execute one trading cycle. Called every TICK_INTERVAL_SECONDS.
Process:
- Check daily limits (trades, loss cap)
- Check position limits
- Scan all open markets
- Apply market filters
- Generate trading signals
- Execute trades with position sizing
# Main evolution loop
for tick in range(num_ticks):
feed.update() # Refresh market data
for bot in population:
bot.tick() # Each bot evaluates and trades
engine.settle_markets() # Check for settlements
Market Filtering
_passes_market_filter(snap)
Check if a market passes this bot’s filter criteria.
Market snapshot to evaluate
True if market passes all filters
Filters applied:
- Volume 24h ≥
min_volume_24h (if available)
- Open interest ≥
min_open_interest (if available)
- Category in
categories list
- Time to expiry between
min_time_to_expiry_hrs and max_time_to_expiry_hrs
- At least one side’s ask price in range [
min_price, max_price]
# Example usage (internal)
for ticker, snap in markets.items():
if not bot._passes_market_filter(snap):
continue
# ... generate signal
Signal Generation
_generate_signal(snap)
Generate trading signal for a market based on signal_type.
Returns (side, confidence) or None if no signal
Signal types:
price_level: Buy when ask in specific range
momentum: Buy based on price direction
mean_reversion: Buy on z-score deviation
value: Buy cheap side vs fair value
contrarian: Bet against crowd
signal = bot._generate_signal(market_snap)
if signal:
side, confidence = signal
print(f"Signal: {side} (confidence: {confidence:.2f})")
Signal Strategies
_signal_price_level(snap)
Buy when ask price falls in configured range.
# Example: Buy yes if price between $0.30-$0.70
if price_threshold_low <= yes_ask <= price_threshold_high:
return ("yes", yes_ask)
_signal_momentum(snap)
Buy based on price direction over lookback window.
Number of ticks to look back
Minimum % change to trigger signal
# Example: If price up 5% over 30 ticks, buy yes
if pct_change > momentum_trigger_pct:
return ("yes", abs(pct_change))
elif pct_change < -momentum_trigger_pct:
return ("no", abs(pct_change))
_signal_mean_reversion(snap)
Buy when price deviates from rolling mean.
Z-score threshold (e.g., 2.0 = 2 std devs)
# Example: If price 2 std devs above mean, expect drop
if z > mean_rev_zscore:
return ("no", abs(z)) # Price too high
elif z < -mean_rev_zscore:
return ("yes", abs(z)) # Price too low
_signal_value(snap)
Buy whichever side is cheaper vs 50/50 fair value.
Minimum edge required (e.g., 0.15 = 15 cent discount)
# Example: If yes trading at $0.35, edge = $0.15
yes_edge = 0.50 - yes_ask
if yes_edge > value_edge_min:
return ("yes", yes_edge)
_signal_contrarian(snap)
Bet against the crowd when market is very confident.
Confidence threshold (e.g., 0.80 = 80%)
# Example: If yes at $0.85, bet no (crowd overconfident)
if yes_ask > contrarian_threshold:
return ("no", yes_ask - contrarian_threshold)
Side Selection
_apply_side_bias(signal_side)
Apply genome-encoded directional bias to signal.
Original signal side (“yes” or “no”)
Final side after bias application
Logic:
side_bias < 0.2: Always return “no”
side_bias > 0.8: Always return “yes”
0.2 ≤ side_bias ≤ 0.8: Follow signal with possible flip
# Example: 15% chance to flip side
if random.random() < side_flip_prob:
return opposite_of(signal_side)
return signal_side
Position Sizing
Position sizing uses Kelly-like fractional bankroll approach:
# Target allocation
alloc = acct.equity * params['bankroll_fraction']
# Cap to max single market allocation
max_alloc = acct.equity * params['max_single_market_pct']
alloc = min(alloc, max_alloc)
# Can't exceed available cash
alloc = min(alloc, acct.cash)
# Execute
engine.try_buy(bot_id, ticker, side, alloc)
Risk Controls
Bots enforce multiple risk limits:
# Daily trade limit
if acct.trades_today >= params['max_trades_per_day']:
return # Stop trading for today
# Daily loss limit
if acct.daily_pnl <= -(acct.equity * params['daily_loss_limit_pct']):
return # Stop trading for today
# Position limit
if acct.n_open >= params['max_concurrent']:
return # No more concurrent positions
Example: Bot Lifecycle
from genetic.bot import GeneticBot
from genetic.genome import Genome
from genetic.feed import MarketDataFeed
from genetic.engine import PaperTradingEngine
from kalshi_client import KalshiClient
import time
# Setup
client = KalshiClient()
feed = MarketDataFeed(client)
engine = PaperTradingEngine(feed)
# Create bot with momentum strategy
genome = Genome.random()
genome.signal_type = 0.2 # Momentum strategy
genome.bankroll_fraction = 0.02 # 2% per trade
genome.max_concurrent_positions = 0.25 # ~5 positions
bot = GeneticBot(genome, feed, engine, ["Finance"], bankroll=100.0)
print(f"Bot {bot.bot_id} starting")
print(f"Strategy: {bot.params['signal_type']}")
print(f"Bankroll: ${bot.account.cash:.2f}")
# Run for 100 ticks
for tick in range(100):
feed.update()
bot.tick()
if tick % 10 == 0:
acct = bot.account
print(f"Tick {tick}: {acct.n_open} open, {acct.n_settled} settled, "
f"ROI: {acct.roi_pct:+.2f}%")
time.sleep(30) # 30 second ticks
# Final stats
engine.settle_with_targeted_check()
acct = bot.account
print(f"\nFinal Results:")
print(f" Total trades: {acct.total_trades}")
print(f" Settled: {acct.n_settled}")
print(f" Win rate: {acct.win_rate:.1%}")
print(f" Realized P&L: ${acct.realized_pnl:+.2f}")
print(f" ROI: {acct.roi_pct:+.2f}%")