我连接到公共 WebSocket 数据流,并在 Polymarket 发现了定价错误的代币

发布: (2026年3月19日 GMT+8 06:35)
5 分钟阅读
原文: Dev.to

Source: Dev.to

请提供您希望翻译的文章正文内容,我将按照您的要求保留链接并将正文翻译成简体中文。

Overview

我连接了两个 WebSocket 数据源:一个是用于结算 Polymarket 15 分钟加密市场的 Chainlink 预言机,另一个是 Polymarket 的订单簿。并排观察它们时,我发现了一个持续的延迟:预言机的更新在不到一秒的时间内完成,而订单簿大约需要 55 秒才能反映相同的变动。几乎整整一分钟的时间里,代币都停留在陈旧的数据上。结算来源是公开的,任何人都可以连接,并且它始终比它所结算的市场提前近一分钟运行。这不是一个 bug——而是市场的工作方式——但能够如此清晰地测量到这一点还是相当罕见的。

策略

核心逻辑很简单:

  1. 在每一次预言机价格更新时,检查三个条件:

    • 价格相对于开盘价 > 0.07 % 变动
    • 剩余时间 > 5 分钟
    • 代币价格 < $0.62
  2. 如果 全部三个 条件成立,买入低价方,等待结算,并收取 $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 系统,我很想了解您是如何组织它们的。这种“许多并发的长期任务共享状态”的模式似乎很常见,但在构建时我找不到好的开源参考。

0 浏览
Back to Blog

相关文章

阅读更多 »