Build AI Trade Alerts with an API: Automated Market Commentary for Developers | FlashAlpha

Build AI Trade Alerts with an API: Automated Market Commentary for Developers

How to build automated AI trade alerts and market commentary using the FlashAlpha API and MCP server. Get natural language market narratives, regime change alerts, VRP signals, and exposure shift notifications. Connect AI agents like Claude, Cursor, and Windsurf to live options data via MCP.

T
Tomasz Dobrowolski Quant Engineer
Mar 29, 2026
38 min read
AI TradeAlerts MCP API Python DeveloperGuide OptionsAnalytics Automation

If you're searching for an AI trade alerts API, an automated market commentary data source, or trying to figure out how to build an options AI agent that generates real-time market briefings, this is the guide. The FlashAlpha API provides both structured analytics and natural language narratives, and the MCP server lets AI agents query live options data natively.


Three Approaches to AI Trade Alerts

There are three ways to build AI-powered market alerts with the FlashAlpha API, each at a different level of abstraction:

  1. API polling + your own detection logic. Poll structured endpoints (exposure summary, VRP, levels), detect regime changes or threshold breaches in your code, and fire alerts through Slack, Discord, or email. Maximum control, more code.
  2. Narrative endpoint for pre-built commentary. The /v1/exposure/narrative/{symbol} endpoint returns natural language market analysis generated from structured data — regime context, GEX changes, key levels, OI flow, vanna/charm interpretation, and outlook. One call gives you a ready-to-send market brief.
  3. MCP for AI-agent-driven analysis. Connect Claude, Cursor, Windsurf, or any MCP-compatible agent to the FlashAlpha MCP server. The agent pulls live data, reasons over it, and generates custom analysis. No polling loop, no detection code — the agent IS the alerting system.

This guide covers all three. Start with whichever fits your stack.

Endpoints Used in This Guide

EndpointTierWhat It Returns
/v1/exposure/narrative/{symbol}Growth+Natural language market narrative with structured data: regime, GEX changes, key levels context, OI flow, vanna/charm interpretation, outlook
/v1/exposure/summary/{symbol}Growth+Net GEX/DEX/VEX/CHEX, gamma regime, dealer hedging estimates, verbal interpretation
/v1/vrp/{symbol}AlphaVRP z-score, percentile, strategy scores, warnings, macro context
/v1/exposure/levels/{symbol}FreeGamma flip, call wall, put wall, max gamma strikes, highest OI
/v1/stock/{symbol}/summaryFree+Comprehensive stock summary with live quote data

Natural language market narratives + structured analytics for 6,000+ symbols

One API call returns a full market brief. Free tier available.

Get API Access

Quick Start: Your First Narrative Call

from flashalpha import FlashAlpha

fa = FlashAlpha("YOUR_KEY")
narrative = fa.narrative("SPY")

print(narrative['narrative'])
print(f"Regime:  {narrative['regime']}")
print(f"Outlook: {narrative['outlook']}")
import { FlashAlpha } from 'flashalpha';

const fa = new FlashAlpha('YOUR_KEY');
const narrative = await fa.narrative('SPY');

console.log(narrative.narrative);
console.log(`Regime: ${narrative.regime}`);
console.log(`Outlook: ${narrative.outlook}`);
using FlashAlpha;

var fa = new FlashAlphaClient("YOUR_KEY");
var narrative = await fa.NarrativeAsync("SPY");

Console.WriteLine(narrative.Narrative);
Console.WriteLine($"Regime: {narrative.Regime}");
fa := flashalpha.NewClient("YOUR_KEY")
narrative, _ := fa.Narrative(ctx, "SPY")

fmt.Println(narrative.Narrative)
fmt.Printf("Regime: %s\n", narrative.Regime)
FlashAlphaClient fa = new FlashAlphaClient("YOUR_KEY");
JsonObject narrative = fa.narrative("SPY");

