Polymarket Bot 教程 · 第 30 章,共 32 章
面向 Polymarket bots 的生产级风控代码:仓位上限、每日亏损限制、halt 哨兵、成交率 watchdog、重启时对账、幂等重试。来自真实生产 trader 的代码模式。
本章内容
风控代码占了生产交易 bot 的大部分。策略逻辑只是最容易的部分;真正决定 bot 能否熬过第一个糟糕周的,是周边的上限、停机、watchdog 和对账机制。本章讲的是生产级风控模式。
- 为什么风控代码占据了真实 trading bot 的大部分
- 仓位上限(单市场、单策略、总计)
- 每日亏损 kill switch
- halt 哨兵(基于文件的紧急停止)
- 成交率 watchdog
- 重启时对账 diary 与链上状态
- 代码:生产级、支持 halt 的循环
为什么风控代码占据了真实 trading bot 的大部分
我们在自有 bot codebase 上做过一个统计:60% 的 LOC 是风控代码(上限、停机、watchdog、reconciliation)。30% 是策略。10% 是 glue。
这个比例是对的。策略很简单-描述何时进场、何时退出,只需要几十行代码。风控代码则是其他一切:当价格比预期更快地反向移动时怎么办,成交开始消失时怎么办,WebSocket 掉线时怎么办,策略被证明无利可图时怎么办。
大多数 builder 的失败故事都有同样的模式:策略本身是对的,但 bot 因为没有触发 halt 而在 regime change 中持续交易。先写 halt,再写策略。
仓位上限(单市场、单策略、总计)
三个上限,必须在代码里强制执行。
- 单市场上限:无论 edge confidence 多高,每个市场最多 $X。典型值:小型 bot 为 $25-100,生产环境为 $200-500。用于限制单个市场判断错误时的爆炸半径。
- 单策略上限:如果你运行多个策略,每个策略分配总资本的一部分。典型值:每个策略 30-50%。防止某个策略糟糕的一天吞掉其他策略的资金。
- 总上限:同时部署的最大钱包余额百分比。典型值:50-70%。为意外机会或 bot 自身记账 bug 预留资金缓冲。
这三个上限都应该在下单函数内部强制执行,而不只是写在策略逻辑里。策略可能有 bug;下单门禁是最后一道防线。
每日亏损 kill switch
最重要的单一风控:每日亏损 kill switch。
规则:如果自 UTC 午夜以来,已实现 + 未实现 PnL 低于起始日余额的 -X%,bot 停止开新仓位,并且(可选)平掉现有仓位。典型 X:5-10%。
数学上看:一个预期胜率 60% 的 bot,可能有 5% 的概率出现 10 连败。没有 kill switch 时,这种连败会不断叠加:亏损 $200 → bot 继续交易 → 再亏 $200 → 钱包回撤 40%。如果在 -10% 时触发开关,坏日子的损失就封顶在 $200,而第二天 bot 可以重新开始。
这个开关要在服务端强制执行:写入 halt 文件,或设置数据库标志,并由 trading loop 每次迭代检查。只有人工复核后才能重启。
halt 哨兵(基于文件的紧急停止)
最简单的 halt 机制:bot 在每次循环迭代时检查一个文件(例如 /opt/pmt/HALT),如果文件存在就停止交易。
def trading_loop():
while True:
if os.path.exists("/opt/pmt/HALT"):
log("HALT file detected, sleeping")
time.sleep(30)
continue
run_one_iteration()
time.sleep(5)
要从任何地方立即停止(SSH、Telegram bot、监控系统):touch /opt/pmt/HALT。要恢复:rm /opt/pmt/HALT。
这种基于文件的方法是故意保持低技术门槛的,因为它在更复杂的 halt 机制失效时仍然可用:比如 bot 部分崩溃、数据库不可达、API key 受限速影响时。文件系统访问始终可用。
成交率 watchdog
策略假设 FOK orders 以某个比例成交(通常 60-80%)。当这个比例明显下降时,说明情况变了:市场 maker 撤走了,你的策略被识别了,或者 API 故障正在发生。无论原因是什么,驱动策略 PnL 计算的假设已经失效。
watchdog 逻辑:滚动 24 小时成交率统计。如果 < 30%(或低于预期的 50%),就报警 + 自动 halt。只在人工复核后恢复。
watchdog 也很适合做诊断。成交率突然下降,通常与外部事件相关(Polymarket deploy、Polygon 拥堵、你的 IP 被限速),无论交易影响如何,你都应该知道。
重启时对账 diary 与链上状态
bot 会维护一份 diary,记录它认为自己持有的仓位。链上维护真相。二者应该始终一致;一旦不一致,bot 就是在基于错误认知运行,并会错误交易。
对账逻辑:在每次重启时,以及正常运行期间每小时一次,获取 bot 接触过的每个 token 的链上余额。将其与 diary 比较;如果任何 token 的余额与 diary 的差异超过舍入容差,就报警 + halt。
最常见的不一致原因是:某个订单实际上成功了,但 bot 的 API 调用漏记了(超时、重试未记录)。链上已经有仓位;bot 却以为没有。没有 reconciliation,bot 就不会挂出止盈退出单,仓位会一直持有到结算。
代码:生产级、支持 halt 的循环
参考实现:带有全部风控控制的 production trading loop。
def production_loop():
while True:
# Halt checks
if os.path.exists("/opt/pmt/HALT"):
sleep_with_log(30); continue
if daily_pnl_below_threshold():
create_halt("daily PnL kill"); continue
# Reconcile every hour
if now() - last_reconcile > 3600:
ok = reconcile_diary_vs_chain()
last_reconcile = now()
if not ok: create_halt("reconciliation failed"); continue
# Fill-rate watchdog
if recent_fill_rate() < 0.30:
create_halt("fill rate collapse"); continue
# Strategy
try:
run_strategy_once()
except Exception as e:
log_exception(e)
if consecutive_exceptions >= 5:
create_halt(f"exceptions: {e}"); continue
time.sleep(5)
模式很清晰:每次迭代都必须通过门禁。策略 bug 不能绕过这些控制,这是结构上保证的。





