Weather Bot — Episode 2: Turning GFS, ECMWF, and ICON Forecasts Into Polymarket Trading Signals
So I had the idea: use professional weather models to find mispriced temperature bets on Polymarket. But there's a gap between "this sounds like it should work" and actually pulling data from three different forecast systems, comparing it to live market prices, and deciding what to buy.
This episode is about building that bridge. How I picked the models, how I access them for free, and the part that surprised me most — why I abandoned US cities entirely and started trading Ankara and Buenos Aires instead.
What This Post Covers
The forecasting pipeline behind WeatherBot — three global weather models accessed through one free API, how Weather Underground actually determines the "right answer," and a city selection decision that went against everything I expected. This is the technical foundation the bot runs on, so if something here doesn't make sense, the later episodes won't either.
Three Models, One API
I use three global weather models. All of them are free through Open-Meteo's API — no API key, no credit card, up to 10,000 calls per day.
GFS (Global Forecast System) is run by NOAA in the US. It updates every 6 hours and it's the most widely used model globally. Solid general accuracy, but I noticed pretty quickly that it tends to underestimate temperatures outside the US.
ECMWF IFS comes from the European Centre and is generally considered the world's most accurate model. Updates every 12 hours. In my testing, ECMWF consistently predicted higher temperatures than the other two — and was usually the closest to what actually happened.
ICON is from Germany's DWD weather service. Updates every 6 hours. Good for European cities, but sometimes it'd diverge from the other two models by 2-3°C for no obvious reason.
Here's what a single API call looks like:
https://api.open-meteo.com/v1/forecast?latitude=40.13&longitude=33.00&hourly=temperature_2m&models=gfs_seamless,ecmwf_ifs025,icon_seamless
One call, three models, all the hourly data I need. I cache results for 15 minutes to avoid burning through the daily limit.
What this does in plain English: I'm asking Open-Meteo to give me hour-by-hour temperature predictions from all three models for a specific location. The bot pulls the highest predicted temperature for each day from each model, then uses that to decide whether a Polymarket price looks wrong.
How Weather Underground Determines the Answer
This part is easy to overlook but it decides whether you win or lose.
Every Polymarket weather market resolves based on data from Weather Underground, and each city has a designated airport weather station. Not a random sensor downtown. A specific airport, identified by its ICAO code.
Some examples:
| City | Airport | ICAO Code |
|---|---|---|
| Seoul | Incheon International | RKSI |
| Ankara | Esenboğa International | LTAC |
| Wellington | Wellington International | NZWN |
| Paris | Charles de Gaulle | LFPG |
| Buenos Aires | Ministro Pistarini | SAEZ |
When I first set up the bot, I was feeding it city center coordinates. The forecasts were off by 1-2°C because airports sit on the outskirts, surrounded by open tarmac, and experience different microclimates than downtown. Switching to exact airport coordinates was one of those small fixes that made a noticeable difference.
One more thing — I covered this in Episode 1, but it matters here too: Weather Underground truncates temperatures to whole degrees. 10.9°C becomes 10°C. This means my bot needs to predict the correct integer bucket, not just get "close." A forecast of 10.7°C and an actual of 11.0°C are only 0.3°C apart in the real world, but they land in different buckets. Different bucket means zero payout.
What the Bot Actually Does With the Data
The scan cycle runs every 5 minutes. Here's the process, roughly in the order I built it:
First, the bot fetches hourly forecasts from all three models for each city. From the hourly data, it pulls the predicted daily maximum — the highest temperature any hour of the day is expected to hit.
Then comes the part that took me a few painful losses to figure out. My first instinct was to average the three models: (GFS + ECMWF + ICON) / 3. That felt like the "smart" approach. It wasn't. GFS and ICON consistently pulled the average down, and the actual temperature almost always came in higher. I'll get into the full failure data in Episode 3, but the short version is: I switched to using the model maximum — the highest value among the three — and accuracy jumped immediately.
After getting the model maximum, the bot applies a city-specific bias correction. Some cities have a consistent gap between what the models predict and what actually gets recorded. Ankara, for example, gets a +0.5°C adjustment because all three models systematically underpredict there. Other cities like Paris and Buenos Aires don't need any correction at all.
The adjusted forecast points to a specific temperature bucket on Polymarket. If that bucket's YES price is below $0.20, that's a potential buy. If it's above $0.20, the bot checks one bucket below as a fallback — sometimes the real temperature lands in the adjacent bucket, and if that one's cheap, it's worth a shot.
Finally, the bot checks model agreement. If all three models are within 1.5°C of each other, that's high confidence. If they're spread 1.5-3.0°C apart, that's medium. Over 3.0°C spread? Skip it entirely. I learned this the hard way — when models disagree by that much, you're basically flipping a coin.
Why I Dropped US Cities
This was the decision I didn't expect to make.
When I started, I assumed NYC, Chicago, and Miami would be the best markets to trade. Highest volume, most liquidity, most familiar cities. I was wrong on every count that mattered.
The problem is competition. Most weather trading bots — including several popular open-source ones — only scan US cities using NOAA data. When a good opportunity appears in Chicago, it gets scooped up in seconds. By the time my bot spotted a mispriced bucket, some faster bot had already bought it.
But I was also looking at my forecast accuracy data. US cities were terrible. Chicago and Seattle had 4-5°F prediction errors. That's not a rounding issue — that's a wrong-bucket-every-time issue. The models just aren't as accurate for these locations' specific airport microclimates.
Non-US cities told a completely different story. Ankara averaged under 1°C error with the right model selection. Wellington and Buenos Aires were similar. Less bot competition meant mispricing lasted minutes to hours instead of seconds. Lower volume, sure — but still enough for $1-2 bets. And the European models (ECMWF, ICON) are naturally more accurate for these regions.
There was one more advantage I hadn't considered: time zones. Ankara's market prices are set mostly by US-based traders who are asleep during Ankara's morning hours. My bot, running 24/7, could catch opportunities that showed up at 3 AM Eastern time and sat untouched for hours.
So I dropped Chicago and Seattle from my city list. Ankara became my primary market. It felt counterintuitive at the time — betting on weather in a Turkish city I'd never visited — but the data was clear.
Key Takeaways
- Three free weather models (GFS, ECMWF, ICON) through one Open-Meteo API call. No key, no cost, 10,000 calls/day.
- Weather Underground resolves using specific airport stations. Use airport coordinates, not city center — cost me 1-2°C of accuracy before I figured that out.
- Model maximum beats model average. I'll show the full failure data in Episode 3.
- Non-US cities (Ankara, Wellington, Buenos Aires) had less competition, better model accuracy, and time zone advantages. US cities were a trap.
What's Next
The pipeline was built. The city list was set. The confidence filters were in place. I felt good about it. Episode 3 is the part where all of that confidence ran into a wall — seven trades, seven losses, and every single actual temperature coming in higher than my prediction.
← Previous: Episode 1: How I Started Betting on Temperature Next: Episode 3: I Lost 7 Straight Weather Trades on Polymarket →
More updates on the way. If you're working on something similar or found a smarter way to do it, drop it in the comments — the more we share, the faster we all move.
Disclaimer: This blog documents my personal learning journey. Nothing here is financial advice.
Comments
Post a Comment