← Back to All Tutorials

Tutorial 10: Polymarket Weather Scanner Beginner-Friendly

Table of Contents
  1. What Does This Scanner Do?
  2. Key Concepts
  3. Code Walkthrough
  4. No API Key Needed!
  5. Dependencies
  6. Glossary

1. What Does This Scanner Do?

This scanner compares Polymarket temperature prediction markets against real weather forecasts to find mispriced markets. If the weather forecast says it'll be 75 degrees tomorrow but the market is pricing it at 70 degrees, that's a potential opportunity.

Simple Analogy: Imagine a sports betting site where people bet on tomorrow's temperature. You have a friend who's a meteorologist with access to 51 weather models. When the betting crowd disagrees with your meteorologist friend, you've found a potentially profitable bet. This scanner automates that comparison for 35+ cities worldwide.

2. Key Concepts

Polymarket Temperature Markets

Polymarket has markets for tomorrow's temperature in major cities. Each market asks a question like "Will NYC be above 75 degrees tomorrow?" with YES/NO binary outcomes.

These markets have "temperature buckets" - ranges like 70-75, 75-80, 80-85 degrees. Each bucket has its own market with its own price.

Open-Meteo API (Free Weather Data)

The scanner uses the Open-Meteo API, which is completely free and doesn't require an API key. It provides:

Ensemble Models

Instead of trusting one weather forecast, the scanner looks at 51 different weather models. If 45 out of 51 models agree it'll be above 75 degrees, that's an 88% probability. If the market price only implies a 60% chance, there might be an edge.

Caching

Weather forecasts don't change every second. The scanner caches forecasts for 1 hour to avoid hammering the API and to keep things fast.

3. Code Walkthrough

1 scrape_temperature_slugs() - Find Available Markets

# Scrape Polymarket's weather page for market URLs
# Returns a list of "slugs" like "nyc-temperature-tomorrow"
tomorrow_slugs = scrape_temperature_slugs()

What it does: Scrapes the Polymarket weather/temperature page to find all available temperature markets for tomorrow. A "slug" is the URL-friendly name of a market.

2 fetch_forecast() - Get Weather Prediction

# Uses Open-Meteo API to get forecast for a city
forecast = fetch_forecast(city)
# Returns: { predicted_temp: 76.3, high: 79, low: 72, ... }

What it does: Calls the free Open-Meteo API with the city's coordinates to get tomorrow's predicted temperature. No API key needed.

3 fetch_ensemble() - Get Probability Estimates

# Gets 51 weather model runs for probability estimation
ensemble = fetch_ensemble(city)
# If 40/51 models say temp > 75 -> ~78% probability

What it does: Fetches 51 different weather model predictions. By counting how many models predict each temperature range, you can estimate the true probability of each outcome.

4 run_scan() - The Main Scan Cycle

def run_scan():
    # Step 1: Find tomorrow's temperature markets
    tomorrow_slugs = scrape_temperature_slugs()

    # Step 2: For each city, fetch market data + weather forecast
    for slug in tomorrow_slugs:
        city = extract_city_from_slug(slug)
        market = parse_market_data(fetch_event_data(slug))
        forecast = fetch_forecast(city)
        ensemble = fetch_ensemble(city)

    # Step 3: Sort by volume and display
    city_data.sort(key=lambda x: x["market"]["volume_24h"])
    print_summary_table(city_data)

What it does: Runs the full scan cycle: find markets, fetch weather data, compare forecasts to market prices, display results sorted by trading volume. Loops every 30 minutes.

4. No API Key Needed!

This scanner is unique because it requires zero API keys:

This makes it the easiest tutorial to run - just install dependencies and go!

5. Dependencies

pip install requests termcolor

That's it! Only two packages needed.

6. Glossary

TermMeaning
SlugA URL-friendly identifier for a Polymarket market
Ensemble ModelMultiple weather prediction models run together for better accuracy
Temperature BucketA temperature range that has its own market (e.g., 70-75 degrees)
Mispriced MarketA market where the price doesn't reflect the true probability
CacheTemporarily storing data to avoid re-fetching it
ScrapingExtracting data from a webpage automatically

