The Bot Ledger
FR

Accueil / Guides

Connecter un bot à Kalshi en cinq étapes

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

Des baies de serveurs dans un centre de données éclairé en bleu
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()