Skip to content

Repository files navigation

DeepKick cover

DeepKick

World Cup match-winner maker bot for the Algo Traders Club — a readable, forkable Kalshi bot with non-negotiable risk controls and DeepSeek-powered news context.

Fork of Kalshinator. DeepKick is a community fork of Kalshinator, the Algo Traders Club's canonical Kalshi reference bot. Same battle-tested kalshi/, risk/, db/, and engine/ layers — the fork point is strategies/ and data/, retargeted for 2026 World Cup match-winner markets. If you are new to the club stack, start with Kalshinator to learn the base; use DeepKick when you want the World Cup strategy and DeepSeek defaults out of the box.

30-second pitch

DeepKick is a World Cup–focused fork of the Kalshinator reference bot. It scans Kalshi Sports match-winner markets before kickoff, compares public team-strength (Elo-style) ratings to market prices, and posts resting maker limits when the modeled edge exceeds 5%. Optional DeepSeek via OpenRouter can nudge the binary Elo probability within a hard ±5 percentage-point cap — it never replaces the quantitative model.

DeepKick is not a live in-game latency bot (pro desks have feeds ~30 seconds faster than public APIs), an edge guarantee, or investment advice. It defaults to demo mode and DRY_RUN=true so you can learn the full lifecycle before risking real capital.

Tournament window: 2026 FIFA World Cup — June 11 through July 19 (US/Mexico/Canada, 48 teams, 104 matches).

Quickstart

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 (pure-Elo fallback runs without it)

# 3. Sanity-check credentials
uv run scripts/check_balance.py

# 4. Run one dry-run cycle (writes to data/deepkick.db)
uv run scripts/run_once.py

# 5. Start the backend (terminal 1)
uv run uvicorn deepkick.main:app --reload

# 6. Start the dashboard (terminal 2)
uv run streamlit run src/deepkick/dashboard/app.py

# Optional: open the static research/results dashboard instead
uv run streamlit run src/deepkick/dashboard/results_app.py

# Optional: refresh Kalshi fixture snapshot for the results dashboard
KALSHI_ENVIRONMENT=prod uv run scripts/snapshot_fixtures.py

See docs/dashboard.md for what each dashboard shows and how to read the backtest results.

Verify the API:

curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8000/status

We do not compete on speed

The research is explicit: reacting to live win-probability from public feeds is dead on arrival for a small bot. DeepKick targets soft pre-game lines on group-stage and knockout match-winner markets, modeled from public team-strength ratings. That is the teachable, defensible edge — not millisecond reaction.

Architecture

Single uvicorn process runs FastAPI, the APScheduler polling loop, and the SQLite writer. Streamlit is a separate read-mostly client.

flowchart TB
    subgraph Uvicorn["uvicorn process"]
        FastAPI["FastAPI\nmain.py"]
        Scheduler["APScheduler"]
        Loop["engine/loop.py\npoll -> evaluate -> risk -> execute -> log"]
        Kalshi["kalshi/client.py\nmarket data + orders"]
        Ratings["data/ratings.py\nElo seed / future live feed"]
        Strategy["strategies/worldcup.py\nElo + bounded DeepSeek context"]
        Risk["risk/\nKelly sizing + circuit breakers"]
        Repo["db/repository.py\nsingle SQLite writer"]

        Scheduler --> Loop
        Loop --> Kalshi
        Loop --> Ratings
        Loop --> Strategy
        Strategy -->|TradeSignals| Loop
        Loop -->|pre-trade checks| Risk
        Risk -->|approved orders only| Kalshi
        Loop --> Repo
        FastAPI --> Repo
        FastAPI --> Kalshi
    end

    DB[("data/deepkick.db")]
    Dashboard["Streamlit dashboard\napi_client.py only"]

    Repo --> DB
    Dashboard -->|HTTP| FastAPI
Loading

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.

Module boundaries (what forks touch)

Directory Fork? Role
strategies/, data/ Yes — fork points World Cup logic and ratings feeds
kalshi/, llm/, risk/, db/, engine/ No Infrastructure — do not bypass risk

World Cup strategy

worldcup (default) fetches Kalshi's KXWCGAME series directly via WORLDCUP_SERIES_TICKERS, rather than scanning every Sports series. Real match-winner tickers look like KXWCGAME-26JUN25TURUSA-USA (YES = USA beats Turkiye). The strategy intentionally skips companion TIE contracts and tournament-outright series such as KXMENWORLDCUP, because those require different models.

  1. Loads team Elo seeds from data/worldcup_elo_seed.json (v1 static fallback).
  2. Parses the KXWCGAME ticker into team codes and skips non-team outcomes such as TIE.
  3. Computes neutral-ground win probability from the Elo gap.
  4. Optionally asks OpenRouter (default model: deepseek/deepseek-chat) for a compact injury/lineup context check, then clamps any probability move to ±5 percentage points — not a full probability forecast.
  5. Emits a maker limit one tick inside the spread when edge > 5%.