System.out.println(narrative.getString("narrative"));
System.out.println("Regime: " + narrative.getString("regime"));
curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/exposure/narrative/SPY"
$ pip install flashalpha  |  npm install flashalpha  |  dotnet add package FlashAlpha  |  go get github.com/FlashAlpha-lab/flashalpha-go

Alert Use Cases

Each of these patterns polls one or two endpoints and fires an alert when a condition is met. The detection logic is simple because the API does the heavy computation.

1. Regime Change Alerts

The gamma regime flip is one of the highest-signal events in options analytics. When the market crosses from positive gamma (dealers dampen moves) to negative gamma (dealers amplify moves), the character of price action changes fundamentally. Detect it by polling the exposure summary endpoint.

from flashalpha import FlashAlpha
import time

fa = FlashAlpha("YOUR_KEY")
previous_regime = None

while True:
    summary = fa.exposure_summary("SPY")
    current_regime = summary['regime']

    if previous_regime and current_regime != previous_regime:
        send_alert(
            title="SPY REGIME CHANGE",
            message=f"Gamma regime flipped: {previous_regime} -> {current_regime}\n"
                    f"Net GEX: ${summary['exposures']['net_gex']:,.0f}\n"
                    f"Gamma flip level: {summary['gamma_flip']}\n"
                    f"Gamma read: {summary['interpretation']['gamma']}"
        )

    previous_regime = current_regime
    time.sleep(300)  # 5 min polling

2. VRP Signal Alerts

Fire an alert when the VRP z-score crosses a threshold, indicating unusually rich or thin premium.

vrp = fa.vrp("SPY")
z = vrp['vrp']['z_score']

if z > 1.5:
    send_alert(
        title="SPY VRP RICH",
        message=f"VRP z-score: {z:.2f} ({vrp['vrp']['percentile']}th percentile)\n"
                f"Harvest score: {vrp['net_harvest_score']:.2f}\n"
                f"Best strategy: {max(vrp['strategy_scores'], key=lambda k: vrp['strategy_scores'][k] or 0)}"
    )
elif z < -1.0:
    send_alert(
        title="SPY VRP THIN",
        message=f"VRP z-score: {z:.2f} - premium selling unfavorable"
    )

3. Key Level Breach Alerts

Monitor whether price crosses critical dealer positioning levels: the gamma flip, call wall, or put wall.

resp = fa.exposure_levels("SPY")
levels = resp['levels']
price = resp['underlying_price']

gamma_flip = levels['gamma_flip']
call_wall = levels['call_wall']
put_wall = levels['put_wall']

if price < gamma_flip:
    send_alert(
        title="SPY BELOW GAMMA FLIP",
        message=f"Price ${price:.2f} crossed below gamma flip ${gamma_flip:.2f}\n"
                f"Entering negative gamma territory. Expect amplified moves.\n"
                f"Put wall support: ${put_wall:.2f}"
    )

if price > call_wall:
    send_alert(
        title="SPY ABOVE CALL WALL",
        message=f"Price ${price:.2f} broke above call wall ${call_wall:.2f}\n"
                f"Dealer hedging pressure reduced. Breakout potential."
    )

4. Morning Market Briefing

Pull the narrative endpoint for your watchlist at market open and send a consolidated brief.

watchlist = ["SPY", "QQQ", "TSLA", "NVDA", "AAPL"]
briefing = []

for sym in watchlist:
    try:
        resp = fa.narrative(sym)
        n = resp['narrative']
        briefing.append(f"**{sym}** ({n['data']['regime']})\n{n['outlook']}\n")
    except Exception as e:
        briefing.append(f"**{sym}** - unavailable: {e}\n")

send_alert(
    title="Morning Market Briefing",
    message="\n".join(briefing)
)

5. Unusual Exposure Shift Detection

Compare today's GEX to a stored value from the previous session. Large day-over-day changes in net GEX often precede volatility regime shifts.

import json, os

STATE_FILE = "gex_state.json"

def load_state():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f)
    return {}

def save_state(state):
    with open(STATE_FILE, "w") as f:
        json.dump(state, f)

state = load_state()
summary = fa.exposure_summary("SPY")
current_gex = summary['exposures']['net_gex']

