🌤️ Weather-Arb-Master — 项目深度分析


分析日期:2026-04-22
源码来源:weather-arb-master.zip
项目状态:实盘运行中 (AWS EC2, 31 城市, Maker-First 执行)



一、项目概览


weather-arb 是一个 Polymarket 天气温度套利系统,利用气象模型预测与预测市场定价之间的偏差,发现错误定价并自动执行交易。核心策略是 D1-only 温度 bin 套利:买入预测温度 ±1 的 3 个 bin,每个 5 shares,在隔日结算后获取收益。


核心数据流



Open-Meteo Previous Runs API → 历史预报偏差统计 → 修正预测
        ↓
Polymarket Gamma API → bin 价格 → Edge 计算
        ↓
WR ≥ 60% & Edge ≥ 15% → Maker-First 执行 (GTC → FAK)
        ↓
IEM ASOS 地面真值 → 自动结算 → Telegram 推送



二、技术栈


层级技术
语言TypeScript (Node.js)
运行时ts-node (直接执行 .ts)
部署AWS EC2 t3.micro (eu-west-1)
进程管理systemd (weather-live.service)
区块链Polygon Mainnet (Chain ID 137)
下单@polymarket/clob-client v5.8.1
钱包ethers.js v5
定时任务node-cron v4
通知Telegram Bot API
数据源Open-Meteo, IEM ASOS, Polymarket Gamma/CLOB



三、项目结构详解



weather-arb/
├── src/
│   ├── weatherPaper.ts           # 模拟盘主程序 (信号生成 + 模拟成交)
│   ├── weatherLive.ts            # 实盘主程序 (信号生成 + 真实下单)
│   ├── weatherExecutor.ts        # Maker-First 执行引擎 (GTC/FAK 下单)
│   ├── weatherBacktestReal.ts    # 真实价格回测引擎 (walk-forward, 无前瞻偏差)
│   ├── bt_depth_slippage.ts      # 深度 + 滑点回测
│   ├── paramSweep.ts             # 参数网格扫描 (Sharpe 优化)
│   ├── modelCompare.ts           # 气象模型对比分析
│   ├── dashboard.ts              # HTML 仪表盘生成
│   ├── slippageAnalysis.ts       # 滑点专项分析
│   ├── improvementPlan.ts        # 改进路径分析
│   ├── spreadAnalysis.ts         # ±N 覆盖度分析
│   ├── portfolio.ts              # 投资组合追踪
│   ├── telegram.ts               # Telegram 推送模块
│   │
│   ├── api/                      # 数据源 API 封装
│   │   ├── aggregator.ts         # 多源天气数据聚合器
│   │   ├── openMeteo.ts          # Open-Meteo API (预报 + Previous Runs)
│   │   └── nws.ts                # NOAA/NWS API (美国城市)
│   │
│   ├── engine/                   # 套利引擎
│   │   ├── arbEngine.ts          # 核心定价比较逻辑
│   │   ├── tempScanner.ts        # 温度盘口扫描器 (51城坐标映射)
│   │   └── signalDisplay.ts      # 信号格式化输出
│   │
│   ├── polymarket/               # Polymarket 客户端
│   │   └── client.ts             # Gamma API + CLOB 封装
│   │
│   ├── types/                    # TypeScript 类型定义
│   │   └── index.ts              # 核心类型 (WeatherForecast, ArbitrageSignal, etc.)
│   │
│   └── utils/                    # 工具函数
│       ├── config.ts             # 环境变量加载
│       ├── helpers.ts            # 概率计算, Kelly, 温度转换
│       └── logger.ts             # 结构化日志
│
├── scripts/                      # 运维脚本
│   ├── redeem.py                 # 自动赎回
│   ├── debugBook.js              # Orderbook 调试
│   ├── genDashboard.js           # 仪表盘生成
│   ├── live_vs_bt.js             # 实盘 vs 回测对比
│   └── check*.py                 # 各种检查脚本
│
├── analysis/                     # 可视化分析报告 (HTML)
│   ├── 深度与真实滑点分析.html
│   ├── 滑点与规模分析.html
│   ├── D1_32天回测_去T3.html
│   ├── D1实盘vs回测.html
│   └── 回测结果.html
│
├── data/                         # 数据存储
│   ├── backtest-real/            # 回测结果 (JSON/CSV/HTML)
│   ├── paper/                    # 模拟盘仓位
│   └── live/                     # 实盘数据
│
├── docs/                         # 项目文档
│   ├── 天气套利项目沉淀.md
│   └── 项目阶段性收获总结.md
│
├── package.json
├── tsconfig.json
└── .env.example



