安全地比较 Kalshi 和 Polymarket
比较 Kalshi 和 Polymarket,要从合约开始。两条挂牌可能用日常语言描述同一个事件,却在不同的结果、观察窗口、数据来源或边界条件上结算。如果在检查这些条款之前,就把两者的价格放在一起比较,得到的只是一个看似精确、实则针对两个不同主张的比较。
Dino 会把相关挂牌匹配进一个 Market 对象,并把结算差异一并保留在这个对象上。本教程使用 Python SDK 查看一对匹配结果,只有在完成合约检查之后,才计算价格差距。
拉取一个匹配的 Market 及其详情
创建一个免费 API 密钥并安装客户端,然后请求一个已开放的市场系列。本示例使用天气类别,因为它在披露信息中的站点和分组差异很容易看出来:
export DINO_API_KEY=sk_live_...
pip install dino-markets
from dino_markets import Dino
client = Dino()
catalog = client.markets(
category="weather",
market_type="weather_high",
status="open,live",
limit=20,
)
summary = next(
(
market
for market in catalog["markets"]
if market["coverage"]["kalshi"]
and market["coverage"]["polymarket"]
),
None,
)
if summary is None:
raise SystemExit("No two-venue weather comparison is available right now.")
market = client.market(summary["id"])
列表结果提供一个稳定的 Dino id,以及当前的延迟价格。client.market(id) 会为完整比较添加标准化上下文、平台身份、市场深度和结算披露信息。
把披露信息变成审查清单
下面这个函数会在计算任何价格之前,展示四项检查:
def comparison_checks(market):
settlement = market.get("settlement") or {}
risks = settlement.get("risks") or []
served_blocking = [
risk
for risk in risks
if risk.get("severity") == "high"
]
fully_priced = bool(market["outcomes"]) and all(
outcome.get("kalshi") is not None
and outcome.get("polymarket") is not None
for outcome in market["outcomes"]
)
return {
"entity_match_served": market["match"] == "high_confidence",
"full_price_coverage": fully_priced,
"settlement_parity": settlement.get("parity") is True,
"served_blocking_risks": served_blocking,
}
checks = comparison_checks(market)
print(checks)
match 回答的是身份问题:Dino 是否有足够证据证明这些挂牌代表同一个事件或背后的主张,从而可以把它们放在一起提供。完整价格覆盖回答的是,每个结果是否都能在两个平台之间进行比较。结算一致性和已提供的风险列表则说明,匹配的结果是否在相容的条款下结算付款,具体还要参照下面的取消披露信息。
一个 Market 可以是有效的跨平台比较,同时又带有结算方面的保留说明。在这种情况下,它的 signal 会保持为 spread,这条保留说明应该和价格放在一起展示。已确认的 Opportunity 有更高的门槛,来自单独的 /v2/arbitrage 资源。
分层阅读合约条款
把 Market 详情字段当作一个固定的审查顺序:
| 检查项 | 字段 | 需要验证的内容 |
|---|---|---|
| 身份 | match、title、类别上下文 | 两个平台的挂牌指向同一个事件或主张。 |
| 结果 | outcomes[].key、outcomes[].name | 分组覆盖的是同一组真实世界的结果。 |
| 覆盖范围 | coverage、结果价格 | 在比较需要的每个地方,两个平台都有真实价格。 |
| 结算 | settlement.parity、settlement.risks[]、settlement.kalshi_text、settlement.poly_text | 结算来源和截止边界相容或已被披露。阅读各平台的规则文本,了解取消条款的具体措辞。 |
对外提供的 settlement.risks[] 会有意省略内部的 cancel_* 事件。请阅读 kalshi_text 和 poly_text,了解各平台的取消条款。Dino 会先根据完整的内部风险集合计算 settlement.parity 和 signal,然后再从公开的风险列表中过滤掉这些事件。
天气类市场说明了为什么每一层都很重要。两份每日最高气温合约可能标注的是同一个城市,却依据不同的气象站结算。它们的温度区间也可能相差 1 度。Dino 会保留每个平台实际的分组,报告重叠部分,而不是凭空生成一个合并价格。
加密货币阈值类市场则暴露出另一种边界问题。一个平台可能按"等于或高于"某个阈值结算,另一个平台则使用"高于"。这样一来,恰好在阈值上出现的价格差距,指向的其实是获胜条件不同的合约,即使两边的标题提到的是同一种资产和同一个数字。
最后再计算价格差异
在审查完披露信息之后,针对每个价格完整的结果,计算观测到的差异:
for outcome in market["outcomes"]:
kalshi = outcome.get("kalshi")
polymarket = outcome.get("polymarket")
if kalshi is None or polymarket is None:
continue
gap_pts = abs(kalshi - polymarket) * 100
print(
outcome["name"],
f"Kalshi {kalshi:.2f}",
f"Polymarket {polymarket:.2f}",
f"gap {gap_pts:.1f} pts",
)
结果是 Market 的 priced_at 时间戳上的一个跨平台价差,说明两个观测价格之间相差多远。真正执行交易还需要当前的订单簿数据、可用规模、费用,以及相容的结算条款。这是开发者数据,不构成交易或金融建议。
身份匹配和触发条件的判定标准,请参阅 Dino 如何匹配市场。上面用到的每个字段,请参阅 Market 对象参考文档。实时看板以人类可读的形式展示相同的披露信息。