Skip to main content
EARNINGS AUTOMATION · PART 1 OF 5

Earnings Calendar Monitor

Never get caught off guard by an earnings report again. OpenClaw checks your watchlist every morning and alerts you 3 days before any ticker reports — using free data, zero paid subscriptions.

yfinance Free
No API Key
3-Day Alerts
Watchlist-Driven
Overview Pt 1: Calendar Pt 2: Estimates Pt 3: Surprise Tracker Pt 4: Price Reaction Pt 5: Daily Brief
Disclaimer: Earnings calendar data is for research monitoring only. Dates may shift. Not financial advice.

What Is an Earnings Calendar?

Every public company is required by law to report its financial results four times a year—once each quarter. The dates when these reports will be published are announced in advance on the earnings calendar. This is public information. You can find it on Yahoo Finance, CNBC, MarketWatch, or any financial data provider.

But here's the problem: if you have a diversified watchlist of 20+ stocks, manually checking each one on different financial sites every single day is tedious and error-prone. You might miss a ticker entirely. You might be unaware that your largest position is reporting in two days. That's when an earnings report can move a stock 10–20% or more in minutes, and you're caught off guard.

Before Market Open (BMO) vs After Market Close (AMC) timing matters for how you position. A report released BMO can gap your position at the open; AMC gives you time to react after the close. OpenClaw tracks both, so you can plan accordingly.

The Earnings Cycle Timeline

Q1 Ends → Earnings → Analyst → Stock Mar 31 Report Due Call Live Reacts (Apr–May) ±10–20%

Most earnings happen within 4–6 weeks of the quarter's end. Earnings calls (where executives explain the results) typically happen within days. The stock can react anywhere from 30 minutes to several hours after the announcement.

What OpenClaw Automates

The traditional approach is manual. You. Every morning, checking 20 different sites for 20 tickers. Hoping you don't skip one.

OpenClaw replaces that with a single script that runs automatically every morning and does the work for you. Here's the before-and-after:

Without OpenClaw With OpenClaw
Manually check Yahoo Finance, Seeking Alpha, etc. every day Script runs automatically at 6:30 AM every weekday
Easy to miss a ticker. No alerts if you don't check. Checks all tickers in your config. Sends email if anything reports in the next 3 days.
Inconsistent record-keeping. Dates scribbled in notes. Results logged to CSV automatically. Historical record for backtesting.
Reacts to earnings. Positioned during the move. Gets a 3-day heads-up. Time to review position size, check IV, read filings.

That 3-day window is your edge. You're not reacting—you're preparing. You can check if the stock is overbought (high IV rank), pull the latest 10-Q filing, read the last earnings call transcript, and decide whether to trim, hold, or add to your position. By the time the report hits, you're ready.

The earnings-config.yaml Snippet

All OpenClaw scripts read from a single config file. This is where you tell OpenClaw what to do: which tickers to watch, how many days ahead to look, when to send alerts, and when to run.

Here's the earnings calendar section of the config:

earnings-config.yaml
watchlist:
  tickers: [AAPL, MSFT, NVDA, AMZN, GOOGL]

calendar:
  lookahead_days: 5
  alert_days_before: 3
  market_hours_only: false   # include pre-market & after-hours reports

alerts:
  email: "you@example.com"
  daily_digest: true
  send_time: "06:30"

scheduler:
  earnings_calendar:
    script: earnings_calendar.py
    schedule: "30 6 * * 1-5"  # Weekdays at 6:30 AM

Field Explanations:

Pro Tip: Start with 5 tickers (a small watchlist) and tune the alert window to 3 days. Once it's running smoothly, expand your watchlist and adjust the lookahead. Too many alerts = you'll ignore them.

The Python Script: earnings_calendar.py

This is the script that OpenClaw runs every morning. It reads your config, fetches earnings dates from yfinance (a free, open-source library), checks for upcoming reports, and sends an email alert if anything falls within your alert window.

Every line is commented so you can understand what's happening. You don't need to modify this script to use it—just save it, and let the cron scheduler run it.

earnings_calendar.py
"""
earnings_calendar.py — OpenClaw Earnings Calendar Monitor

Reads earnings-config.yaml, checks upcoming earnings for your watchlist,
and sends an email alert if any ticker reports within your alert window.

Usage:  python earnings_calendar.py
        (Typically run by cron each morning)
"""

import yaml
import yfinance as yf
import pandas as pd
from datetime import datetime, timedelta
import smtplib
from email.mime.text import MIMEText
import csv

# ──────────────────────────────────────────────────────────────────────────
# 1. LOAD CONFIGURATION
# ──────────────────────────────────────────────────────────────────────────

with open("earnings-config.yaml") as f:
    cfg = yaml.safe_load(f)

# Extract settings from config
tickers       = cfg["watchlist"]["tickers"]
lookahead     = cfg["calendar"]["lookahead_days"]
alert_window  = cfg["calendar"]["alert_days_before"]
alert_email   = cfg["alerts"]["email"]
send_time     = cfg["alerts"]["send_time"]

print("\n" + "="*60)
print("OpenClaw Earnings Calendar Monitor")
print("="*60)
print(f"Scanning {len(tickers)} tickers for earnings in next {lookahead} days")
print(f"Alert threshold: {alert_window} days before report")
print()

# Calculate date boundaries
today = datetime.today().date()
cutoff = today + timedelta(days=lookahead)

print(f"Date range: {today} to {cutoff}\n")

# ──────────────────────────────────────────────────────────────────────────
# 2. FETCH EARNINGS DATES FROM YFINANCE
# ──────────────────────────────────────────────────────────────────────────

upcoming = []

for ticker in tickers:
    try:
        print(f"  Fetching {ticker}...", end=" ")
        stock = yf.Ticker(ticker)

        # yfinance.earnings_dates returns a DataFrame indexed by date
        # Columns: "EPS Estimate" and "Reported EPS"
        cal = stock.earnings_dates

        if cal is None or cal.empty:
            print("(no earnings data)")
            continue

        # Filter to future dates within our lookahead window
        cal = cal[cal.index.date >= today]
        cal = cal[cal.index.date <= cutoff]

        # If nothing found, skip
        if cal.empty:
            print("(none in window)")
            continue

        # Iterate over matching earnings dates
        for date, row in cal.iterrows():
            days_away = (date.date() - today).days

            upcoming.append({
                "Ticker":       ticker,
                "Date":         date.strftime("%Y-%m-%d"),
                "Days Away":    days_away,
                "Alert":        "⚠️ ALERT" if days_away <= alert_window else "",
                "EPS Estimate": row.get("EPS Estimate", "N/A"),
            })

        print(f"({len(cal)} earnings)")

    except Exception as e:
        print(f"(error: {e})")
        continue

# ──────────────────────────────────────────────────────────────────────────
# 3. PRINT RESULTS TO TERMINAL
# ──────────────────────────────────────────────────────────────────────────

if upcoming:
    # Sort by days away (nearest first)
    df = pd.DataFrame(upcoming).sort_values("Days Away")

    print("\n📅 UPCOMING EARNINGS ON YOUR WATCHLIST")
    print("="*65)
    print(df.to_string(index=False))
    print()
else:
    print("✅ No earnings found in the next", lookahead, "days for your watchlist.")
    print()

# ──────────────────────────────────────────────────────────────────────────
# 4. SEND EMAIL ALERT IF ANY REPORTS ARE WITHIN THE ALERT WINDOW
# ──────────────────────────────────────────────────────────────────────────

# Filter to only upcoming reports (within alert_days_before)
alerts = [u for u in upcoming if u["Days Away"] <= alert_window]

if alerts:
    # Build email body
    body = "OpenClaw Earnings Alert\n"
    body += "="*50 + "\n\n"
    body += "The following stocks on your watchlist report earnings soon:\n\n"

    for a in alerts:
        body += f"  {a['Ticker']:6s}  —  {a['Date']}  ({a['Days Away']:2d} days away)\n"
        body += f"           EPS Estimate: {a['EPS Estimate']}\n\n"

    body += "---\n"
    body += "Next steps: Review your position size, check IV rank,\n"
    body += "pull the latest filing, and read the last earnings transcript.\n"
    body += "This is your 3-day heads-up to prepare.\n\n"
    body += "Not financial advice. Automated from OpenClaw.\n"

    # NOTE: To actually send email, configure SMTP credentials below.
    # This is a stub. In production, you'd use:
    #
    #   import os
    #   smtp_server = "smtp.gmail.com"
    #   smtp_port = 587
    #   sender_email = os.getenv("OPENCLAW_EMAIL")
    #   sender_password = os.getenv("OPENCLAW_PASSWORD")
    #
    #   msg = MIMEText(body)
    #   msg["Subject"] = f"OpenClaw: {len(alerts)} earnings report(s) coming up"
    #   msg["From"] = sender_email
    #   msg["To"] = alert_email
    #
    #   server = smtplib.SMTP(smtp_server, smtp_port)
    #   server.starttls()
    #   server.login(sender_email, sender_password)
    #   server.send_message(msg)
    #   server.quit()

    print("📧 ALERT WOULD BE SENT")
    print("="*65)
    print(f"To: {alert_email}")
    print(f"Subject: OpenClaw: {len(alerts)} earnings report(s) coming up")
    print()
    print(body)
