The VIX — the CBOE Volatility Index — is the single most actionable indicator for options traders. When VIX spikes, options premiums explode. When VIX collapses, premium sellers get paid. Most traders watch it manually. This guide shows you how to automate it.
We'll use the SignalSage API on RapidAPI to pull live VIX-based signals and build a Python trading dashboard that tells you exactly what to do based on current market conditions.
What the Dashboard Does
- Reads the current VIX regime (low/elevated/high)
- Recommends the right options strategy for the environment
- Identifies high-probability trade setups
- Tracks the volatility magnet (mean-reversion signal)
- Outputs a ranked action list every morning
Prerequisites
- Python 3.8+
- RapidAPI account (free tier works)
- Basic options knowledge (know what an iron condor is)
Step 1: Get the API Key
- Sign up at RapidAPI
- Search "SignalSage"
- Subscribe to the free BASIC plan
- Copy your
X-RapidAPI-Key
Step 2: Install Dependencies
pip install requests rich schedule
Step 3: The Dashboard
import requests
import schedule
import time
from datetime import datetime
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich import box
console = Console()
RAPIDAPI_KEY = "YOUR_RAPIDAPI_KEY_HERE"
BASE_URL = "https://signalsage.p.rapidapi.com"
HEADERS = {
"X-RapidAPI-Key": RAPIDAPI_KEY,
"X-RapidAPI-Host": "signalsage.p.rapidapi.com"
}
def get_playbook():
r = requests.get(f"{BASE_URL}/api/playbook", headers=HEADERS)
r.raise_for_status()
return r.json()
def get_setups():
r = requests.get(f"{BASE_URL}/api/setups", headers=HEADERS)
r.raise_for_status()
return r.json()
def get_magnet():
r = requests.get(f"{BASE_URL}/api/magnet", headers=HEADERS)
r.raise_for_status()
return r.json()
def vix_color(vix: float) -> str:
if vix < 15:
return "green"
elif vix < 20:
return "yellow"
elif vix < 30:
return "orange3"
return "red"
def render_dashboard():
console.clear()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
console.print(f"\n[bold cyan]SignalSage Options Dashboard[/bold cyan] [dim]{now}[/dim]\n")
# --- PLAYBOOK ---
pb = get_playbook()
data = pb.get("data", {})
overview = data.get("marketOverview", {})
vix = overview.get("vix", 0)
vix_analysis = overview.get("vixAnalysis", "")
key_levels = overview.get("keyLevels", "")
top_setups = data.get("topSetups", [])
color = vix_color(vix)
console.print(Panel(
f"[{color}]VIX: {vix:.2f}[/{color}] {vix_analysis}\n\n[dim]{key_levels}[/dim]",
title="[bold]Market Overview[/bold]",
border_style=color
))
# --- SETUPS ---
setups = get_setups()
setup_list = setups.get("high_conviction_setups", [])
if setup_list:
table = Table(box=box.ROUNDED, show_header=True, header_style="bold magenta")
table.add_column("Symbol", style="cyan", width=8)
table.add_column("Strategy", width=20)
table.add_column("Direction", width=12)
table.add_column("Confidence", justify="right")
table.add_column("Notes", width=35)
for s in setup_list[:8]:
conf = s.get("confidence", 0)
conf_color = "green" if conf > 0.7 else "yellow" if conf > 0.5 else "white"
table.add_row(
s.get("symbol", ""),
s.get("strategy", ""),
s.get("direction", ""),
f"[{conf_color}]{conf:.0%}[/{conf_color}]",
s.get("notes", "")[:35]
)
console.print("\n[bold]High-Conviction Setups[/bold]")
console.print(table)
else:
console.print(Panel(
"[yellow]No high-conviction setups right now.\nVIX regime suggests waiting for better entries.[/yellow]",
title="Setups",
border_style="yellow"
))
# --- MAGNET ---
magnet = get_magnet()
magnet_text = magnet.get("magnetAnalysis", "")
# Show first 400 chars of the magnet analysis
console.print(Panel(
magnet_text[:400] + ("..." if len(magnet_text) > 400 else ""),
title="[bold]Volatility Magnet[/bold]",
border_style="blue"
))
console.print("\n[dim]Refreshes every 5 minutes. Press Ctrl+C to exit.[/dim]")
def run():
render_dashboard()
schedule.every(5).minutes.do(render_dashboard)
while True:
schedule.run_pending()
time.sleep(1)
if __name__ == "__main__":
try:
run()
except KeyboardInterrupt:
console.print("\n[dim]Dashboard stopped.[/dim]")
Sample Output
SignalSage Options Dashboard 2026-06-06 09:31:00
╭─────────────────────── Market Overview ───────────────────────╮
│ VIX: 21.51 21.51 → IV elevated, avoid new trades │
│ │
│ SPY key levels: 580 / 570 / 560 │
╰────────────────────────────────────────────────────────────────╯
High-Conviction Setups
╭────────┬──────────────────────┬────────────┬────────────┬─────────────────────────────────────╮
│ Symbol │ Strategy │ Direction │ Confidence │ Notes │
├────────┼──────────────────────┼────────────┼────────────┼─────────────────────────────────────┤
│ SPY │ Iron Condor │ Neutral │ 78% │ VIX elevated, sell both wings │
│ QQQ │ Put Credit Spread │ Bullish │ 65% │ Support held at 200MA │
╰────────┴──────────────────────┴────────────┴────────────┴─────────────────────────────────────╯
VIX Regime Cheat Sheet
| VIX Level | Regime | Best Strategy |
|---|---|---|
| < 15 | Low volatility | Buy straddles, avoid premium selling |
| 15–20 | Normal | Iron condors, defined-risk spreads |
| 20–30 | Elevated | Short strangles with wide strikes |
| > 30 | Fear spike | Sell puts on pullbacks, cash-secured |
The general rule: sell premium when VIX is high, buy it when VIX is low. SignalSage automates this regime detection so you don't have to track it manually every morning.
Automate the Morning Brief
import smtplib
from email.mime.text import MIMEText
def email_brief(to_addr: str):
pb = get_playbook()
vix = pb["data"]["marketOverview"]["vix"]
analysis = pb["data"]["marketOverview"]["vixAnalysis"]
body = f"VIX: {vix}\n{analysis}\n\nRun your dashboard for full setups."
msg = MIMEText(body)
msg["Subject"] = f"Morning Options Brief — VIX {vix}"
msg["From"] = "your@gmail.com"
msg["To"] = to_addr
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as s:
s.login("your@gmail.com", "app-password")
s.send_message(msg)
Run it at 9 AM with cron: 0 9 * * 1-5 python brief.py
The API is live on RapidAPI — search "SignalSage" by Circle of Wizards. Free tier, no credit card required. PRO unlocks higher rate limits for algorithmic traders running this on a schedule.
Top comments (0)