Developer Console
Sign in to manage API keys.

Forecast VIX from prediction markets

No prediction market lists VIX directly. PolyBridge synthesises a probability from the markets that do exist: equity drawdown proxies, crude oil, gold, and geopolitical risk.

Published
May 23, 2026
Read time
2 min
Stack
Python · REST

This article uses a saved snapshot from the original VIX stress-monitor example. The probabilities shown below are historical example outputs, not live forecasts.

Setup

Before you begin

Install requests:

pip install requests

Verify the Forecast API:

curl -s -X POST https://api.polybridge.ai/v1/forecast \
  -H "Content-Type: application/json" \
  -d '{"question": "Will the VIX close above 30 at any point in the next 90 days?"}' \
  | python3 -m json.tool

A successful response includes probability, confidence, confidence_interval, and source-market metadata such as markets_used. Displayed source-market counts are derived from the returned source-market list.

{
  "probability": 0.10,
  "confidence": 0.34,
  "confidence_interval": {
    "lower": 0.05,
    "upper": 0.15
  },
  "markets_used": [
    {
      "id": "example-market-id",
      "question": "Example source market question",
      "platform": "polymarket",
      "platform_url": "https://example.com"
    }
  ]
}
The script

Five Forecast API calls

The script asks for one headline VIX forecast, then four driver signals that help explain equity volatility: energy prices, equity drawdowns, safe-haven flows, and shipping disruption. PolyBridge synthesises each probability from whichever prediction markets are relevant, even though none of these questions have a direct listing.

For a current version of this workflow, use a rolling question such as: “Will the VIX close above 30 at any point in the next 90 days?”

pythonstress_monitor.py
import time
import requests

API_URL = "https://api.polybridge.ai/v1/forecast"
TIMEOUT = 75
MAX_RETRIES = 4

HEADLINE = "Will the VIX close above 30 at any point in the next 90 days?"

DRIVERS = [
    (
        "Crude oil > $90 (next quarter)",
        "Will crude oil settle above $90 at any point in the next 90 days?",
    ),
    (
        "SPX drawdown > 10% (next quarter)",
        "Will SPX draw down more than 10% at any point in the next 90 days?",
    ),
    (
        "Gold +10% (next quarter)",
        "Will gold rise more than 10% from its current price at any point in the next 90 days?",
    ),
    (
        "Hormuz regular traffic (next quarter)",
        "Will the Strait of Hormuz be open to regular traffic at the end of the next 90 days?",
    ),
]

def forecast(session, question):
    headers = {"Content-Type": "application/json"}

    for attempt in range(MAX_RETRIES + 1):
        try:
            r = session.post(
                API_URL,
                headers=headers,
                json={"question": question},
                timeout=TIMEOUT,
            )
        except requests.RequestException:
            if attempt >= MAX_RETRIES:
                raise
            time.sleep(min(20.0, 2.0 ** attempt))
            continue

        if r.status_code in (429, 503):
            if attempt >= MAX_RETRIES:
                r.raise_for_status()
            try:
                wait = float(r.headers.get("Retry-After", ""))
            except (TypeError, ValueError):
                wait = min(20.0, 2.0 ** attempt)
            time.sleep(wait)
            continue

        r.raise_for_status()
        return r.json()

    raise RuntimeError(f"Failed after {MAX_RETRIES} retries: {question}")

def bar(p):
    filled = round(p * 20)
    return "█" * filled + "░" * (20 - filled)

with requests.Session() as session:
    result = forecast(session, HEADLINE)
    p = float(result.get("probability", 0))
    print("SIGNAL")
    print(f"{p * 100:>5.1f}%  {bar(p)}  VIX > 30 in 90d")
    print()
    print("HIGHLIGHTED DRIVERS")
    for label, question in DRIVERS:
        result = forecast(session, question)
        p = float(result.get("probability", 0))
        print(f"{p * 100:>5.1f}%  {bar(p)}  {label}")

Run the article script with python3 stress_monitor.py. The article snippet prints a terminal summary. The full GitHub cookbook also writes assets/snapshot.json and renders assets/market-stress-monitor.png.

Forecast snapshot

Headline forecast and driver markets

Read this as the saved output from the original article run, not a live forecast. Its labels keep the original two-month and June 2026 horizons so the displayed probabilities stay tied to the questions that produced them.

Forecast snapshot

PolyBridge Market Stress Monitor

Historical example probabilities from prediction markets.

Headline + drivers
Headline forecast
VIX > 30 (2mo)
Range 15% to 35%
25%
Driver markets
Source market
Crude > $90 (Jun 2026)
Range 85% to 99%
95%
6 source markets
Source market
SPX drawdown > 10% (2mo)
Range 0.1% to 5%
1%
3 source markets
Source market
Gold +10% (2mo)
Range 5% to 15%
8%
6 source markets
Source market
Hormuz reopens (Jun 30, 2026)
Range 12% to 25%
18%
6 source markets
Snapshot 2026-06-03T01:42:45Z · Source: PolyBridge ForecastHistorical example output

In the saved snapshot, the headline result was a 25% probability that the VIX would close above 30 during the original two-month horizon. In that saved output, market stress was a real risk, but not the most likely outcome. The driver rows explain what was moving the example forecast. Oil was the strongest warning signal, with crude above $90 in June 2026 priced at 95%. SPX drawdown risk was low at 1%, gold upside was muted at 8%, and Hormuz reopening by June 30, 2026 at 18% pointed to unresolved shipping and geopolitical risk.

Forecast API

Run the forecast

Call the Forecast API with your own market question.

Read the Forecast docs →