🌤️ 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_SPREAD | 1 | 买 pred ± 1 共 3 bins |
MAX_LEAD_TIME | 1 | D1-only (仅预测明天) |
MIN_WIN_RATE | 0.60 | 50 天回测胜率门槛 |
MIN_EDGE | 0.15 | WR × $5 / cost - 1 ≥ 15% |
BACKTEST_DAYS | 50 | 回测窗口 |
MIN_SHARES | 5 | 每 bin 最少份数 |
MIN_DATA_DAYS | 25 | 最少可用数据天数 |
4.2 套利引擎 (engine/arbEngine.ts)
通用套利引擎,支持多种天气事件类型:
概率计算核心:
置信度评估 (assessConfidence):
4.3 温度扫描器 (engine/tempScanner.ts)
专门处理 Polymarket "Highest temperature in [City] on [Date]?" 市场:
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: 1000ms4.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 结算规则(重要!)
calendarDayTemperatureMax 存储 °F → round((F-32)*5/9) = 整数 °C- 香港: Hong Kong Observatory (HKO),向下取整 (floor)
- Tel Aviv/Moscow: NOAA 数据源
六、回测与业绩
6.1 32 天回测 (306 笔)
| 场景 | PnL | ROI | $/天 | 说明 |
|---|---|---|---|---|
| 理想无滑点 | $117.45 | 17.1% | $3.67 | 上界 |
| 纯 FAK | $44.50 | 4.5% | $1.39 | 下界 |
| 纯 Maker | $154.19 | 23.7% | $4.82 | 最优 |
| 实际混合 | $87.59 | 14.7% | $2.74 | Maker-First |
| 指标 | 值 |
|---|---|
| 胜率 (won=true) | 67.0% (205/306) |
| 胜率 (pnl>0) | 62.4% (191/306) |
| Sharpe | 17.40 |
6.2 模拟盘 (27 笔已结算, 截至 04-11)
| 指标 | 值 |
|---|---|
| 胜率 | 59.3% |
| ROI | +26.0% |
| 累计 PnL | +$16.52 |
6.3 参数扫描结论 (param_sweep_d30)
| 排名 | Hour | Spread | Sharpe | PnL | ROI |
|---|---|---|---|---|---|
| 1 | 12 | 1 | 14.57 | $167.53 | 28.5% |
| 2 | 10 | 1 | 14.54 | $159.14 | 26.9% |
| 3 | 0 | 1 | 14.50 | $214.00 | 29.1% |
结论: Spread=1 碾压其他配置,top 4 全是 spread=1。当前配置 h=10, s=1 已处最优区间。
6.4 城市维度业绩
Top 5 盈利城市:
| 城市 | W/L | PnL | ROI |
|---|---|---|---|
| Seoul | 16W/5L | +$30.44 | 55.8% |
| Miami | 9W/4L | +$25.26 | 127.9% |
| Seattle | 10W/7L | +$20.25 | 58.3% |
| Lucknow | 11W/4L | +$18.62 | 45.0% |
| Warsaw | 10W/2L | +$15.84 | 46.4% |
七、滑点分析
7.1 核心发现
滑点 ≠ orderbook 深度,滑点 = 价格过时 (staleness)
7.2 按价位区间滑点 (47 笔实盘)
| 价位 | 样本 | 中位 fillR | 建议 |
|---|---|---|---|
| <5¢ | 8 | 1.627x | Maker-only |
| 5-10¢ | 12 | 1.412x | Maker 优先 |
| 10-20¢ | 8 | 1.059x | 可控 |
| 20-40¢ | 19 | 1.097x | 甜蜜区 |
7.3 $1 最低限制
Polymarket FAK 要求 ≥ $1 notional。57% 的 bins (价格 <20¢ × 5 份) 无法 FAK,只能 maker 挂单。
八、TWAP 拆单与规模化
8.1 规模预期
| 方案 | 日均成本 | 日均 PnL | 月均 PnL | ROI |
|---|---|---|---|---|
| 20 sh (当前) | $88.71 | $34.52 | ~$1,036 | 38.9% |
| 50 sh | $221.77 | $80.56 | ~$2,417 | 36.3% |
| 100 sh | $443.55 | $149.49 | ~$4,485 | 33.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
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%
十二、下一步方向
十三、快速开始
# 安装
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)。