Overview
Therunner.py module contains the main evolution loop that orchestrates the genetic algorithm training system. It manages the infinite evolution cycle, coordinates trading periods, handles crash recovery, and persists results.
Functions
run_evolution()
Main entry point for the infinite evolution loop. Behavior:- Sets up logging with
setup_logging() - Connects to Kalshi API
- Starts market data feed
- Waits for initial market data
- Attempts to resume from saved state or starts fresh
- Runs infinite evolution loop (Ctrl+C to stop gracefully)
- Each iteration runs one complete generation
- Automatically saves state after each generation
- Resumes from latest checkpoint on restart
- Updates hall of fame with top performers
- Evolves population for next generation
- Press Ctrl+C to interrupt
- Current generation state is saved
- Resume anytime by running again
main()
CLI entry point that simply callsrun_evolution().
Internal Functions
_run_generation()
Run a single generation: create bots, trade, evaluate, evolve.Logger instance from setup_logging()
Active market data feed
Population of genomes for this generation
Current generation number
List of market categories (refreshed each generation)
Tuple of (next_generation_genomes, next_generation_number)
-
Initialization
- Refresh market categories from feed
- Create fresh
PaperTradingEngine - Instantiate
GeneticBotfor each genome
-
Trading Period
- Duration:
GENERATION_DURATION_SECONDS(typically 24 hours) - Tick interval:
TICK_INTERVAL_SECONDS(typically 30s) - Each tick:
- Settle completed markets
- Each bot evaluates and trades
- Periodic progress logging
- Periodic checkpoints
- Duration:
-
Settlement Wait
- After trading period, wait up to
SETTLEMENT_WAIT_HOURSfor positions to settle - Polls every
SETTLEMENT_WAIT_POLL_SECONDS - Force-closes any remaining positions as losses if timeout
- After trading period, wait up to
-
Evaluation & Evolution
- Calculate fitness for all bots
- Save generation state
- Update hall of fame
- Evolve new population using
evolve()
- Can be interrupted (Ctrl+C) at any point
- Saves current state before exiting
- Handles interrupts during trading or settlement
_save_and_log()
Evaluate fitness, save state, update hall of fame, log results.Logger instance
Generation number
All bots in generation
Number of ticks completed
- Evaluate fitness (ROI%) for all bots
- Compute generation statistics
- Log generation summary with leaderboard
- Save complete generation state to JSON
- Update hall of fame with top 10 performers
Generation Lifecycle
A complete generation follows this timeline:Phase 1: Initialization (< 1 minute)
- Refresh market categories
- Create trading engine
- Instantiate all bots with genomes
Phase 2: Trading Period (configurable, default 24 hours)
Phase 3: Settlement Wait (0-2 hours)
- Wait for open positions to settle naturally
- Poll for settlements every 60 seconds
- Force-close unsettled positions after timeout
Phase 4: Evaluation & Evolution (< 1 minute)
- Calculate fitness scores
- Generate statistics and leaderboard
- Save state and update hall of fame
- Create next generation via selection, crossover, mutation
Phase 5: Next Generation
- Increment generation number
- Loop back to Phase 1
Configuration
The runner uses these constants fromgenetic.config:
Number of bots per generation
Starting capital for each bot (USD)
Trading period length (default: 24 hours)
Seconds between trading ticks
Maximum time to wait for positions to settle
Polling interval during settlement wait
Ticks between progress logs (default: every 15 min)
Ticks between checkpoints (default: every 30 min)
Ticks between targeted settlement checks (default: every hour)
Recovery & Resume
The runner automatically handles crash recovery:- Loads
latest.jsonto find most recent generation - Restores all genomes from that generation
- Starts the next generation (does not replay)
- Mid-generation crashes: restart from beginning of next generation
Usage Examples
Basic Start
With Custom Configuration
Monitoring Progress
Integration with Other Scripts
Error Handling
The runner handles various error scenarios:No Markets Available
Tick Errors
Keyboard Interrupts
Performance Considerations
Resource Usage:- Memory: ~50-100 MB for 50 bots
- CPU: Low (mostly sleeping between ticks)
- Network: API calls every
TICK_INTERVAL_SECONDS - Disk: ~10 MB per generation (state files)
- Increase
TICK_INTERVAL_SECONDSto reduce API calls - Decrease
POPULATION_SIZEfor faster generations - Adjust
GENERATION_DURATION_SECONDSbased on market activity - Run on a server for 24/7 operation
- Avoid race conditions
- Simplify debugging
- Respect API rate limits
- Running multiple independent evolutions in parallel
- Using different configuration parameters
- Merging hall of fame results post-hoc