if 'SPY' in state:
    prev_gex = state['SPY']
    change_pct = ((current_gex - prev_gex) / abs(prev_gex)) * 100 if prev_gex != 0 else 0

    if abs(change_pct) > 30:
        send_alert(
            title="SPY GEX SHIFT",
            message=f"Net GEX changed {change_pct:+.0f}% day-over-day\n"
                    f"Previous: ${prev_gex:,.0f}\n"
                    f"Current:  ${current_gex:,.0f}\n"
                    f"Regime:   {summary['regime']}"
        )

state['SPY'] = current_gex
save_state(state)

Complete Python Alerting Script

Here's a production-ready script that combines all five alert types and sends notifications via Slack, Discord, or email. Run it on a cron job or a scheduled task.

import os, json, time, requests
from datetime import datetime
from flashalpha import FlashAlpha

# --- Configuration ---
API_KEY = os.environ["FLASHALPHA_API_KEY"]
SLACK_WEBHOOK = os.environ.get("SLACK_WEBHOOK_URL")
DISCORD_WEBHOOK = os.environ.get("DISCORD_WEBHOOK_URL")
WATCHLIST = ["SPY", "QQQ", "TSLA", "NVDA", "AAPL"]
STATE_FILE = "alert_state.json"

fa = FlashAlpha(API_KEY)

# --- Notification ---
def send_alert(title, message):
    timestamp = datetime.now().strftime("%H:%M:%S")
    full_msg = f"[{timestamp}] {title}\n{message}"
    print(full_msg)

    if SLACK_WEBHOOK:
        requests.post(SLACK_WEBHOOK, json={"text": full_msg})

    if DISCORD_WEBHOOK:
        requests.post(DISCORD_WEBHOOK, json={"content": full_msg})

# --- State Management ---
def load_state():
    if os.path.exists(STATE_FILE):
        with open(STATE_FILE) as f:
            return json.load(f)
    return {"regimes": {}, "gex": {}}

def save_state(state):
    with open(STATE_FILE, "w") as f:
        json.dump(state, f)

# --- Alert Logic ---
def check_alerts():
    state = load_state()
    alerts_fired = 0

    for sym in WATCHLIST:
        try:
            # Pull all data
            summary = fa.exposure_summary(sym)
            levels_resp = fa.exposure_levels(sym)
            levels = levels_resp['levels']
            price = levels_resp['underlying_price']

            # 1. Regime change
            current_regime = summary['regime']
            prev_regime = state['regimes'].get(sym)
            if prev_regime and current_regime != prev_regime:
                send_alert(f"{sym} REGIME CHANGE",
                    f"{prev_regime} -> {current_regime}\n"
                    f"Net GEX: ${summary['exposures']['net_gex']:,.0f}")
                alerts_fired += 1
            state['regimes'][sym] = current_regime

            # 2. Key level breach
            gamma_flip = levels['gamma_flip']
            if price < gamma_flip and state.get(f'{sym}_above_flip', True):
                send_alert(f"{sym} BELOW GAMMA FLIP",
                    f"Price ${price:.2f} < flip ${gamma_flip:.2f}")
                alerts_fired += 1
            state[f'{sym}_above_flip'] = price >= gamma_flip

            # 3. GEX shift
            current_gex = summary['exposures']['net_gex']
            prev_gex = state['gex'].get(sym)
            if prev_gex and prev_gex != 0:
                change = ((current_gex - prev_gex) / abs(prev_gex)) * 100
                if abs(change) > 30:
                    send_alert(f"{sym} GEX SHIFT",
                        f"Net GEX {change:+.0f}% day-over-day\n"
                        f"${prev_gex:,.0f} -> ${current_gex:,.0f}")
                    alerts_fired += 1
            state['gex'][sym] = current_gex

            # 4. VRP signal (Alpha plan only)
            try:
                vrp = fa.vrp(sym)
                z = vrp['vrp']['z_score']
                if z > 1.5:
                    send_alert(f"{sym} VRP RICH",
                        f"z={z:.2f} pctl={vrp['vrp']['percentile']}th "
                        f"harvest={vrp['net_harvest_score']:.2f}")
                    alerts_fired += 1
            except Exception:
                pass  # VRP requires Alpha plan

        except Exception as e:
            print(f"Error checking {sym}: {e}")

    save_state(state)
    print(f"\nScan complete. {alerts_fired} alert(s) fired for {len(WATCHLIST)} symbols.")