7. Full Code: Python to Pseudo-Code Translation

run_scan() - The Main Scan Cycle

# --- PYTHON ---
def run_scan():
    tomorrow_slugs = scrape_temperature_slugs()
    if not tomorrow_slugs:
        print("No temperature markets for tomorrow found!")
        return []
    _load_cache()
    city_data = []
    for slug in tomorrow_slugs:
        city = extract_city_from_slug(slug)
        event_data = fetch_event_data(slug)
        market = parse_market_data(event_data)
        forecast = fetch_forecast(city)
        ensemble = fetch_ensemble(city) if city in CITY_COORDS else None
        city_data.append({"city": city, "market": market,
                          "forecast": forecast, "ensemble": ensemble})
        time.sleep(0.3)
    city_data.sort(key=lambda x: x["market"]["volume_24h"], reverse=True)
    print_summary_table(city_data)
    print_detailed_city(city_data[:TOP_N])
    return city_data

# --- PSEUDO-CODE ---
FUNCTION run_scan():
    STEP 1 - Find tomorrow's temperature markets:
        SCRAPE the Polymarket weather page for market URLs (slugs)
        IF no markets found: PRINT "not posted yet" and STOP

    STEP 2 - Load any cached weather data from previous runs

    STEP 3 - For each city market:
        EXTRACT the city name from the market URL slug
        FETCH the Polymarket market data (prices, volumes, buckets)
        PARSE the market data into structured format
        FETCH the weather forecast from Open-Meteo (free API)
        FETCH ensemble data (51 weather models) if coordinates are known
        SAVE all this data together
        WAIT 0.3 seconds (be polite to the API)

    STEP 4 - Sort results:
        SORT all cities by 24-hour trading volume (most popular first)

    STEP 5 - Display results:
        PRINT a summary table showing all cities side by side
        PRINT detailed analysis for the top N cities
        PRINT full deep-dive for the #1 city

fetch_forecast() - Get Weather Prediction

# --- PYTHON ---
def fetch_forecast(city):
    coords = CITY_COORDS.get(city)
    if not coords: return None
    lat, lon = coords
    url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&daily=temperature_2m_max,temperature_2m_min"
    response = requests.get(url, timeout=10)
    return response.json()

# --- PSEUDO-CODE ---
FUNCTION fetch_forecast(city name):
    LOOK UP the latitude and longitude for this city
    IF coordinates not found: RETURN nothing

    CALL the Open-Meteo free weather API:
        "Give me tomorrow's high and low temperature for these coordinates"

    WAIT up to 10 seconds for a response
    PARSE and RETURN the forecast data
    (No API key needed - this is a free public service)

fetch_ensemble() - Get Probability Estimates

# --- PSEUDO-CODE ---
FUNCTION fetch_ensemble(city name):
    LOOK UP the latitude and longitude for this city

    CALL the Open-Meteo ensemble API:
        "Give me the predictions from ALL 51 weather models"

    FOR each temperature bucket (e.g., 70-75, 75-80 degrees):
        COUNT how many of the 51 models predict this range
        CALCULATE the probability = count / 51

    EXAMPLE: If 40 out of 51 models say temperature > 75:
        Probability of >75 degrees = 40/51 = 78.4%

    RETURN all the probability estimates

main() - Infinite Loop

# --- PYTHON ---
def main():
    while True:
        run_scan()
        remaining = REFRESH_MINUTES * 60
        while remaining > 0:
            time.sleep(COUNTDOWN_INTERVAL)
            remaining -= COUNTDOWN_INTERVAL

# --- PSEUDO-CODE ---
FUNCTION main():
    LOOP FOREVER:
        RUN a complete scan (find markets, get forecasts, compare, display)
        WAIT 30 minutes
        THEN RUN another scan