flowchart LR
    Market["Kalshi binary market\nYES/NO"] --> Parse["Parse YES team\nfrom ticker"]
    Ratings["Elo ratings"] --> Baseline["Binary Elo baseline\np(YES)"]
    Parse --> Baseline
    Baseline --> Candidate["Best Elo candidate\nedge > MIN_EDGE"]
    Candidate --> LLM{"OpenRouter key set?"}
    LLM -->|No| Signal["TradeSignal\npure Elo"]
    LLM -->|Yes| DeepSeek["DeepSeek context check\nstructured JSON"]
    DeepSeek --> Haircut["Apply confidence haircut"]
    Haircut --> Clamp["Clamp final p(YES)\nto baseline +/- cap"]
    Clamp --> Reprice["Recompute YES/NO edge"]
    Reprice --> Signal
    Signal --> Risk["risk/\nlimits + sizing"]
Loading

Hybrid Model Honesty

Elo owns the probability. DeepSeek only receives the already-binary YES probability for the specific Kalshi contract being evaluated, then returns structured JSON through the same OpenRouter/Pydantic path used elsewhere. The final YES probability is clamped to baseline ± LLM_MAX_PROBABILITY_ADJUSTMENT (default ±5pp), and DeepSeek's self-reported confidence is haircut before it can reduce signal confidence. This is deliberate: LLMs are overconfident on prediction markets, so DeepKick treats narrative skill as context, not sizing authority. See docs/deepseek-sentiment-layer.md for the full design note.

Next obvious fork step: wire a live ratings feed in data/ratings.py (api-sports.io free tier, ClubElo export, etc.).

How to fork this for your own market

  1. Fork or clone this repository.

  2. Create src/deepkick/strategies/your_strategy.py implementing the Strategy ABC:

    from deepkick.strategies import register_strategy
    from deepkick.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=[...])
            ...
  3. Register the module in strategies/__init__.py (import it so @register_strategy runs).

  4. Point .env at your strategy: ACTIVE_STRATEGY=your_strategy

  5. Repoint the market filter: MARKET_CATEGORY_FILTER=CRYPTO (or whatever category you trade)

  6. Run uv run scripts/run_once.py — your signals still pass through risk/ before any order is placed.

See strategies/safe_compounder.py and strategies/worldcup.py for reference patterns.

Configuration

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 worldcup or safe_compounder, llm_directional, or your fork
MARKET_CATEGORY_FILTER Sports World Cup markets live here; Kalshi's category filter is case-sensitive
WORLDCUP_SERIES_TICKERS KXWCGAME Comma-separated World Cup game series to fetch directly
EXCLUDED_MARKET_CATEGORIES ENTERTAINMENT,MENTIONS Sports is not excluded — required for this fork
OPENROUTER_MODEL deepseek/deepseek-chat Config string only — swap without code changes
LLM_MAX_PROBABILITY_ADJUSTMENT 0.05 Hard cap on how far DeepSeek can move the Elo baseline
DATABASE_PATH ./data/deepkick.db Auto-created on first run

API endpoints

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.

Testing

uv run pytest                  # all mocked HTTP — safe default
uv run pytest -m live          # opt-in live API tests (demo credentials)
uv run scripts/backtest.py     # pure-Elo historical seed backtest; no credentials

Read-only Kalshi diagnostics:

KALSHI_ENVIRONMENT=prod uv run scripts/list_series.py "world cup"
KALSHI_ENVIRONMENT=prod uv run scripts/inspect_markets.py KXWCGAME KXMENWORLDCUP

Where to go from here (intentional v1 gaps)

These are documented gaps, not oversights — reasonable territory for your fork:

  • Live team-strength ratings feed (static JSON seed ships in v1)
  • WebSocket order book streaming
  • Multi-model LLM consensus / ensemble voting
  • Cross-venue arbitrage (Polymarket, PMXT, etc.)
  • Historical backtesting framework
  • Additional World Cup series models (BTTS, group qualification, tournament outrights)
  • Database migrations / Postgres swap
  • Telegram / Discord control UI
  • Live in-game reaction (deliberately out of scope)

Disclaimer

DeepKick is an educational reference implementation maintained by the Algo Traders Club. It is not investment advice. Past performance of any bundled strategy 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.

License

MIT — see LICENSE. Copyright Algo Traders Club.

Links

About

DeepKick World Cup 2026 Trading Agent on Kalshi ⚽️

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages