Skip to main content

Earnings Calendar System

Overview

The earnings calendar system automatically fetches and displays upcoming earnings reports for all securities in the user’s portfolio, including manually tracked holdings, connected brokerage accounts, and SnapTrade positions.

Architecture

Data Flow

  1. Cron Job (/api/cron/fetch-earnings) runs weekly on Sundays at 3 AM UTC
  2. Fetches all unique tickers from THREE sources:
    • securities table (Plaid-connected holdings)
    • manual_public_holdings table (manually tracked stocks)
    • snaptrade_positions table (SnapTrade brokerage positions)
  3. Deduplicates tickers using a Set to create a unique list
  4. Calls Finnhub API for each unique ticker to get earnings data for the next 365 days
  5. Upserts earnings data into the earnings table
  6. Frontend queries earnings based on user’s holdings

Components

Backend

  • /app/api/cron/fetch-earnings/route.ts: Cron job that fetches earnings data
    • Runs weekly: 0 3 * * 0 (Sunday 3 AM UTC)
    • Max duration: 800 seconds
    • Rate limited: 1 request per second (Finnhub free tier: 60 calls/min)

Frontend

  • /hooks/queries/use-earnings.ts: React hook that fetches earnings for user’s holdings
    • Extracts ticker symbols from all holding types (manual, SnapTrade, connected)
    • Queries earnings table for matching tickers
    • Filters to show only upcoming/future earnings
  • /components/dashboard-earnings-card.tsx: Dashboard card showing next 4 upcoming earnings
  • /app/earnings-calendar/page.tsx: Full earnings calendar page

Database Schema

API Integration

Finnhub API

  • Endpoint: https://finnhub.io/api/v1/calendar/earnings
  • Rate Limit: 60 calls/minute (free tier)
  • Authentication: API key via X-Finnhub-Token header
  • Response: Array of earnings events with estimates and actuals

Environment Variables

  • FINNHUB_API_KEY: Required for API authentication
  • SUPABASE_URL: Supabase project URL
  • SUPABASE_SERVICE_ROLE_KEY: Service role key for admin access
  • CRON_SECRET: Secret for authenticating cron requests

Holdings Support

The system supports earnings for all holding types, with both backend (data fetching) and frontend (display) integration:

Manual Holdings

  • Backend source: manual_public_holdings table (column: symbol)
  • Frontend structure: securities is an object with ticker_symbol
  • Includes only active holdings (is_active = true)

SnapTrade Holdings

  • Backend source: snaptrade_positions table (column: symbol)
  • Frontend structure: securities is an array with first element containing ticker_symbol
  • Positions from brokerage accounts (Schwab, Fidelity, etc.)

Connected Holdings (Plaid)

  • Backend source: securities table (column: ticker_symbol)
  • Frontend structure: securities is an object with ticker_symbol
  • Holdings from Plaid-connected bank/brokerage accounts

Deduplication

The backend cron job uses a JavaScript Set to automatically deduplicate tickers across all three sources, ensuring each ticker is only fetched once from the Finnhub API even if a user has the same stock in multiple accounts.

Rate Limiting

The cron job implements rate limiting to respect Finnhub’s API limits:
  • 1 second delay between requests
  • Processes securities sequentially (not parallel)
  • Max 60 securities per minute
  • Weekly schedule prevents excessive API usage

Error Handling

  • Failed API calls are logged and counted
  • Errors don’t stop the entire batch
  • Response includes success/failure counts and error details
  • Upsert logic prevents duplicate entries

Manual Trigger

To manually trigger the earnings fetch (for testing):

Monitoring

Check cron job logs in Vercel dashboard:
  • Look for “Starting earnings data fetch…”
  • Monitor success/error counts
  • Check for Finnhub API rate limit errors
  • Verify earnings data is being inserted

Future Enhancements

  • Add earnings surprises (actual vs estimate)
  • Send notifications for earnings reports
  • Filter earnings by portfolio value/importance
  • Add earnings call transcripts integration
  • Historical earnings performance tracking
  • Earnings impact on stock price analysis