if __name__ == "__main__":
    check_alerts()

Run this every 5 minutes during market hours with a cron entry like */5 9-16 * * 1-5 python3 alert_scanner.py or a systemd timer.

$ pip install flashalpha
>>> fa = FlashAlpha("YOUR_KEY")
>>> n = fa.narrative("SPY")
{"regime": "positive_gamma", "narrative": "SPY is pinned in positive gamma territory...", "outlook": "..."}

AI Agent Integration via MCP

The Model Context Protocol (MCP) lets AI agents call FlashAlpha tools directly. Instead of writing polling loops and detection logic, you describe what you want in natural language and the agent handles the data retrieval, analysis, and formatting. The FlashAlpha MCP server exposes 38 tools (21 live + 17 historical replay) including GetNarrative, GetExposureSummary, GetLevels, GetMaxPain, GetVolatility, GetGex, GetDex, GetVex, RunScreener, and more.

Claude Desktop

Add the FlashAlpha MCP server to your Claude Desktop configuration file (claude_desktop_config.json):

{
  "mcpServers": {
    "flashalpha": {
      "url": "https://lab.flashalpha.com/mcp"
    }
  }
}

Claude Desktop will discover all 38 tools (21 live + 17 historical replay) automatically. Ask questions like "What's the dealer positioning on SPY right now?" and Claude will call the appropriate endpoint, interpret the data, and give you a natural language answer grounded in live analytics.

Claude Code

Add the MCP server from the command line:

claude mcp add flashalpha --transport http https://lab.flashalpha.com/mcp

Now Claude Code can query live options data as part of its coding workflow. Ask it to "check the gamma regime on TSLA before I deploy this strategy" and it will pull the data inline.

Cursor and Windsurf

Both Cursor and Windsurf support MCP servers. Add the same configuration to your Cursor .cursor/mcp.json or Windsurf MCP settings:

{
  "mcpServers": {
    "flashalpha": {
      "url": "https://lab.flashalpha.com/mcp"
    }
  }
}

The FlashAlpha MCP server uses Streamable HTTP transport (MCP protocol version 2025-03-26), which is supported natively by all major MCP clients without requiring a local proxy or SSE adapter.

Example Prompts for AI Agents

Once connected, try these prompts with any MCP-compatible agent:

  • "What's the dealer positioning on SPY right now?" — The agent calls GetExposureSummary and GetLevels, then interprets the regime, net GEX, gamma flip, and key walls.
  • "Which of my watchlist stocks have the richest VRP?" — The agent loops through your symbols calling GetVolatility (or the VRP endpoint), ranks by z-score, and highlights harvest-favorable setups.
  • "Is it safe to sell premium on TSLA today?" — The agent pulls the narrative, VRP, and exposure data, evaluates the gamma regime, checks for event risk, and gives a reasoned yes/no with supporting data.
  • "Give me a morning briefing for SPY, QQQ, and IWM" — The agent calls GetNarrative for each symbol and synthesizes a consolidated multi-asset brief.
  • "Compare the vanna exposure on NVDA vs TSLA" — The agent calls GetVex for both symbols and summarizes which has more directional sensitivity to IV changes.

The agent doesn't just fetch data — it reasons over it. That's the difference between an API dashboard and an AI-powered alerting system. The MCP connection turns your coding assistant into an options analyst with real-time data access.

Building a Daily AI Market Report

Combine the narrative, VRP, and exposure endpoints to generate a multi-section daily report. This is the foundation for an automated market newsletter or internal trading desk briefing.

from flashalpha import FlashAlpha
from datetime import datetime

