HedgeFriend
← All posts
Research6 min readHedgeFriend

Reading Form 4: what insider filings do and don't tell you

Insider buys are a noisy signal until you strip out the scheduled sales. A short field guide.

Form 4 is the filing an officer, director, or ten-percent owner submits after transacting in their own company's stock. It is one of the few places where a person with genuine private information is legally required to describe what they did with it, within two business days. That makes it attractive. It also makes it heavily studied, and most naive readings of it are wrong.

The transaction code is the whole story

A raw count of "insider sells" is close to meaningless, because most of them were scheduled months in advance or are not discretionary at all. The transaction code tells you which kind you are looking at:

  • P — open-market purchase. The insider spent their own money. This is the row that carries most of the signal.
  • S — open-market sale. Informative only after you exclude the planned ones.
  • M — option exercise, usually followed by an S on the same day. Mechanical, not a view.
  • A — grant or award. Compensation, not conviction.
  • F — shares withheld to cover tax on vesting. Looks like a sale, means nothing.
Rule of thumb: cluster buys by multiple officers, in open-market P transactions, at a company with no recent buying history, is the configuration worth a second look.

Three things that will burn you

  1. 1.Trading plans. A sale under a pre-arranged plan was decided long before the filing date, so aligning it with recent news is a spurious correlation. The filing footnotes flag these.
  2. 2.Filing lag and clustering. Filings bunch around vesting dates and blackout-window openings, which produces calendar seasonality that has nothing to do with outlook.
  3. 3.Amendments. Filings get corrected. If your pipeline reads the original and never revisits it, your history slowly diverges from the record.

Querying it

insider_buys.py
python
import os, requests

HEADERS = {"Authorization": f"Bearer {os.environ['HEDGEFRIEND_KEY']}"}

r = requests.get(
    "https://api.hedgefriend.dev/v1/sec/insider-trades/AAPL",
    params={"from": "2024-01-01", "transaction_code": "P"},
    headers=HEADERS,
    timeout=30,
)
r.raise_for_status()

buys = r.json()["data"]
print(f"{len(buys)} open-market purchases")

The endpoint takes `transaction_code` directly, so the filtering happens server-side. From there, aggregate by filer and compare against the same company's own baseline rather than a cross-sectional average. Insider behavior is idiosyncratic; the useful comparison is almost always to the issuer's own history. There is also a `/summary` variant that returns net buys versus sales over a window.

Try it on your own data

The free tier covers 500 requests a day — enough to reproduce anything in this post.

Get a free key