Corporate insiders — CEOs, CFOs, directors — have to report every time they buy or sell their own company's stock on SEC Form 4, within two business days. Insider buying on the open market is one of the few market signals that's both public and hard to fake: people rarely put their own cash into their own stock unless they mean it.
The problem: Form 4 is filed as XML, thousands of times a week. Reading it by hand is hopeless, and parsing the XML yourself is a weekend gone.
So I built a small screener that ranks my watchlist by insider conviction. Here's the whole thing.
Disclosure: I use my own API for this (SEC Intel). The Form 4 parsing + scoring is the tedious part it removes; the screener logic below is yours to keep.
The idea
- For each ticker on my watchlist, pull the parsed Form 4 summary.
- Read the insider-conviction score (0–100) — it weighs how many insiders bought, whether the C-suite is involved, and buys vs. sells.
- Rank so the real buying floats to the top.
The code
import requests
HOST = "sec-intel-filings-financials-insider-trades.p.rapidapi.com"
HEADERS = {"X-RapidAPI-Key": "YOUR_KEY", "X-RapidAPI-Host": HOST}
WATCHLIST = ["NVDA", "AAPL", "MSFT", "TSLA", "AMD", "META", "AMZN", "XOM"]
def get(path, **params):
r = requests.get(f"https://{HOST}{path}", params=params, headers=HEADERS, timeout=30)
r.raise_for_status()
return r.json()
rows = []
for ticker in WATCHLIST:
summary = get("/insider", query=ticker)["summary"]
rows.append((summary["conviction_score"], summary["signal"], ticker, summary["net_usd"]))
# rank: strongest insider conviction first
for score, signal, ticker, net in sorted(rows, reverse=True):
print(f"{ticker:6} conviction {score:>3} {signal:8} net ${net:,.0f}")
Live output when I ran it:
TSLA conviction 70 bullish net $879,654,993
XOM conviction 0 neutral net $0
AAPL conviction 0 bearish net $-111,739,341
MSFT conviction 0 bearish net $-2,843,905
META conviction 0 bearish net $-10,063,533
AMZN conviction 0 bearish net $-51,643,529
AMD conviction 0 bearish net $-167,076,160
NVDA conviction 0 bearish net $-410,446,401
One insider put ~$880M into TSLA on the open market while the rest of mega-cap tech shows insiders selling. That's the whole point: the buy is the rare signal, and it floats straight to the top. No XML, no CIK lookups, no Form 4 field decoding.
Make it an alert
Wrap it in a loop and ping yourself when conviction crosses your threshold — Slack, Telegram, email, whatever:
def scan_and_alert(threshold=50):
for ticker in WATCHLIST:
s = get("/insider", query=ticker)["summary"]
if s["conviction_score"] >= threshold:
notify(f"Insider buying: {ticker} ({s['conviction_score']}/100, {s['signal']})")
Bonus: want the whole market instead of a watchlist?
GET /insider-signalsreturns the newest open-market insider buys across all filers (Form 4 code P), sorted by size.
Feed it to an agent instead
The same JSON drops straight into a prompt or a tool call — or connect the API as an MCP server (Claude Desktop, Cursor, VS Code) and just ask "any strong insider buying on my watchlist today?". The data comes back structured, so the model doesn't guess.
Notes on using this responsibly
Insider buying is a signal, not a crystal ball — people buy for many reasons, and this isn't investment advice. But as a filter to surface where informed people put their own money, a conviction-ranked screen beats scrolling filings by hand.
Try it
- Free tier (1,000 calls/mo, no card): SEC Intel API on RapidAPI
- Try every endpoint in the browser: live docs
- More on the API: secintelapi.netlify.app
What would you screen for? Drop your watchlist + threshold in the comments.
Top comments (0)