You'll create a professional-grade options flow monitoring system that tracks unusual trading activity and sends automated alerts when large trades occur. This tutorial takes approximately 3-4 hours to complete and requires intermediate Python knowledge.

Key Takeaways

  • Build a complete options monitoring system using Python 3.9+ and free Polygon.io API access
  • Detect unusual options activity with volume thresholds 3x above average daily levels
  • Automate monitoring with 15-minute intervals and email alerts for significant trades

What You'll Need

  • Python 3.9 or higher installed on your system
  • Free Polygon.io API account (provides 5 API calls per minute)
  • Gmail account for automated email alerts
  • Code editor like VS Code or PyCharm
  • Basic understanding of options trading concepts

Time estimate: 3-4 hours | Difficulty: Intermediate

Step-by-Step Instructions

Step 1: Install Required Python Libraries

Open your terminal or command prompt and install the necessary packages using pip. Run these commands one at a time:

pip install requests pandas matplotlib seaborn yagmail schedule datetime pytz

These libraries handle API requests, data processing, visualization, email notifications, and task scheduling. The requests library manages HTTP calls to Polygon.io, while pandas processes the options data efficiently. Yagmail simplifies Gmail integration for alerts.

Step 2: Set Up Your Polygon.io API Access

Visit Polygon.io's signup page and create a free account. Navigate to your dashboard and copy your API key from the "API Keys" section.

Create a new Python file called config.py and add your credentials:

POLYGON_API_KEY = "your_api_key_here"
GMAIL_USER = "your_email@gmail.com"
GMAIL_APP_PASSWORD = "your_16_char_app_password"
ALERT_RECIPIENTS = ["trader1@email.com", "trader2@email.com"]

The free Polygon.io tier provides 5 API calls per minute, which limits you to monitoring about 50-75 stock symbols efficiently. For Gmail integration, you'll need to generate an app-specific password through your Google Account security settings.

Step 3: Write the Core Options Data Fetcher

Create options_fetcher.py with this function to retrieve options chain data:

import requests
import pandas as pd
from datetime import datetime, timedelta
from config import POLYGON_API_KEY

class OptionsFlowMonitor:
    def __init__(self):
        self.api_key = POLYGON_API_KEY
        self.base_url = "https://api.polygon.io"

    def get_options_chain(self, symbol, expiry_date):
        url = f"{self.base_url}/v3/reference/options/contracts"
        params = {
            "underlying_ticker": symbol,
            "expiration_date": expiry_date,
            "apikey": self.api_key,
            "limit": 1000
        }
        response = requests.get(url, params=params)
        return response.json()

This function queries Polygon.io's options contracts endpoint for a specific underlying symbol and expiration date. The API returns detailed contract information including strike prices, option types, and trading volumes. Setting the limit to 1000 ensures you capture the full options chain for most stocks.

a computer screen with a lot of data on it
Photo by Lukas / Unsplash

Step 4: Filter for Unusual Volume and Open Interest

Add this method to your OptionsFlowMonitor class to identify unusual trading activity:

def detect_unusual_activity(self, options_data, volume_threshold=3.0):
    unusual_trades = []
    contracts = options_data.get('results', [])

    for contract in contracts:
        daily_volume = contract.get('day_volume', 0)
        open_interest = contract.get('open_interest', 0)
        avg_volume = contract.get('average_volume_30d', 1)

        if daily_volume > (avg_volume * volume_threshold) and daily_volume > 100:
            volume_ratio = daily_volume / max(avg_volume, 1)
            oi_ratio = daily_volume / max(open_interest, 1)

            unusual_trades.append({
                'ticker': contract.get('ticker'),
                'strike': contract.get('strike_price'),
                'expiry': contract.get('expiration_date'),
                'volume': daily_volume,
                'volume_ratio': round(volume_ratio, 2),
                'oi_ratio': round(oi_ratio, 2)
            })

    return sorted(unusual_trades, key=lambda x: x['volume_ratio'], reverse=True)

This algorithm identifies options contracts with volume exceeding 3x their 30-day average and minimum daily volume of 100 contracts. The volume-to-open-interest ratio helps distinguish between new position building versus existing position adjustments. Higher ratios often indicate informed trading activity.

Step 5: Set Up Automated Email Alerts

Create the alert system by adding this method to send notifications when significant activity occurs:

import yagmail
from config import GMAIL_USER, GMAIL_APP_PASSWORD, ALERT_RECIPIENTS

def send_alert(self, unusual_trades):
    if not unusual_trades:
        return

    yag = yagmail.SMTP(GMAIL_USER, GMAIL_APP_PASSWORD)
    timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

    subject = f"Options Flow Alert - {len(unusual_trades)} Unusual Trades"
    body = f"Detected at {timestamp}:\n\n"

    for trade in unusual_trades[:10]: # Top 10 alerts
        body += f"• {trade['ticker']} ${trade['strike']} {trade['expiry']}\n"
        body += f" Volume: {trade['volume']} ({trade['volume_ratio']}x avg)\n"
        body += f" Vol/OI Ratio: {trade['oi_ratio']}\n\n"

    try:
        yag.send(ALERT_RECIPIENTS, subject, body)
        print(f"Alert sent: {len(unusual_trades)} trades detected")
    except Exception as e:
        print(f"Email alert failed: {e}")

The alert system limits notifications to the top 10 most unusual trades to avoid email spam while ensuring you don't miss significant activity. Each alert includes the option symbol, strike price, expiration date, current volume, and comparative ratios.

Step 6: Create a Data Visualization Dashboard

Build a simple dashboard to visualize options flow patterns using matplotlib:

import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime

def create_dashboard(self, unusual_trades):
    if not unusual_trades:
        print("No unusual activity to display")
        return

    df = pd.DataFrame(unusual_trades)
    fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(15, 10))

    # Volume distribution
    ax1.hist(df['volume'], bins=20, alpha=0.7)
    ax1.set_title('Volume Distribution')
    ax1.set_xlabel('Daily Volume')

    # Volume ratio scatter
    ax2.scatter(df['volume'], df['volume_ratio'], alpha=0.6)
    ax2.set_title('Volume vs Volume Ratio')
    ax2.set_xlabel('Daily Volume')
    ax2.set_ylabel('Volume Ratio')

    # Top 10 by volume
    top_10 = df.nlargest(10, 'volume')
    ax3.barh(range(len(top_10)), top_10['volume'])
    ax3.set_yticks(range(len(top_10)))
    ax3.set_yticklabels(top_10['ticker'])
    ax3.set_title('Top 10 by Volume')

    # OI Ratio distribution
    ax4.hist(df['oi_ratio'], bins=20, alpha=0.7)
    ax4.set_title('Open Interest Ratio Distribution')

    plt.tight_layout()
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    plt.savefig(f'options_flow_{timestamp}.png')
    plt.show()

This dashboard generates four key visualizations: volume distribution histogram, volume-ratio correlation scatter plot, top 10 contracts by volume, and open interest ratio distribution. The charts save automatically with timestamps for historical analysis.

Step 7: Schedule Automated Monitoring

Create scheduler.py to run your monitor every 15 minutes during market hours:

import schedule
import time
from datetime import datetime
import pytz
from options_fetcher import OptionsFlowMonitor

def run_monitor():
    # Check if market is open (9:30 AM - 4:00 PM ET)
    et = pytz.timezone('US/Eastern')
    now = datetime.now(et)
    market_open = now.replace(hour=9, minute=30, second=0)
    market_close = now.replace(hour=16, minute=0, second