fa = FlashAlpha("YOUR_KEY")

def generate_daily_report(symbols):
    report = []
    report.append(f"# Daily Market Report - {datetime.now().strftime('%Y-%m-%d %H:%M ET')}\n")

    for sym in symbols:
        report.append(f"\n## {sym}\n")

        # Section 1: Narrative overview
        try:
            n = fa.narrative(sym)['narrative']
            report.append(f"### Market Narrative\n{n['regime']}\n\n{n['key_levels']}\n")
            report.append(f"**Regime:** {n['data']['regime']} | **Outlook:** {n['outlook']}\n")
        except Exception as e:
            report.append(f"Narrative unavailable: {e}\n")

        # Section 2: Key levels
        try:
            levels = fa.exposure_levels(sym)['levels']
            report.append(f"### Key Levels\n")
            report.append(f"- Gamma flip: ${levels['gamma_flip']:.2f}\n")
            report.append(f"- Call wall:  ${levels['call_wall']:.2f}\n")
            report.append(f"- Put wall:   ${levels['put_wall']:.2f}\n")
        except Exception as e:
            report.append(f"Levels unavailable: {e}\n")

        # Section 3: VRP assessment
        try:
            vrp = fa.vrp(sym)
            z = vrp['vrp']['z_score']
            report.append(f"### Volatility Risk Premium\n")
            report.append(f"- Z-score: {z:.2f} ({vrp['vrp']['percentile']}th percentile)\n")
            report.append(f"- Harvest score: {vrp['net_harvest_score']:.2f}\n")
            best = max(vrp['strategy_scores'], key=lambda k: vrp['strategy_scores'][k] or 0)
            report.append(f"- Top strategy: {best} ({vrp['strategy_scores'][best]}/100)\n")
            if vrp['warnings']:
                report.append(f"- Warnings: {', '.join(vrp['warnings'])}\n")
        except Exception:
            report.append(f"VRP requires Alpha plan.\n")

        # Section 4: Exposure summary
        try:
            s = fa.exposure_summary(sym)
            ex = s['exposures']
            report.append(f"### Exposure\n")
            report.append(f"- Net GEX: ${ex['net_gex']:,.0f}\n")
            report.append(f"- Net DEX: ${ex['net_dex']:,.0f}\n")
            report.append(f"- Regime:  {s['regime']}\n")
        except Exception as e:
            report.append(f"Summary unavailable: {e}\n")

    return "\n".join(report)

report = generate_daily_report(["SPY", "QQQ", "TSLA", "NVDA"])
print(report)

# Send via email, Slack, or save to file
with open(f"report_{datetime.now().strftime('%Y%m%d')}.md", "w") as f:
    f.write(report)

Run this at 9:35 AM ET (5 minutes after market open, once data has populated) and at 3:55 PM ET (pre-close snapshot) for a two-report daily workflow. The narrative endpoint handles the heavy lifting of turning structured data into readable analysis.

Webhook and Polling Patterns

The FlashAlpha API is pull-based (polling), not push-based (webhooks). Here are the patterns that work well for alerting systems.

Rate Limit Awareness

Every plan has a daily request limit. An alerting system that polls 5 symbols every 5 minutes uses 5 endpoints x 5 symbols x 78 intervals (6.5 hours) = 1,950 requests/day. That fits comfortably in the Growth plan (2,500 req/day). Reduce polling frequency or watchlist size for lower tiers.

PlanDaily LimitSuggested Polling
Free5 req/daySingle morning briefing for 1 symbol
Basic100 req/day3 symbols, 3 checks/day (open, midday, close)
Growth2,500 req/day20 symbols, 5-min polling, all endpoints
AlphaUnlimitedFull universe, continuous polling

Efficient Polling

# Use exposure summary as the primary poll - it returns regime, GEX, and interpretation
# Only call VRP and narrative when summary triggers a signal

summary = fa.exposure_summary(sym)

# Only fetch narrative when regime changes or at scheduled briefing times
if regime_changed(summary) or is_briefing_time():
    narrative = fa.narrative(sym)