四、核心模块深度解析


4.1 信号生成 (weatherPaper.ts / weatherLive.ts)


信号生成是整个系统的核心,流程如下:



1. fetchPrevRuns(city, targetDate, BACKTEST_DAYS=50)
   → 获取历史 50 天 Open-Meteo 每个 run 的预报
   → 按 leadTime 分组,取偏差中位数 → bias

2. 对目标日,取最新 D1 run 的预测 rawFC
   → corrected = rawFC - bias_median

3. fetchPolyBins(city, targetDate)
   → 从 Polymarket Gamma API 获取事件 slug
   → 从 CLOB 获取所有温度 bin 的 best_ask 价格

4. matchBins(corrected, bins, spread=1)
   → 选 predicted bin ± 1 共 3 个 bin
   → totalCost = Σ(bin.askPrice × 5 shares)

5. 回测 winRate: 过去 50 天同逻辑命中次数
   → edge = winRate × $5.00 / totalCost - 1
   → 若 winRate ≥ 60% && edge ≥ 15% → 入场

关键参数:


参数说明
FIXED_SPREAD1买 pred ± 1 共 3 bins
MAX_LEAD_TIME1D1-only (仅预测明天)
MIN_WIN_RATE0.6050 天回测胜率门槛
MIN_EDGE0.15WR × $5 / cost - 1 ≥ 15%
BACKTEST_DAYS50回测窗口
MIN_SHARES5每 bin 最少份数
MIN_DATA_DAYS25最少可用数据天数

4.2 套利引擎 (engine/arbEngine.ts)


