我连接到公共 WebSocket 数据流,并在 Polymarket 发现了定价错误的代币
Source: Dev.to
请提供您希望翻译的文章正文内容,我将按照您的要求保留链接并将正文翻译成简体中文。
Overview
我连接了两个 WebSocket 数据源:一个是用于结算 Polymarket 15 分钟加密市场的 Chainlink 预言机,另一个是 Polymarket 的订单簿。并排观察它们时,我发现了一个持续的延迟:预言机的更新在不到一秒的时间内完成,而订单簿大约需要 55 秒才能反映相同的变动。几乎整整一分钟的时间里,代币都停留在陈旧的数据上。结算来源是公开的,任何人都可以连接,并且它始终比它所结算的市场提前近一分钟运行。这不是一个 bug——而是市场的工作方式——但能够如此清晰地测量到这一点还是相当罕见的。
策略
核心逻辑很简单:
-
在每一次预言机价格更新时,检查三个条件:
- 价格相对于开盘价 > 0.07 % 变动
- 剩余时间 > 5 分钟
- 代币价格 < $0.62
-
如果 全部三个 条件成立,买入低价方,等待结算,并收取 $1(或者失去本金)。
有趣的地方不在于策略本身,而在于让它可靠运行。
实现
架构
单个进程持有一个打开的 WebSocket 接收亚秒级更新,跟踪 16 个重叠的市场,在每个 tick 上评估信号,非阻塞地下单,发送 Telegram 通知,为崩溃恢复持久化状态,并监控自身健康——所有这些都并发进行。
asyncio 是显而易见的选择:几乎零 CPU 工作,全部是 I/O‑bound。七个并发任务在同一个事件循环中运行:
tasks = [
oracle.run(shutdown),
market_lifecycle_loop(...),
signal_evaluation_loop(...),
telegram.run(shutdown),
state_persist_loop(...),
redeem_loop(...),
sanity_check_loop(...),
]
await asyncio.gather(*tasks)
没有线程,没有锁,没有多进程。
处理僵尸 WebSocket 连接
最棘手的 bug 是僵尸 WebSocket:连接保持存活,ping/pong 正常,未抛出异常,但价格数据悄然停止流动。简单的 recv 超时无效,因为心跳帧仍然到达。
修复: 使用单调时钟记录最近一次真实价格更新的时间戳,并在每次超时时检查它。如果在阈值时间内没有收到真实数据,则终止连接并强制重新连接。
验证外部凭证
另一个细微问题:机器人启动后,日志看起来完美,但 20 分钟后 Telegram 聊天 ID 错误,导致所有通知静默失败。
修复: 在进入主循环之前验证每个外部凭证:
# 验证 Telegram
telegram.get_me()
telegram.send_message(test_chat_id, "test")
# 验证 Polymarket API 密钥
polymarket.verify_keys()
如果有问题,机器人将在前两秒内退出并给出明确错误,例如:
ERROR: Telegram chat_id=123456 is invalid.
Tip: send any message to @your_bot first, then use getUpdates to find your chat_id.
回测结果
- 评估的市场: 8,876 个已结算市场
- 价格点: 146,000
- 标记的交易: 5,017
- 胜率: 在 BTC、ETH、XRP 和 SOL 中为 61.4 %
我尝试了七种不同的方法来击垮系统(日期拆分、参数网格搜索、费用翻倍、每日拆分等)。它们都没有让系统失效,尽管真实环境会更严苛:订单簿更薄、滑点更大,且随时间推移延迟会缩小。这不是退休计划。
开源
整个项目是开源的,并且包括一个演示模式,可在不使用任何 API 密钥的情况下连接实时数据并进行纸上交易。
https://github.com/JonathanPetersonn/oracle-lag-sniper
合作邀请
如果您构建过类似的实时 asyncio 系统,我很想了解您是如何组织它们的。这种“许多并发的长期任务共享状态”的模式似乎很常见,但在构建时我找不到好的开源参考。