# Only fetch VRP when regime is positive gamma (favorable for selling)
if summary['regime'] == 'positive_gamma':
    vrp = fa.vrp(sym)

This cascading pattern keeps request counts low by using cheap, fast endpoints as gatekeepers for more expensive ones.

Why Not Build It Yourself?

You can build all of this from raw data. Here's what that involves:

  1. Options chain data source — Raw chains for all strikes and expirations, updated intraday. Budget $200-2,500/mo.
  2. GEX computation engine — Aggregate gamma exposure across all strikes, compute dealer hedging assumptions, determine regime, identify flip levels.
  3. VRP calculation pipeline — ATM IV extraction, realized vol across multiple windows, z-score computation, strategy scoring model.
  4. Natural language generation — Turn structured data into readable narratives. Fine-tune a model or build templates.
  5. Alert detection logic — Regime change detection, threshold monitoring, state management, deduplication.
  6. Notification infrastructure — Slack/Discord/email integration, rate limiting, failure handling.
  7. MCP server — Build and host a Model Context Protocol server so AI agents can access your data.

That's 6+ months of engineering for a single-person team. The FlashAlpha API collapses steps 1-4 into API calls. The MCP server eliminates step 7. You only need to write steps 5 and 6, which is what the complete script above does in ~80 lines of Python.

API Access and Pricing

The narrative endpoint requires the Growth plan (from $239/mo). VRP requires the Alpha plan (from $1,199/mo). Key levels are available on the Free tier. The MCP server is available on all plans — the tools you can access depend on your plan tier.

PlanPriceNarrativeVRPLevelsMCP
Free$0NoNoYesYes
Basicfrom $63/moNoNoYesYes
Growthfrom $239/moYesNoYesYes
Alphafrom $1,199/moYesYesYesYes

To evaluate before committing, the interactive API playground lets you test narrative and exposure calls in the browser. The AI agents page has MCP setup instructions for every supported client.

SDKs available in Python, JavaScript, C#, Go, and Java. All SDKs include typed exceptions (RateLimitError, TierRestrictedError) and automatic retries.

Frequently Asked Questions

The /v1/exposure/narrative/{symbol} endpoint returns a natural language market analysis generated from live structured data. It describes the current gamma regime, recent GEX changes, key level context, open interest flow, vanna/charm interpretation, and forward-looking outlook. It's designed to be sent directly as an alert or embedded in a market report without additional processing.
The MCP server requires authentication. Pass your API key in the MCP client configuration. Free-tier keys work for tools that access free endpoints (GetLevels, GetGex, GetStockSummary). Growth+ keys unlock GetNarrative and GetExposureSummary.
Set up an incoming webhook in Slack or Discord, then POST the alert message as JSON to the webhook URL. The complete alerting script in this guide includes Slack and Discord notification code. For email, use any SMTP library (Python's smtplib, Node's nodemailer).
Claude Desktop, Claude Code, Cursor, Windsurf, and any client that supports the MCP Streamable HTTP transport (protocol version 2025-03-26). The FlashAlpha MCP server exposes 38 tools (21 live + 17 historical replay): GetGex, GetDex, GetVex, GetLevels, GetExposureSummary, GetNarrative, GetMaxPain, GetVolatility, GetStockSummary, GetStockQuote, GetTickers, GetOptionChain, GetAccount, CalculateGreeks, SolveIV, and RunScreener.
Narrative data is generated from live options chains and exposure computations. It updates throughout the trading day. The response includes a timestamp field so your alerting system can verify freshness. Growth plan responses are cached briefly; Alpha plan responses have zero cache.
Yes, with limitations. The Free plan gives you 5 requests/day, which is enough for a single morning briefing using the levels endpoint (gamma flip, call/put walls). For continuous polling and narrative access, you need Growth or Alpha.

Live Market Pulse

Get tick-by-tick visibility into market shifts with full-chain analytics streaming in real time.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Execution-Ready

Instantly send structured orders to Interactive Brokers right from your scan results.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!