通用套利引擎,支持多种天气事件类型:


  • temperature_high/low: 温度超过/低于阈值 → 正态分布 CDF 概率模型
  • precipitation: 降水概率 → 集合预报 + 逐日 P(至少一天降水)
  • snowfall: 降雪概率 → 温度辅助判断
  • hurricane: 飓风 → 标记为需要专业数据源
  • extreme_heat/cold: 极端天气 → 复用温度模型
  • wind_speed: 风速 → 正态分布模型

  • 概率计算核心:

  • 有集合预报时 → 直接用 51 成员分布计算 bin 命中概率
  • 无集合预报时 → 确定性预报 + 正态分布近似 (stdDev 随 daysOut 增长: 1天→2°F, 7天→6.5°F, 14天→10°F)

  • 置信度评估 (assessConfidence):

  • 多数据源 → +0.1
  • 集合预报可用 → +0.15
  • 短期预报 (≤3天) → +0.2
  • 超大 edge (>30%) → -0.1 (市场可能知道你不知道的)
  • 飓风事件 → -0.15 (固有不确定性高)

  • 4.3 温度扫描器 (engine/tempScanner.ts)


    专门处理 Polymarket "Highest temperature in [City] on [Date]?" 市场:


  • 51 城市坐标映射 — 使用机场 ICAO 坐标(与 Weather Underground 结算一致)
  • Bin 解析引擎 — 支持 °C 和 °F 两种单位,自动解析 "20°C"、"50-51°F"、"70°F or higher" 等格式
  • 集合预报概率 — 51 成员分布直接计算落入 bin 的概率
  • 格式化输出 — CLI 表格 + 信号排序

  • 4.4 执行引擎 (weatherExecutor.ts)


    Maker-First 策略


    
    信号触发 → GTC 挂单 (best_ask − 1¢)
                  ↓
           等待 60s (大单) / 120s (小单)
                  ↓
         ┌── 成交 → 完成
         │
         ├── 大单未成交 → 撤单 → FAK 扫单 (limitPrice = min(maxAsk, priceCap))
         │
         └── 小单未成交 (<$1) → 保持挂单 (Polymarket $1 最低限制,FAK 无法执行)
    

    关键发现:实盘滑点的根因是价格过时 (scan→execute 延迟 60-180s),而非 orderbook 深度不足。Maker 挂单可完全消除滑点。


    下单保护参数:

  • MIN_EV: 0.05 (最低 edge 才下单)
  • MIN_EDGE: 0.15 (VWAP edge 门槛)
  • POST_SLIP_EDGE: 0.15 (滑点后最低 edge)
  • MAX_RETRIES: 2 (最大重试次数)
  • RETRY_DELAY: 1000ms

  • 4.5 回测引擎 (weatherBacktestReal.ts)


    Walk-forward 无前瞻偏差回测


    
    Phase 1 — 拉取天气数据 (Previous Runs + IEM)
    Phase 2 — Walk-forward 产生模型预测
    Phase 3 — 对每个预测,从 Polymarket 获取真实 bin 价格
    Phase 4 — 用真实价格计算 edge,模拟交易 P&L
    

    支持 CLI 参数:

  • --days=30: 回测天数
  • --cities=london,nyc: 城市过滤
  • --lead=1: D1-only
  • --shares=10: 每 bin 份数



  • 五、城市池与市场数据


    5.1 活跃城市 (31 城)


    区域城市
    欧洲 (8)London, Madrid, Milan, Paris, Amsterdam, Munich, Warsaw, Moscow
    亚太 (8)Tokyo, Seoul, Beijing, Shenzhen, Singapore, Chongqing, Kuala Lumpur, Lucknow
    中东/非洲 (5)Tel Aviv, Ankara, Istanbul, Cape Town, Lagos
    美洲 (9)Atlanta, Houston, Miami, Seattle, San Francisco, Los Angeles, Mexico City, São Paulo, Wellington
    其他 (1)Helsinki

    5.2 已移除城市 (T3-CUT)


    Shanghai, Hong Kong, Jakarta, NYC, Toronto, Chicago, Denver, Dallas, Buenos Aires, Busan, Panama City, Taipei, Wuhan, Austin, Chengdu, Jeddah — 回测亏损或数据问题。


    5.3 数据源


    数据源用途API 端点
    Open-Meteo Previous Runs历史预报 → 偏差统计previous-runs-api.open-meteo.com
    IEM ASOS (Iowa Mesonet)机场气象站地面真值 → 结算mesonet.agron.iastate.edu
    Polymarket Gamma API事件/市场 slug 查找gamma-api.polymarket.com
    Polymarket CLOB实时价格 + 下单clob.polymarket.com
    NOAA/NWS美国城市补充预报api.weather.gov

    5.4 结算规则(重要!)


  • 默认权威数据源: Weather Underground (WU),底层是 IEM ASOS 机场气象站
  • 测站: 机场 ICAO 站点(不是城市中心)
  • 温度格式: WU 显示的整数温度(四舍五入)
  • °C 城市: WU calendarDayTemperatureMax 存储 °F → round((F-32)*5/9) = 整数 °C
  • 例外:
  • - 香港: Hong Kong Observatory (HKO),向下取整 (floor)

    - Tel Aviv/Moscow: NOAA 数据源




    六、回测与业绩


    6.1 32 天回测 (306 笔)


    场景PnLROI$/天说明
    理想无滑点$117.4517.1%$3.67上界
    纯 FAK$44.504.5%$1.39下界
    纯 Maker$154.1923.7%$4.82最优
    实际混合$87.5914.7%$2.74Maker-First

    指标
    胜率 (won=true)67.0% (205/306)
    胜率 (pnl>0)62.4% (191/306)
    Sharpe17.40

    6.2 模拟盘 (27 笔已结算, 截至 04-11)


    指标
    胜率59.3%
    ROI+26.0%
    累计 PnL+$16.52

    6.3 参数扫描结论 (param_sweep_d30)


    排名HourSpreadSharpePnLROI
    112114.57$167.5328.5%
    210114.54$159.1426.9%
    30114.50$214.0029.1%

    结论: Spread=1 碾压其他配置,top 4 全是 spread=1。当前配置 h=10, s=1 已处最优区间。


    6.4 城市维度业绩


    Top 5 盈利城市:


    城市W/LPnLROI
    Seoul16W/5L+$30.4455.8%
    Miami9W/4L+$25.26127.9%
    Seattle10W/7L+$20.2558.3%
    Lucknow11W/4L+$18.6245.0%
    Warsaw10W/2L+$15.8446.4%



    七、滑点分析


    7.1 核心发现


    滑点 ≠ orderbook 深度,滑点 = 价格过时 (staleness)


  • 旧 VWAP 深度模型认为 5 份滑点 ≈ 0¢
  • 实盘真实滑点:中位 18.9% (1.189x), 均值 58.5% (1.585x)
  • 根因:scan→execute 间 60-180 秒内价格已移动

  • 7.2 按价位区间滑点 (47 笔实盘)


    价位样本中位 fillR建议
    <5¢81.627xMaker-only
    5-10¢121.412xMaker 优先
    10-20¢81.059x可控
    20-40¢191.097x甜蜜区

    7.3 $1 最低限制


    Polymarket FAK 要求 ≥ $1 notional。57% 的 bins (价格 <20¢ × 5 份) 无法 FAK,只能 maker 挂单。




    八、TWAP 拆单与规模化


    8.1 规模预期


    方案日均成本日均 PnL月均 PnLROI
    20 sh (当前)$88.71$34.52~$1,03638.9%
    50 sh$221.77$80.56~$2,41736.3%
    100 sh$443.55$149.49~$4,48533.7%

    8.2 推荐方案:高频扫描 + 逐笔加仓


    
    每 10-15 分钟扫描一次
      ↓ 获取最新预报 + 最新价格
      ↓ 如果仍有 edge → 下 20 shares
      ↓ 同一 bin 最多累计 N 轮 (cap=50 or 100)
      ↓ 天然实现 TWAP,每轮使用最新信息验证
    

    优势:每轮独立验证 edge,避免盲目拆单

    风险:做市商可能根据成交调整报价(但天气市场流动性由专业 MM 提供,恢复快)




    九、部署架构


    9.1 AWS EC2


    
    EC2 t3.micro (eu-west-1, IP: 54.170.78.92)
      └─ weather-live.service (systemd)
         └─ weatherLive.ts --cron
            ├─ UTC 00:00  全量扫描 + 下单
            ├─ UTC 00:10  结算重试
            ├─ UTC 00:15  TG 每日汇总
            └─ UTC 04:00  补充结算
    

    9.2 环境变量


    
    # Polymarket 交易凭证
    POLY_PRIVATE_KEY=0x...          # 钱包私钥
    POLY_API_KEY=...                # CLOB API key
    POLY_API_SECRET=...             # CLOB API secret
    POLY_API_PASSPHRASE=...         # CLOB API passphrase
    POLY_FUNDER=0x...               # 代理钱包 (GNOSIS_SAFE 模式)
    
    # 信号配置
    MIN_EDGE_PERCENT=5              # 最小套利阈值
    SCAN_INTERVAL_MINUTES=30        # 扫描间隔
    MAX_MARKETS=50                  # 最大市场数
    
    # 通知
    TELEGRAM_BOT_TOKEN=...          # Telegram Bot Token
    TELEGRAM_CHAT_ID=...            # Telegram Chat ID
    

    9.3 运维命令


    
    # SSH
    ssh -i polyaierlan.pem ec2-user@54.170.78.92
    
    # 服务管理
    sudo systemctl status weather-live.service
    sudo systemctl restart weather-live.service
    sudo journalctl -u weather-live.service -f
    
    # 部署更新
    scp -i polyaierlan.pem src/weatherPaper.ts ec2-user@54.170.78.92:~/weather-arb/src/
    



    十、关键公式


    预测修正

    
    T_corrected = T_raw_forecast - bias_median
    

    Edge 计算

    
    Edge = WR × $5.00 / totalCost - 1
    

    单笔 P&L

  • WIN: PnL = $5.00 - totalCost
  • LOSS: PnL = -totalCost

  • Kelly 仓位

    
    f* = p - (1-p)/b
    其中 p = 胜率, b = odds (净赔率)
    

    正态分布 CDF (Abramowitz & Stegun 近似)

    用于从确定性预报 + 标准差估计概率。




    十一、关键经验与踩坑


    问题原因解决
    T3-CUT 城市无法结算settlePending 找不到已切城市加临时 SETTLE_ONLY_CITIES 数组
    双重 TG 推送weather-scan 和 weather-paper 同时运行停用 scan service
    EV 计算不准用回测 WR 算 EV改用 CLOB 实时 token 价格
    回测 event cache 过期Polymarket event 到期后 slug 变化定期清理 event_*.json
    90 天回测超时数据量大 + API 限速分批缓存 + 手动监控进度
    won vs pnl>0 混用24 笔 won 但 payout=0区分预测准确性和实际结算
    滑点根因误判以为 orderbook 深度不够发现是价格过时,改用 Maker-First
    跨季校准失效季节漂移严重只用最近 25-50 天数据校准

    策略演进路径


    1. V1: 全城市全 leadTime → D2+ ROI 极低

    2. V2: 扩展到 47 城市 → 13 城回测亏损,切除

    3. V3: 参数扫描 → spread=1, hour=0 最优

    4. V4: D1-only → ROI/day 从 9.7% 提升到 42.7%

    5. V5: Maker-First 执行 → 消除滑点,ROI 从 4.5% 提升到 14.7%




    十二、下一步方向


    ☐ 按价位区间动态执行路径 (maker-only for <10¢ bins)
    ☐ 收集 maker fill rate 数据优化等待时间
    ☐ 缩小 scan→execute 延迟 (降低价格过时风险)
    ☐ 城市级别动态仓位管理
    ☐ 扩大到 20-50 shares (需 TWAP 拆单)
    ☐ 11 个新城市优化气象模型 (modelCompare)
    ☐ 实现高频扫描模式 (每 10-15 分钟)
    ☐ 添加同 bin 累计仓位追踪 + cap 控制
    ☐ 做市商深度监控 (防止流动性突变)



    十三、快速开始


    
    # 安装
    npm install
    
    # 配置
    cp .env.example .env   # 填入 Polymarket API 凭证
    
    # 模拟盘
    npx ts-node src/weatherPaper.ts         # 单次扫描
    npx ts-node src/weatherPaper.ts --cron  # 定时守护
    
    # 实盘
    npx ts-node src/weatherLive.ts --cron   # 实盘定时
    npx ts-node src/weatherLive.ts --dry    # 干跑 (不下单)
    
    # 回测
    npx ts-node src/bt_depth_slippage.ts    # 深度+滑点回测
    npx ts-node src/paramSweep.ts           # 参数扫描
    npx ts-node src/weatherBacktestReal.ts  # 真实价格回测
    
    # 分析工具
    npx ts-node src/modelCompare.ts         # 模型对比
    npx ts-node src/spreadAnalysis.ts       # 覆盖度分析
    npx ts-node src/slippageAnalysis.ts     # 滑点分析
    



    十四、总结


    weather-arb 是一个设计精良的预测市场套利系统,核心优势在于:


    1. D1-only 策略 — 资金效率最高,隔日结算

    2. 统计偏差校正 — 用历史预报误差修正当前预测

    3. Maker-First 执行 — 有效消除滑点,提升实际 ROI

    4. 完整回测框架 — walk-forward 无前瞻偏差验证

    5. 系统化城市管理 — 定期修剪亏损城市,优化城市池


    经 31 天 / 306 笔回测验证:胜率 67%、ROI 39%、Sharpe 17.4。实盘运行稳定,具备规模化潜力(50-100 shares)。