关于 kalshi
通过 Kalshi API 查询和交易预测市场的技能,涵盖市场发现、定价、订单簿、实时数据及需认证的账户操作。
主要功能
- 01浏览系列、事件和市场
- 02查询订单簿与交易记录
- 03获取蜡烛图和预测历史
- 04管理需认证的订单与账户
- 05查询交易所及比赛实时数据
适用场景
- 01查找体育系列中的市场
- 02查看价格和订单簿深度
- 03创建或修改市场订单
- 04检查历史市场活动
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ starchild-ai-agent/ official-skills --skill kalshi安装后在 Claude Code 中输入/kalshi确认已加载。
详细介绍
Kalshi API
交易并查询首个受 CFTC 监管的预测市场交易所。针对真实世界事件的二元是/否合约,价格为 1–99 美分。
基础 URL: https://external-api.kalshi.com/trade-api/v2
演示 URL: https://external-api.demo.kalshi.co/trade-api/v2
在 https://kalshi.com/account/api-keys 获取 API 密钥(需要 Premier 或 Market Maker 级别)
核心概念
层级:系列 > 事件 > 市场
- 系列 — 周期性事件模板(例如,“月度就业报告”“每周首次申领失业救济人数”)
- 事件 — 系列中的具体实例(例如,“2026 年 5 月就业报告”)
- 市场 — 事件中的单个二元结果(例如,“新增就业人数会超过 20 万吗?”)
二元合约定价
- 价格以美分计(1–99),代表隐含概率
- 是合约价格为 65 美分 = 市场隐含概率为 65%
- 价格为 X 的是买价等同于价格为 (100 - X) 的否卖价——订单簿仅显示是买价和否买价
- 结算:若结果为是,则支付 1.00 美元(100 美分);若为否,则支付 0 美元
- 所有货币值(余额、价格、结算金额)均以美分计
代码格式
- 系列:
KXBTC、KXJOBLESS、KXINX - 事件:
KXBTC-25MAY30(系列 + 日期) - 市场:
KXBTC-25MAY30-T100000(事件 + 阈值/结果)
体育比赛代码遵循不同的格式:{SERIES}-{YYMONDD}{TEAM1}{TEAM2}-{TEAM}
- 示例:
KXNHLGAME-25MAY12EDMORL-EDM(NHL,2025 年 5 月 12 日,埃德蒙顿对奥兰多,埃德蒙顿获胜) - 每场比赛事件都有两个互斥的是市场——每支球队各一个
关键:基于系列的市场导航
**体育、选举或任何基于系列的类别都不要使用 /markets?keyword=。**它只会显示多场比赛的串关组合,而非实际的比赛级市场。搜索“NHL”“Fulham”“Premier League”等内容会返回零条或无关结果。
**始终按以下层级导航:系列 → 事件 → 市场。**比赛级市场位于系列/事件层级下,必须通过 /events?series_ticker=KXXX 访问。此外,/markets/{ticker} 对比赛市场可能返回 404——买卖价只会出现在事件端点的响应中(/events/{event_ticker} 搭配 with_nested_markets=true)。
此模式适用于所有基于系列的类别,不只是体育:
- 体育比赛 — NHL、NBA、NFL、MLB、EPL 等
- 政治选举 — 多候选人事件中的单个候选人市场
- 特定公司市场 — 系列中的财报、CEO 变更
- 周期性经济数据 — 就业报告、首次申领失业救济人数、CPI 等
已知体育系列代码:
| 体育项目 | 系列代码 | 示例 |
|---|---|---|
| NHL | KXNHLGAME | KXNHLGAME-25MAY12EDMORL |
| NBA | KXNBAGAME | KXNBAGAME-25MAY12BOSLAL |
| NFL | KXNFLGAME | KXNFLGAME-25SEP07KCDET |
| MLB | KXMLBGAME | KXMLBGAME-25MAY12NYYLAD |
| EPL(Premier League) | KXEPLGAME | KXEPLGAME-25MAY12FULARS |
体育赛事的正确工作流:
# 1. List open games for a sport
curl -s "https://external-api.kalshi.com/trade-api/v2/events?series_ticker=KXNHLGAME&status=open&with_nested_markets=true"
# 2. Get specific game with live bid/ask
curl -s "https://external-api.kalshi.com/trade-api/v2/events/KXNHLGAME-25MAY12EDMORL?with_nested_markets=true"
# WRONG — do not do this:
# curl -s "https://external-api.kalshi.com/trade-api/v2/markets?keyword=NHL" ← returns parlays, not games
如何调用
Kalshi 使用 RSA 密钥对签名身份验证。经过身份验证的请求需要以下三个标头:
| 标头 | 值 |
|---|---|
KALSHI-ACCESS-KEY | API 密钥 ID($KALSHI_ACCESS_KEY) |
KALSHI-ACCESS-SIGNATURE | timestamp + method + path 的 RSA-PSS 签名 |
KALSHI-ACCESS-TIMESTAMP | Unix 时间戳(毫秒) |
公开 GET 端点(市场、事件、订单簿)无需身份验证标头即可调用。
# Public endpoint — no auth needed
curl -s "https://external-api.kalshi.com/trade-api/v2/markets?limit=10&status=open"
对于需要身份验证的端点,请直接使用 RSA-PSS 签名(不要使用 kalshi_python SDK——它无法正常工作):
import os, time, base64, requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.backends import default_backend
from dotenv import load_dotenv
load_dotenv('/data/workspace/.env')
BASE_URL = "https://api.elections.kalshi.com"
def kalshi_headers(method: str, path: str) -> dict:
import re
raw = os.environ["KALSHI_PRIVATE_KEY"]
# Decode literal escape sequences first (some input channels save '\n' as
# two chars backslash+n instead of a real newline).
raw = (raw.replace('\\r\\n', '\n').replace('\\n', '\n')
.replace('\\r', '\n').replace('\\t', ' '))
# Strip PEM markers if present, then strip ALL whitespace and rewrap.
body = re.sub(r'-----BEGIN[^-]+-----', '', raw)
body = re.sub(r'-----END[^-]+-----', '', body)
body = re.sub(r'\s+', '', body)
wrapped = '\n'.join(body[i:i+64] for i in range(0, len(body), 64))
pem = f"-----BEGIN RSA PRIVATE KEY-----\n{wrapped}\n-----END RSA PRIVATE KEY-----\n"
private_key = serialization.load_pem_private_key(pem.encode(), password=None, backend=default_backend())
ts = str(int(time.time() * 1000))
msg = (ts + method + path).encode() # path must NOT include query string
sig = private_key.sign(msg, padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH), hashes.SHA256())
return {
"KALSHI-ACCESS-KEY": os.environ["KALSHI_ACCESS_KEY"].strip(),
"KALSHI-ACCESS-TIMESTAMP": ts,
"KALSHI-ACCESS-SIGNATURE": base64.b64encode(sig).decode(),
"Content-Type": "application/json"
}
path = "/trade-api/v2/portfolio/balance"
resp = requests.get(BASE_URL + path, headers=kalshi_headers("GET", path))
print(resp.json()) # {"balance": 5000, ...} — balance is in cents
签名注意事项:
- 使用 PSS,而非 PKCS1v15——PKCS1v15 填充会返回 401。必须使用 PSS 和 SHA256。
- 签名前去掉查询字符串——签名仅根据不带查询字符串的路径计算(例如
/trade-api/v2/portfolio/balance),而不是/trade-api/v2/portfolio/balance?param=value。包含查询字符串会返回 401。 - 密钥环境变量格式——
KALSHI_PRIVATE_KEY接受以下任意格式:原始 base64 正文、带真实换行符的完整 PEM,或换行符折叠为空白字符的完整 PEM(通过网页表单粘贴时很常见)。辅助函数会自动规范化所有格式。为确保最稳妥的存储方式,请在.env中保存为带\n转义符的双引号多行 PEM,这样 python-dotenv 会将其还原为包含真实换行符的 PEM 字符串。
API 规范
完整的 OpenAPI 规范:https://docs.kalshi.com/openapi.yaml
意图路由
将用户意图映射到合适的端点。所有路径均相对于基本 URL。
事件
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /events | limit (1-200), cursor, status, series_ticker, with_nested_markets | 列出事件(不包括多变量事件) |
| GET | /events/{event_ticker} | event_ticker, with_nested_markets | 获取指定事件 |
| GET | /events/{event_ticker}/metadata | event_ticker | 仅获取事件元数据 |
| GET | /events/multivariate | limit, cursor, series_ticker, collection_ticker, with_nested_markets | 列出多变量(组合)事件 |
市场
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /markets | limit, cursor, status, ticker, event_ticker, series_ticker, min_close_ts, max_close_ts | 列出/筛选市场 |
| GET | /markets/{ticker} | ticker | 获取指定市场的详情 |
| GET | /markets/{ticker}/orderbook | ticker, depth | 当前订单簿(yes 买单 + no 买单) |
| GET | /markets/orderbooks | tickers (array, max 100) | 批量获取订单簿 |
| GET | /markets/trades | ticker, limit, cursor, min_ts, max_ts | 获取各市场的交易记录 |
K 线
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /series/{series_ticker}/markets/{ticker}/candlesticks | series_ticker, ticker, start_ts, end_ts, period_interval | 市场级 K 线 |
| GET | /series/{series_ticker}/events/{ticker}/candlesticks | series_ticker, ticker, start_ts, end_ts, period_interval | 汇总的事件级 K 线 |
| GET | /markets/candlesticks | market_tickers, start_ts, end_ts, period_interval | 批量获取 K 线 |
period_interval 的取值:1(1 分钟)、60(1 小时)、1440(1 天)
预测与实时数据
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /series/{series_ticker}/events/{ticker}/forecast_percentile_history | percentiles (0-10000), start_ts, end_ts, period_interval | 历史预测百分位数 |
| GET | /live_data/milestone/{milestone_id} | milestone_id, include_player_stats | 实时里程碑数据 |
| GET | /live_data/batch | milestone_ids (array, max 100), include_player_stats | 批量获取实时数据 |
| GET | /live_data/game-stats/{milestone_id} | milestone_id | 逐场比赛统计数据(橄榄球、篮球、足球、冰球、棒球) |
系列
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /series/{series_ticker} | series_ticker、include_volume | 获取系列模板 |
| GET | /series | category、tags、include_volume、min_updated_ts | 列出所有系列 |
交易所信息
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /exchange/status | — | 当前交易所状态 |
| GET | /exchange/schedule | — | 运营时间 |
| GET | /exchange/announcements | — | 平台公告 |
| GET | /exchange/user_data_timestamp | — | 数据同步时间戳 |
| GET | /series/fee_changes | series_ticker、show_historical | 费用变更历史 |
搜索与发现
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /search/tags_by_categories | — | 按系列类别整理的标签 |
| GET | /search/filters_by_sport | — | 按体育项目整理的筛选条件 |
订单(需认证)
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /portfolio/orders | ticker、event_ticker、status、limit、cursor、subaccount | 列出用户订单 |
| GET | /portfolio/orders/{order_id} | order_id | 获取指定订单 |
| POST | /portfolio/orders | 正文:ticker、action、side、type、count、yes_price/no_price | 创建订单 |
| DELETE | /portfolio/orders/{order_id} | order_id、subaccount | 取消订单 |
| POST | /portfolio/orders/{order_id}/amend | order_id,正文:新的 count/price | 修改订单 |
| POST | /portfolio/orders/{order_id}/decrease | order_id,正文:减少数量 | 减少订单数量 |
| POST | /portfolio/orders/batched | 正文:订单数组 | 批量创建(最大数量随等级而异) |
| DELETE | /portfolio/orders/batched | 正文:订单 ID 数组 | 批量取消 |
| GET | /portfolio/orders/queue_positions | market_tickers、event_ticker、subaccount | 所有未成交订单的排队位置 |
| GET | /portfolio/orders/{order_id}/queue_position | order_id | 指定订单的排队位置 |
订单 V2 — 事件市场订单(需认证,定点数)
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| POST | /portfolio/events/orders | 正文:事件代码、市场方向、价格(定点数)、数量 | 创建 V2 订单 |
| POST | /portfolio/events/orders/batched | 正文:V2 订单数组 | 批量创建 V2 订单 |
| DELETE | /portfolio/events/orders/{order_id} | order_id、subaccount | 取消 V2 订单 |
| DELETE | /portfolio/events/orders/batched | 正文:订单 ID 数组 | 批量取消 V2 订单 |
| POST | /portfolio/events/orders/{order_id}/amend | order_id,正文:新的数量/价格 | 修改 V2 订单 |
| POST | /portfolio/events/orders/{order_id}/decrease | order_id,正文:新的剩余数量 | 减少 V2 订单数量 |
订单组(需认证)
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /portfolio/order_groups | subaccount | 列出所有订单组 |
| POST | /portfolio/order_groups/create | 正文:合约限额 | 创建订单组 |
| GET | /portfolio/order_groups/{id} | id、subaccount | 获取指定订单组 |
| DELETE | /portfolio/order_groups/{id} | id、subaccount | 删除订单组并取消所有订单 |
| PUT | /portfolio/order_groups/{id}/limit | id,正文:新的限额 | 更新合约限额 |
| PUT | /portfolio/order_groups/{id}/trigger | id、subaccount | 触发订单组(取消所有订单) |
| PUT | /portfolio/order_groups/{id}/reset | id、subaccount | 重置已匹配合约计数器 |
投资组合(需身份验证)
| 方法 | 端点 | 主要参数 | 说明 |
|---|---|---|---|
| GET | /portfolio/balance | subaccount | 余额和投资组合价值(以美分为单位) |
| GET | /portfolio/positions | cursor, limit, count_filter, ticker, event_ticker, subaccount | 用户持仓 |
| GET | /portfolio/fills | ticker, order_id, min_ts, max_ts, limit, cursor, subaccount | 所有成交记录 |
| GET | /portfolio/settlements | limit, cursor, ticker, event_ticker, min_ts, max_ts, subaccount | 结算历史记录 |
| GET | /portfolio/deposits | limit, cursor | 存款历史记录 |
| GET | /portfolio/withdrawals | limit, cursor | 提款历史记录 |
| GET | /portfolio/summary/total_resting_order_value | — | 静置订单总价值(仅限 FCM) |
子账户(需身份验证——机构/做市商)
| 方法 | 端点 | 主要参数 | 说明 |
|---|---|---|---|
| POST | /portfolio/subaccounts | — | 创建子账户(最多 32 个) |
| POST | /portfolio/subaccounts/transfer | Body:from、to、amount | 在子账户之间转账 |
| GET | /portfolio/subaccounts/balances | — | 所有子账户余额 |
| GET | /portfolio/subaccounts/transfers | limit, cursor | 转账历史记录 |
| GET | /portfolio/subaccounts/netting | — | 净额结算设置 |
| PUT | /portfolio/subaccounts/netting | Body:subaccount、enabled | 更新净额结算设置 |
RFQ — 报价请求(需身份验证)
| 方法 | 端点 | 主要参数 | 说明 |
|---|---|---|---|
| GET | /communications/rfqs | cursor, limit(1-100), event_ticker, market_ticker, status, user_filter | 列出 RFQ |
| POST | /communications/rfqs | Body:market ticker、side、count | 创建 RFQ(最多 100 个未完成项) |
| GET | /communications/rfqs/{rfq_id} | rfq_id | 获取指定 RFQ |
| DELETE | /communications/rfqs/{rfq_id} | rfq_id | 删除 RFQ |
| GET | /communications/quotes | cursor, limit(1-500), event_ticker, market_ticker, status, rfq_id | 列出报价 |
| POST | /communications/quotes | Body:RFQ ID、side、price、count | 创建报价响应 |
| GET | /communications/quotes/{quote_id} | quote_id | 获取指定报价 |
| DELETE | /communications/quotes/{quote_id} | quote_id | 删除报价 |
| PUT | /communications/quotes/{quote_id}/accept | quote_id | 接受报价 |
| PUT | /communications/quotes/{quote_id}/confirm | quote_id | 确认报价(启动执行计时器) |
| GET | /communications/id | — | 获取用户的通信 ID |
API 密钥(需身份验证)
| 方法 | 端点 | 主要参数 | 说明 |
|---|---|---|---|
| GET | /api_keys | — | 列出所有 API 密钥 |
| POST | /api_keys | Body:public key、name | 使用用户 RSA 公钥创建密钥 |
| POST | /api_keys/generate | Body:name | 自动生成密钥对 |
| DELETE | /api_keys/{api_key} | api_key | 删除 API 密钥 |
账户(需身份验证)
| 方法 | 端点 | 主要参数 | 说明 |
|---|---|---|---|
| GET | /account/limits | — | API 层级速率限制 |
| GET | /account/endpoint_costs | — | 非默认端点的令牌成本 |
历史数据
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /historical/cutoff-timestamps | — | 实时数据与历史数据之间的边界 |
| GET | /historical/markets/{ticker} | ticker | 特定的历史市场 |
| GET | /historical/markets | 互斥筛选条件 | 历史市场 |
| GET | /historical/markets/{ticker}/candlesticks | ticker、start_ts、end_ts、period_interval | 已归档的蜡烛图数据 |
| GET | /historical/orders | 筛选条件 | 已归档的订单 |
| GET | /historical/fills | 筛选条件 | 所有历史成交 |
| GET | /historical/trades | 筛选条件 | 所有历史交易 |
里程碑与结构化目标
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /milestones/{id} | id | 特定里程碑 |
| GET | /milestones | RFC3339 开始日期筛选条件 | 里程碑列表 |
| GET | /structured-targets/{id} | id | 特定结构化目标 |
| GET | /structured-targets | 分页(最多 2000 条) | 目标列表 |
多变量集合
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /multivariate/collections | — | 多变量事件集合列表 |
| GET | /multivariate/collections/{ticker} | ticker | 特定集合 |
| POST | /multivariate/collections/{ticker}/markets | ticker、请求体:市场参数 | 在集合中创建市场(每周限 5000 个) |
激励
| 方法 | 端点 | 主要参数 | 描述 |
|---|---|---|---|
| GET | /incentives | 可选筛选条件 | 激励计划列表 |
速率限制
基于令牌的系统,额度根据 API 层级(Standard、Premier、Market Maker)动态调整。
| 端点类型 | 默认成本 |
|---|---|
| 大多数端点 | 10 个令牌 |
| GetOrder | 2 个令牌 |
| CancelOrder | 2 个令牌 |
| CreateQuote / DeleteQuote | 2 个令牌 |
| 批量操作 | N × 每项成本 |
使用 GET /account/limits 查看您的限额。批量操作的最大规模根据您所在层级的写入额度调整。
分页
所有列表端点均采用基于游标的分页。响应中包含 cursor 字段;将其作为查询参数传回,即可获取下一页。
| 参数 | 描述 |
|---|---|
limit | 每页最多返回的结果数(因端点而异,通常为 1-200) |
cursor | 上一条响应中的不透明游标,用于获取下一页 |
WebSocket 通道
WebSocket 连接地址为 wss://external-api.kalshi.com/trade-api/ws/v2(握手时需要身份验证)。
公开通道:
- 市场行情代码 — 价格、交易量、未平仓量更新
- 公开交易 — 交易通知
- 市场与事件生命周期 — 状态变更、新市场/事件
- 多变量市场与事件生命周期 — MVE 状态变更
已验证身份的通道:
- 用户订单 — 订单创建/更新通知
- 用户成交 — 成交通知
- 市场持仓 — 实时持仓更新
- 订单组更新 — 生命周期与限额通知
- 通信 — RFQ 和报价通知
- 订单簿更新 — 价格档位增量变更
订单字段参考
| 字段 | 值 | 描述 |
|---|---|---|
action | buy、sell | 买入或卖出合约 |
side | yes、no | 结果方向 |
type | limit、market | 订单类型 |
count | 整数 | 合约数量 |
yes_price | 1-99(美分) | yes 方向的价格 |
no_price | 1-99(美分) | no 方向的价格 |
expiration_ts | Unix 时间戳 | 可选的订单过期时间 |
sell_position_floor | 整数 | 卖出时保留的最低持仓量 |
buy_max_cost | 整数(美分) | 市价买入的最高总成本 |
安全注意事项
- 所有价格的单位都是美分(1–99)。价格为 65 表示每份合约 0.65 美元,而不是 65 美元。
- **余额的单位是美分。**10000 = 100.00 美元。
POST /portfolio/orders会在生产环境中提交真实订单。下单前务必核实 ticker、方向和价格。- 批量操作以原子方式执行——要么全部成功,要么全部失败。
- 提供演示环境
https://external-api.demo.kalshi.co/trade-api/v2,可供无风险测试。 - 下单前,务必与用户确认市场 ticker、当前价格和持仓规模。
- 每位用户最多可有 200,000 个未结订单。
已知限制
/markets?keyword=会遗漏基于系列的市场——体育赛事、政治竞选及其他基于系列的类别无法通过关键词搜索找到。请始终通过/events?series_ticker=导航。请参阅上文“重要:基于系列的市场导航”。/markets/{ticker}对赛事市场会返回 404——体育及类似市场的买卖报价只会出现在事件端点响应中。请改用/events/{event_ticker}?with_nested_markets=true。- 经过身份验证的端点需要 RSA 签名——不能像大多数 REST API 那样使用简单的 API 密钥标头进行验证。请使用官方 Python/TypeScript SDK 进行签名。
- 仅支持二元市场——不支持多结果合约(多变量事件除外)
- 受美国监管——仅符合条件的美国居民可以交易
- 市场交易时段——市场设有规定的收盘时间,交易前请检查
close_ts - 历史数据分离——较旧的数据需要通过
/historical/*端点获取,请检查/historical/cutoff-timestamps了解分界点 - V1 与 V2 订单端点——V2 使用定点格式,V1 使用美分。两者均可使用,但新集成建议使用 V2。
- 子账户——仅面向机构和做市商开放(每位用户最多 32 个)
- RFQ 限制——最多同时有 100 个未结 RFQ
- 多变量市场创建——每个集合每周最多 5000 个