polyweather — Weather tail-event bot

Buys $0.01-$0.10 outcomes on Polymarket weather markets when an Open-Meteo ensemble forecast implies ≥2× the market's probability. 20 cities, 4-hour scan cycle, 20-position cap.

Version v1.0.0 · One-time payment · Source code download
Strategy typeTail events
AssetMulti-city
TimeframeEvent-driven
Market typeWeather
Minimum capital$30
Dependencies@polymarket/clob-client, ethers

What it does

polyweather hunts for extreme-temperature outcomes on Polymarket weather markets priced between $0.01 and $0.10 where an ensemble weather forecast says the real probability is at least 2× the market-implied probability. It buys the underpriced tails as FOK takers and holds to resolution.

The edge

Weather markets are populated mostly by casual bettors. The Polymarket book on a "Will NYC hit 95°F tomorrow?" market underprices unlikely outcomes because nobody wants to bet against a sunny forecast for $0.06 even when the historical probability is 12%.

The bot's edge is a real weather forecast (Open-Meteo's ensemble model, free + no auth). When the ensemble says 8% probability and the Polymarket book quotes 3¢ (implied 3%), the gap is your edge. Bet sizes are intentionally tiny ($3 default) because tail outcomes have huge variance — most positions resolve to zero, but the winners pay 10-30x.

How it works

Scan cycle (default every 4 hours):

  1. Discover active weather markets across the 20 covered cities (NYC, London, Paris, Toronto, Tokyo, Shanghai, Singapore, Seoul, Munich, Tel Aviv, etc., full list in source CITIES)
  2. Fetch the Open-Meteo ensemble forecast for that city's coordinates for the market's resolution day
  3. Compute the implied probability of the market's threshold outcome from the ensemble's percentile distribution
  4. Compare: if ensemble_prob ≥ edge × market_prob (default edge = 2.0×), the outcome is underpriced
  5. Filter: market price between $0.01 and $0.10, ensemble probability ≥ 2% (MIN_ENSEMBLE_PROB)
  6. Bet: FOK taker at the market ask price, --bet $3 per position
  7. Cap: up to --max-pending 20 simultaneous positions

Uses viem for signing (instead of ethers, because that's what @polymarket/clob-client-v2 v3.x took as its preferred path).

Sample output

[24/05/2026, 09:00:01] Scanning 47 weather markets... [24/05/2026, 09:00:14] NYC | "Will NYC hit 95°F on May 27?" | market=$0.06 ensemble=14% edge=2.3× — entering [24/05/2026, 09:00:14] BUY (FOK) 50sh @ $0.060 ($3.012 incl fee) [24/05/2026, 09:00:14] Filled: 0x1ab2c3d4... [24/05/2026, 13:00:01] Scanning 47 weather markets... [24/05/2026, 13:00:14] Singapore | "Will Singapore hit 34°C on May 27?" | market=$0.04 ensemble=9% edge=2.25× — entering [27/05/2026, 23:30:00] Resolved WIN "NYC 95°F" | 50sh × $1.00 - $3.00 = +$47.00 | Bal: $77.00

Design targets

Expected value: at 2× edge, a $3 bet at $0.05 entry returns $60 if it wins ($1 × 60 shares) minus $3 cost = $57 net, with ensemble-implied 10% chance. Expected per bet: 10% × $57 - 90% × $3 = $5.70 - $2.70 = +$3.00. Real outcomes have high variance: long stretches of losses punctuated by occasional 10-30x payoffs.

Capital efficiency: 20 max positions × $3 = $60 in active bets. $30 starting bank lets you size up over time as winning resolutions pay out.

FAQ

Why a 2× edge minimum?

Below 2×, the variance of tail outcomes overwhelms the edge. At 2× the long-run expectation is strongly positive even after factoring in ensemble forecast error. You can drop the minimum to 1.5× in source if you want more trades.

What weather data source?

Open-Meteo's free ensemble API. No authentication, generous rate limits, refreshes hourly. The bot uses each ensemble member as a sample to build a probability distribution for the threshold outcome.

Does it work in every city?

Coverage is the 20 cities in the CITIES object: NYC, London, Paris, Toronto, São Paulo, Buenos Aires, Seoul, Seattle, Dallas, Atlanta, Miami, Chicago, Ankara, Wellington, Lucknow, Munich, Tel Aviv, Tokyo, Shanghai, Singapore. Adding more cities is a 1-line edit per city (lat/lon + unit).

What's included

  • polyweather/weather.js
  • polyweather/run.sh (auto-restart wrapper)
  • polymarket-limits.js
  • README with adding cities, edge tuning, and an explanation of the ensemble probability calculation

Configuration

FlagDefaultDescription
--livePlace real orders. Default is dry-run.
--sim-balance 3030Starting balance in dry-run mode (USD).
--max-balance 00Cap balance used for sizing. 0 = use full balance.
--bet 33Fixed bet amount per position in USD.
--edge 2.02.0Minimum forecast/market edge multiplier before entering.
--max-pending 2020Maximum simultaneous open positions.
--scan-interval 1440014400Seconds between market scans. Default is 4 hours.