Reference trading bot for the Algo Traders Club — a readable, forkable Kalshi bot with non-negotiable risk controls.
Kalshinator is the canonical starting point for Algo Traders Club members who want to trade Kalshi with Python: authenticate correctly, size positions conservatively, log every decision to SQLite, and swap in your own market logic without touching auth, execution, or risk code.
Kalshinator is not a profit-maximizing black box, a backtester, or investment advice. It ships with a simple default strategy (Safe Compounder) and an optional LLM example — both are teaching artifacts, not edge guarantees. It defaults to demo mode and DRY_RUN=true so you can learn the full lifecycle before risking real capital.
Requirements: Python 3.12+, uv, Kalshi demo API credentials (Kalshi docs).
# 1. Install dependencies
uv sync --dev
# 2. Configure environment
cp .env.example .env
# Edit .env — at minimum set:
# KALSHI_API_KEY_ID
# KALSHI_PRIVATE_KEY_PATH (path to your demo .pem file)
# OpenRouter key is optional (only needed for ACTIVE_STRATEGY=llm_directional)
# 3. Sanity-check credentials
uv run scripts/check_balance.py
# 4. Run one dry-run cycle (writes to data/kalshinator.db)
uv run scripts/run_once.py
# 5. Start the backend (terminal 1)
uv run uvicorn kalshinator.main:app --reload
# 6. Start the dashboard (terminal 2)
uv run streamlit run src/kalshinator/dashboard/app.pyVerify the API:
curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8000/statusSingle uvicorn process runs FastAPI, the APScheduler polling loop, and the SQLite writer. Streamlit is a separate read-mostly client.
┌─────────────────────────────────────────────────────────────────┐
│ uvicorn process (one) │
│ │
│ APScheduler ──► engine/loop.py │
│ │ │
│ ├─► kalshi/client.py (fetch markets, etc.) │
│ ├─► strategies/*.py (emit TradeSignals) │
│ ├─► risk/ (size + breakers) │
│ ├─► kalshi/client.py (place order) │
│ └─► db/repository.py (WRITE ONLY) │
│ │
│ FastAPI main.py ◄── reads repository + kalshi pass-through │
└───────────────────────────────┬─────────────────────────────────┘
│ HTTP
▼
┌───────────────────────┐
│ dashboard/ (Streamlit) │
│ api_client.py only │
└───────────────────────┘
data/kalshinator.db ◄── single writer (engine/loop.py)
Cycle pipeline: poll → evaluate → risk → execute → log/persist
Every cycle writes a Cycle row; every order attempt (including dry-run) writes an Order row; every balance check writes a BalanceSnapshot row. The dashboard reads history through FastAPI — it never opens the .db file directly.
| Directory | Fork? | Role |
|---|---|---|
strategies/ |
Yes — only fork point | Market-specific signal logic |
kalshi/, llm/, risk/, db/, engine/ |
No | Infrastructure — do not bypass risk |
-
Fork or clone this repository.
-
Create
src/kalshinator/strategies/your_strategy.pyimplementing theStrategyABC:from kalshinator.strategies import register_strategy from kalshinator.strategies.base import Strategy, StrategyResult @register_strategy("your_strategy") class YourStrategy(Strategy): name = "your_strategy" async def evaluate(self, markets): # Your logic here — return StrategyResult(signals=[...]) ...
-
Register the module in
strategies/__init__.py(import it so@register_strategyruns). -
Point
.envat your strategy:ACTIVE_STRATEGY=your_strategy -
Repoint the market filter:
MARKET_CATEGORY_FILTER=CRYPTO(or whatever category you trade) -
Run
uv run scripts/run_once.py— your signals still pass throughrisk/before any order is placed.
See strategies/crypto_threshold.py for a minimal placeholder fork example (returns no signals — safe to leave registered).
All settings flow through .env — see .env.example. Highlights:
| Variable | Default | Notes |
|---|---|---|
DRY_RUN |
true |
Hot-reloaded — no restart needed for /status badge |
KALSHI_ENVIRONMENT |
demo |
Hot-reloaded |
ACTIVE_STRATEGY |
safe_compounder |
or llm_directional, or your fork |
MARKET_CATEGORY_FILTER |
WEATHER |
Kalshi series category |
DATABASE_PATH |
./data/kalshinator.db |
Auto-created on first run |
| Method | Path | Purpose |
|---|---|---|
| GET | /health |
Liveness |
| GET | /status |
Strategy, dry-run, circuit breakers |
| GET | /balance, /positions |
Kalshi pass-through |
| GET | /balance/history, /cycles, /orders |
SQLite history |
| POST | /cycle/run, /cycle/pause, /cycle/resume |
Manual control |
No authentication in v1 — put behind a reverse proxy before exposing publicly.
uv run pytest # all mocked HTTP — safe default
uv run pytest -m live # opt-in live API tests (demo credentials)These are documented gaps, not oversights — reasonable territory for your fork:
- WebSocket order book streaming
- Multi-model LLM consensus / ensemble voting
- Cross-venue arbitrage (Polymarket, PMXT, etc.)
- Historical backtesting framework (v1 captures the SQLite history needed; building the backtester is fork territory)
- Database migrations / Postgres swap (signal you've outgrown single-writer SQLite)
- Telegram / Discord control UI
- Auth-gated or multi-page Streamlit dashboard
- Weather-specific data ingestion (Open-Meteo ensembles)
- Mentions-market base-rate builders (SEC EDGAR transcripts)
Kalshinator is an educational reference implementation maintained by the Algo Traders Club. It is not investment advice. Past performance of the Safe Compounder strategy (or any bundled example) is not a guarantee of future results. The bot defaults to demo mode and DRY_RUN=true for a reason — understand the code and test thoroughly before trading live capital.
MIT — see LICENSE. Copyright Algo Traders Club.
- Algo Traders Club
- Kalshi API docs
- Product requirements: docs/kalshinator-prd.md
