Polymarket Bot 教程 · 第 22 章,共 32 章

Polymarket 上的 NegRisk 多结果 bots:sum-to-1 机制、当 YES legs 之和不为 1 时的 leg arbitrage、跨 legs 对冲,以及多结果市场特有的执行陷阱。

本章内容概览

多结果 NegRisk 市场是互斥的-最终只会有一个结果为 YES。本章是在第 11 章执行机制之上的策略层:如何跨 legs 对冲、何时 sum-to-1 arbitrage 真的存在,以及 NegRisk bots 在首次部署时最常踩的 bug。

  • NegRisk vs binary 回顾
  • Sum-to-1 不变量与套利
  • 逐 leg 对冲构建
  • 执行:订单中的 neg_risk 标志
  • NegRisk bots 的常见 bug
  • 代码:并行快照所有 legs 并检测低于 1.00 的总和

NegRisk vs binary 回顾

Binary:一个 yes/no 市场,两个 token,总和为 1.0。NegRisk:N 个互斥结果,N 个 token,所有 YES legs 的总和在事件中约等于 1.0。

在执行层面,NegRisk 要求每一笔订单都带上 negRisk: true(第 11 章),并通过一个独立的 exchange contract 路由。从策略层面看,NegRisk 提供了 binary 没有的两个独特机会:当总和偏离 1.0 时进行跨 leg arbitrage,以及通过购买多个 YES legs 来构建对冲。

NegRisk 独有的成本:legs 越多,spread tax 越高(你交易的每个 leg 大约要承担 0.5-1c 的 spread 成本),低流动性事件的 sum-to-1 偏离通常更大(套利更常出现,但规模也更小)。

Sum-to-1 不变量与套利

套利前提:如果买入所有 N 个 YES legs 的总成本低于 1.00 美元,那么在结算时你就锁定了确定性利润(必有一个 leg 赔付 1.00 美元;其他 legs 归零)。

在实践中,套利缺口通常只有 0-3c,会被每个 leg 的 spread + fees 吃掉,而且往往在开盘后几分钟内就消失。容量受限于流动性最薄的 leg。

这种套利还受特定结算失败模式影响:例如“none of the above”结果会在没有任何已命名候选人符合条件时明确结算为 YES。如果事件有这样的 leg,而你没有买入它,那么你的“完整对冲”其实漏掉了实际赔付来源。

逐 leg 对冲构建

如果你持有 NegRisk 某个 leg 的仓位,可以按比例买入其他竞争 legs 来对冲。比如你持有 Trump-YES,价格 0.50,并希望对冲 Trump 失败的风险,你可以买入其他已命名 legs 的组合。

每个 leg 的对冲权重 ≈ 该 leg 当前的隐含概率,条件是 Trump 失败。近似公式:weight_i = price_i / (1 - trump_price)

这种对冲并不完美,因为使用的是某一时点的价格,而随着新闻出现,条件概率会变化。每周或在重大新闻后重新平衡对冲即可。不要过度设计;对冲的目标是降低方差,而不是消除它。

执行:订单中的 neg_risk 标志

NegRisk 特有的最常见 bug:在下单 payload 里忘记了 negRisk: true。订单会被 API 接受,但由于它被路由到了标准 CTF exchange,而不是 NegRisk exchange,结算会出错。

// CORRECT for NegRisk markets:
await client.createAndPostOrder(
  { tokenID, price, size, side: Side.BUY },
  { tickSize: '0.01', negRisk: true },   // <-- REQUIRED
  OrderType.FOK
);

权威来源:Gamma API 中的 market.negRisk。读取它,并直接传下去。不要靠猜测硬编码这个标志。

NegRisk bots 的常见 bug

来自多个 bots 的生产环境调试日志。

  1. 缺少 negRisk 标志:订单被接受,但结算失败。解决:在每一层封装里都强制设置该标志。
  2. 对冲时遗漏 “Other” leg:在包含 “None of the above” 结果的事件里,排除它的对冲组合是不完整的。解决:构建对冲时始终检查是否存在 Other leg。
  3. sum-to-1 arbitrage 仓位过小:arber 发现了 1c 的边际优势,但每个 leg 只交易 5 股;总利润在 spread 前只有 5 美分,净值为负。解决:把套利仓位做得足以产生有意义的绝对美元收益,而不是追逐表面百分比。
  4. leg 定价过时:bot 获取 3 个 leg 的价格,总共花了 200ms,最后一个 leg 的价格在抓取期间已经变化。解决:并行获取所有 legs + 将快照视为一次整体观测。

代码:并行快照所有 legs 并检测低于 1.00 的总和

参考:并行快照一个 NegRisk 事件的所有 YES legs,并检测套利。

import asyncio, aiohttp

async def fetch_leg_ask(session, token_id):
    async with session.get(f"https://clob.polymarket.com/book?token_id={token_id}") as r:
        d = await r.json()
        asks = d.get("asks", [])
        return float(asks[0]["price"]) if asks else None

async def check_arb(event_slug):
    event = await fetch_event(event_slug)
    if not event["markets"][0]["negRisk"]: return None
    legs = []
    for m in event["markets"]:
        toks = json.loads(m["clobTokenIds"])
        yes_token = toks[0]
        legs.append(yes_token)

    async with aiohttp.ClientSession() as s:
        asks = await asyncio.gather(*[fetch_leg_ask(s, t) for t in legs])
    if any(a is None for a in asks): return None
    total = sum(asks)
    if total < 0.97:
        return {"edge": 1 - total, "legs": list(zip(legs, asks))}
    return None

所有 legs 的原子执行才是更难的问题,这需要对每个 leg 使用 FOK,并在部分成交时回滚(类似第 16 章 stat-arb 代码中的模式)。

常见问题

NegRisk markets 中的 sum-to-1 不变量是什么?
在一个 NegRisk 多结果市场中,所有 YES legs 的总和会保持接近 1 美元,因为最终只会有一个结果获胜。如果在扣除 fees 后总和低于 1.00,那么按比例买入每个 leg 就能锁定套利利润。这个套利很少见,而且很快就会被抢走-把它当作有趣现象,而不是主要策略。
NegRisk 的定价与 binary 有什么不同?
Binary:YES 价格就是你对概率的直接估计。NegRisk:某个 leg 的 YES 价格是该具体结果在 N 个备选中胜出的概率。随着 N 增大,单个价格会变小(因为概率总和为 1)。交易 NegRisk 需要从相对概率而不是绝对 Yes/No 的角度思考。
NegRisk bot 最常见的 bug 是什么?
在下单时忘记设置 neg_risk: true 标志。订单要么被拒绝,要么被路由到错误的 CTF 仓位。我们在生产中确实遇到过这个问题-我们 trader 历史中的 commit 06deaef 就是专门修复它。对 NegRisk 订单务必始终设置 neg_risk=true(Python)或 negRisk: true(Node)。
我能通过对冲 legs 在 NegRisk 上赚钱吗?
理论上可以(锁定两个 legs 之间的 spread)。但在实践中,对于大多数零售 bots 来说,fees 会吃掉对冲优势。对冲更适合在做 market making 时保持库存中性,而不是作为独立策略。
我如何找到 NegRisk markets?
筛选 gamma /events:找出市场数量大于 2 且设置了 negRisk 标志的事件。常见类别包括:冠军归属(NBA Finals MVP)、选举字段(下一任 Speaker)、锦标赛 bracket。每个 gamma event 都包含其 child markets 数组。
NegRisk markets 的流动性比 binary 更高还是更低?
单个 leg 更低,但整体更高。一个 30 支球队的 NBA Champion 事件可能有 5 万美元的 24h 总成交量,但每支球队的 market 只有 1.6K-这会让逐 leg 交易更难。总流动性是真实存在的,只是被分散了。