else:
    print("✅ No alerts triggered (no earnings within", alert_window, "day window)")
    print()

# ──────────────────────────────────────────────────────────────────────────
# 5. LOG RESULTS TO CSV (FOR HISTORICAL RECORD)
# ──────────────────────────────────────────────────────────────────────────

if upcoming:
    import os
    os.makedirs("data", exist_ok=True)

    log_file = "data/earnings_calendar_log.csv"

    # Add a timestamp column
    df["Timestamp"] = datetime.today().strftime("%Y-%m-%d %H:%M:%S")

    # Append to existing CSV or create new
    if os.path.exists(log_file):
        df.to_csv(log_file, mode='a', header=False, index=False)
    else:
        df.to_csv(log_file, index=False)

    print("💾 LOGGED TO CSV")
    print("="*65)
    print(f"File: {log_file}")
    print(f"Rows: {len(df)}")
    print()

print("Done.\n")
Email Setup Note: The script above has email functionality stubbed out with comments. To enable real email alerts, you'll need to configure an SMTP server (Gmail, Outlook, or your own) and store credentials as environment variables. See the comments in the code for setup instructions. For now, the script will print the alert to the terminal.

Sample Output

Here's what the script prints to your terminal when it runs in the morning:

============================================================
OpenClaw Earnings Calendar Monitor
============================================================
Scanning 5 tickers for earnings in next 5 days
Alert threshold: 3 days before report

Date range: 2026-03-28 to 2026-04-02

  Fetching AAPL... (1 earnings)
  Fetching MSFT... (1 earnings)
  Fetching NVDA... (none in window)
  Fetching AMZN... (1 earnings)
  Fetching GOOGL... (none in window)

📅 UPCOMING EARNINGS ON YOUR WATCHLIST
=================================================================
    Ticker        Date  Days Away Alert       EPS Estimate
      MSFT  2026-03-29          1 ⚠️ ALERT              3.22
      AAPL  2026-04-01          4                       1.61
      AMZN  2026-04-02          5                       1.37

📧 ALERT WOULD BE SENT
=================================================================
To: you@example.com
Subject: OpenClaw: 1 earnings report(s) coming up

OpenClaw Earnings Alert
==================================================

The following stocks on your watchlist report earnings soon:

  MSFT    —  2026-03-29  ( 1 days away)
           EPS Estimate: 3.22

---
Next steps: Review your position size, check IV rank,
pull the latest filing, and read the last earnings transcript.
This is your 3-day heads-up to prepare.

Not financial advice. Automated from OpenClaw.

💾 LOGGED TO CSV
=================================================================
File: data/earnings_calendar_log.csv
Rows: 3

Done.

Notice that MSFT is flagged with ⚠️ ALERT because it reports in 1 day (within the 3-day window). The script logs all three upcoming reports to CSV for your historical record. You can review this log later to see which earnings moved your portfolio, and which ones you handled well.

Cron Setup: Run Automatically Every Morning

Right now, you run the script manually. But the whole point of OpenClaw is automation. You want the script to run every morning at 6:30 AM, while you're still asleep, and have the email waiting for you when you wake up. That's what cron does.

Cron is a job scheduler on Unix-like systems (Linux, macOS). You give it a command and a schedule, and it runs the command at that time, every day.

Open your terminal and edit your crontab:

crontab -e

Add this line at the bottom:

30 6 * * 1-5 cd /path/to/openclaw && python earnings_calendar.py

Save and exit. That's it. The script will now run every weekday at 6:30 AM.

Cron Syntax Breakdown:

30 6 * * 1-5
│  │ │ │ └─ Day of week (0-6, where 0=Sunday)
│  │ │ │    1-5 = Monday through Friday
│  │ │ └─── Month (*, or 1-12)
│  │ └───── Day of month (*, or 1-31)
│  └─────── Hour (0-23, 24-hour format)
└────────── Minute (0-59)

So 30 6 * * 1-5 means: "At 6:30 AM (06:30), every day, every month, Monday through Friday."

The command cd /path/to/openclaw && python earnings_calendar.py means:

Important: Replace /path/to/openclaw with the actual path to your OpenClaw directory. For example: /Users/john/openclaw or /home/trader/projects/openclaw.

To verify your crontab is set:

crontab -l

This will print your scheduled jobs. If you see your earnings_calendar line, you're good.

What To Do With This 3-Day Heads-Up

Getting an alert that MSFT reports in 3 days is only the start. That's when the real work begins. Here's how the Terminal series stacks together:

Each piece is automated. Each runs from the same earnings-config.yaml. Each can be triggered by cron. By the end of the series, you have a full earnings surveillance system that runs automatically every morning and gives you the intelligence you need to trade with confidence.

That's OpenClaw.