Ever wonder how hedge funds know about insider trades before you do?
They're not psychic. They just have systems monitoring SEC filings in real-time. The moment a Form 4 hits EDGAR, they know.
Today, we're building that system. In Python. In under 50 lines.
Why Monitor SEC Filings?
Three filings move markets:
- 8-K: Unscheduled material events (CEO quits, merger announced, lawsuit filed)
- 10-K/10-Q: Annual and quarterly financials
- Form 4: Insider trading β when executives buy or sell their own stock
That last one is interesting. When a CEO buys $2M of their own company's stock, that's a signal. They know something.
What We're Building
A Python script that:
- Checks for new filings every 5 minutes
- Filters by your watchlist (specific tickers)
- Prints alerts to console (easily extendable to Slack, email, etc.)
No scraping. No parsing HTML. No dealing with EDGAR's... quirks.
First, grab a free API key.
The Code
import requests
import time
from datetime import datetime
# Config
API_KEY = "your_api_key" # Free tier at earningsfeed.com
BASE_URL = "https://earningsfeed.com/api/v1"
WATCHLIST = ["AAPL", "TSLA", "NVDA", "MSFT", "GOOGL"]
CHECK_INTERVAL = 300 # 5 minutes
# Track what we've already seen
seen_filings = set()
def get_recent_filings():
"""Fetch recent SEC filings for watchlist tickers."""
headers = {"Authorization": f"Bearer {API_KEY}"}
filings = []
for ticker in WATCHLIST:
response = requests.get(
f"{BASE_URL}/filings",
headers=headers,
params={"ticker": ticker, "limit": 10}
)
if response.ok:
filings.extend(response.json().get("items", []))
return filings
def check_for_new_filings():
"""Check for new filings and alert on any we haven't seen."""
filings = get_recent_filings()
for filing in filings:
filing_id = filing.get("accessionNumber")
if filing_id and filing_id not in seen_filings:
seen_filings.add(filing_id)
alert(filing)
def alert(filing):
"""Print alert for new filing. Swap this for Slack/email/SMS."""
company = filing.get("companyName", "Unknown")
form_type = filing.get("formType", "???")
filed_at = filing.get("filedAt", "")
url = filing.get("url", "")
print(f"""
π¨ NEW FILING DETECTED
βββββββββββββββββββββ
Company: {company}
Form: {form_type}
Filed: {filed_at}
Link: {url}
βββββββββββββββββββββ
""")
def main():
print(f"π Monitoring {len(WATCHLIST)} tickers: {', '.join(WATCHLIST)}")
print(f"β±οΈ Checking every {CHECK_INTERVAL // 60} minutes")
print("Press Ctrl+C to stop\n")
# Initial check
check_for_new_filings()
while True:
time.sleep(CHECK_INTERVAL)
print(f"[{datetime.now().strftime('%H:%M:%S')}] Checking...")
check_for_new_filings()
if __name__ == "__main__":
main()
That's it. Under 50 lines.
Running It
pip install requests
python sec_monitor.py
Output:
π Monitoring 5 tickers: AAPL, TSLA, NVDA, MSFT, GOOGL
β±οΈ Checking every 5 minutes
Press Ctrl+C to stop
π¨ NEW FILING DETECTED
βββββββββββββββββββββ
Company: NVIDIA Corp
Form: 4
Filed: 2024-12-14T16:32:00.000Z
Link: https://www.sec.gov/Archives/edgar/data/1045810/...
βββββββββββββββββββββ
Make It Actually Useful
The alert() function is where you customize. Some ideas:
Slack notifications:
def alert(filing):
requests.post(SLACK_WEBHOOK, json={
"text": f"π¨ {filing['companyName']} just filed a {filing['formType']}"
})
Filter by form type (only insider trades):
if filing.get("formType") == "4":
alert(filing)
Only material events:
# In get_recent_filings(), add forms filter
params={"ticker": ticker, "forms": "8-K,4", "limit": 10}
Why I Built This
Full disclosure: I built Earnings Feed because I got tired of the alternatives.
EDGAR's direct API has rate limits that'll get you blocked. Most commercial APIs charge hundreds per month. I wanted something with a free tier that just... works.
The database covers every public company filing with the SEC. Every 10-K, every Form 4, every 8-K.
If you're building something in the fintech space, it might save you some headaches.
What Would You Build?
I'm curious what you'd do with real-time SEC data:
- Trading signals based on insider buys?
- Alerts when competitors file 8-Ks?
- Tracking institutional ownership changes via 13F?
Drop a comment!
Top comments (0)