The Bot Ledger
FR

Accueil / Guides

Guide API Kalshi : connecter un bot de trading en 5 étapes

L'API Kalshi pour un bot, en Python : requêtes signées, forme du carnet d'ordres, passage et annulation d'ordres, exécutions et historique gratuit en chandeliers.

Server racks in a data center lit blue
Auth
Id de clé API plus une signature RSA sur le timestamp, la méthode et le chemin, à chaque requête.
Lecture
Une API REST pour les marchés, les carnets, les chandeliers ; un websocket pour les exécutions et les deltas du carnet.
Trading
Ordres limite en cents ou en dollars par contrat ; le carnet est en contrats.
Frais taker
0.07 x contracts x p x (1-p), arrondi au cent supérieur par ordre. Les makers ne paient rien sur presque toutes les séries.
Règlement
Publié par l'exchange ; les marchés crypto se règlent sur une moyenne que l'exchange diffuse au fur et à mesure qu'elle s'accumule.
Géographie
Comptes américains. Les programmes de récompense sont fermés aux utilisateurs hors États-Unis.
Docs
docs.kalshi.com

Cinq étapes, volontairement simplifiées. Les chemins d'endpoint suivent la référence publique au moment de la rédaction ; vérifiez la documentation avant de vous y fier.

  1. Signer chaque requête

    Générez une clé API dans les paramètres du compte ; vous obtenez un id de clé et un fichier de clé privée. Chaque requête porte l'id, un timestamp en millisecondes, et une signature RSA-PSS sur le timestamp, la méthode HTTP et le chemin.

    import time, base64, requests
    from cryptography.hazmat.primitives import hashes, serialization
    from cryptography.hazmat.primitives.asymmetric import padding
    
    BASE = "https://api.elections.kalshi.com/trade-api/v2"
    key = serialization.load_pem_private_key(open("kalshi.pem", "rb").read(), password=None)
    
    def headers(method, path):
        ts = str(int(time.time() * 1000))
        msg = (ts + method + "/trade-api/v2" + path).encode()
        sig = key.sign(msg, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH), hashes.SHA256())
        return {"KALSHI-ACCESS-KEY": KEY_ID, "KALSHI-ACCESS-SIGNATURE": base64.b64encode(sig).decode(), "KALSHI-ACCESS-TIMESTAMP": ts}
  2. Lister les marchés d'une série

    r = requests.get(f"{BASE}/markets", params={"series_ticker": "KXBTC15M", "status": "open"}, headers=headers("GET", "/markets"))
    markets = r.json()["markets"]
    ticker = markets[0]["ticker"]
  3. Lire le carnet d'ordres

    L'endpoint du carnet a changé de forme : la version la plus récente liste le prix en dollars et la taille par niveau. Un parseur écrit pour les anciens tableaux en cents renvoie une profondeur nulle sans erreur.

    path = f"/markets/{ticker}/orderbook"
    ob = requests.get(BASE + path, headers=headers("GET", path)).json()["orderbook_fp"]
    yes_bids = ob["yes_dollars"]      # [[price_dollars, size], ...]
    no_bids  = ob["no_dollars"]
    best_yes_ask = 1 - float(no_bids[-1][0])   # un ask YES est le miroir du meilleur bid NO

    L'échelle peut être croisée (meilleur bid YES plus meilleur bid NO au-dessus de 1.00) sur une part notable des instantanés. Protégez-vous contre ce cas avant de coter.

  4. Passer et annuler un ordre

    order = {"ticker": ticker, "action": "buy", "side": "yes", "type": "limit",
             "count": 20, "yes_price": 85, "client_order_id": "win-1757500800"}
    r = requests.post(f"{BASE}/portfolio/orders", json=order, headers=headers("POST", "/portfolio/orders"))
    order_id = r.json()["order"]["order_id"]
    
    requests.delete(f"{BASE}/portfolio/orders/{order_id}", headers=headers("DELETE", f"/portfolio/orders/{order_id}"))
  5. Lire les exécutions et les règlements

    fills = requests.get(f"{BASE}/portfolio/fills", headers=headers("GET", "/portfolio/fills")).json()["fills"]
    settled = requests.get(f"{BASE}/portfolio/settlements", headers=headers("GET", "/portfolio/settlements")).json()

    Utilisez le websocket pour les exécutions dans un bot en réel ; l'interrogation de l'endpoint des ordres est limitée en débit.

L'historique gratuit dont personne ne parle

L'endpoint candlesticks renvoie l'historique du bid, de l'ask et du volume de n'importe quel marché à l'intervalle choisi, depuis sa cotation. Pour la recherche, il remplace un logger que vous n'avez pas encore écrit.

path = f"/series/KXBTC15M/markets/{ticker}/candlesticks"
c = requests.get(BASE + path, params={"start_ts": t0, "end_ts": t1, "period_interval": 1}, headers=headers("GET", path)).json()