Skip to main content

Methodology: Insider Transactions (Form 4) Chip

What the chip says and what it means

On any stock page, near the ticker price, you may see one of four chips: INSIDERS BUYING, INSIDERS SELLING, INSIDERS FLAT, or INSIDERS — (em-dash). Each label encodes the result of a specific 90-day calculation against Form 4 filings reported to the SEC. This page documents exactly which calculation, what the thresholds are, when the chip is hidden, and when it has changed.

The chip is informational, not advice. Cluster insider buying is one input among many; insider selling can be driven by tax planning, diversification, or compensation plans rather than a negative view. Read the underlying Form 4 transactions on the insider tab before drawing a conclusion.

1. Data source

The chip reads GET /api/insiders?ticker=<T>&period=90d. The backend (routes/routes_analysis_fastapi/options_insiders.py) returns the Form 4 transactions for the ticker — the chip’s counts and totals aggregated over the last 90 calendar days, the transaction list itself newest-first and unbounded (see the note below) — plus a float field carrying the most-recent reported shares-outstanding count from the company’s annual filing. The transactions come straight from SEC EDGAR via the platform’s Form 4 parser; no commercial data vendor sits between EDGAR and the chip.

Form 4 is the SEC’s reporting form for changes in beneficial ownership by company insiders — officers, directors, and ten-percent shareholders. It must be filed within two business days of the transaction. The chip’s 90-day window means it reflects roughly the last quarter of named-insider activity.

Filings the company makes under its own SEC ID. Some Form 4s name the issuer itself as the reporting owner (the filing’s owner field carries the company’s CIK, not a person’s; the footnotes may still name the officer). Since 2026-09-24 those rows are listed in the transaction feed with the label “Filed under the company’s own SEC ID”, but they are excluded from everything that counts insiders: this chip’s buy/sell totals, the net figure, and cluster detection. An unnamed filer cannot be counted as a distinct insider. The test is a comparison of the two CIKs on the filing and never a guess: a row with either CIK missing is treated as a normal insider row.

2. Transaction-code mapping

Form 4 codeBucketed as
P (open-market or private purchase)BUY
S (open-market or private sale)SELL
All other codes (A grant/award, D disposition to issuer, G gift, F tax-withholding, M option exercise, etc.)Ignored

Bucketing is deliberate. We count only open-market purchases (P) and open-market sales (S) — the transactions where the insider made a directional choice with their own money. We do NOT count A (RSU vests, option grants, other compensation-issued shares — non-discretionary) because counting them painted “INSIDERS BUYING” on routine compensation events. RSU vests are excluded for that reason: receiving a scheduled equity grant is not a market signal. We also do not count D (dispositions to the issuer, including tax withholding), G (gifts), F (tax-withholding), or M (option exercise without sale) for the same reason — none of those carry a directional signal.

The bucketing change shipped 2026-05-22 (BOARD CYCLE DATA_CZAR P1). Before that date the chip counted A as a BUY and D as a SELL; that was wrong — an officer’s RSU vest is not a buy, and a forced disposition to cover taxes is not a sell. The current mapping matches the route’s own summary (insiders.py: net90dayValue sums P/S only) and pg_get_recent_insider_buys (WHERE transaction_code='P').

The code mapping lives in static/js/ticker-renderer.ts in _renderInsiderNetFlowChip (lines 1873–1888).

3. The 1%-of-float threshold

Aggregate share counts cross the 90-day window:

The chip is then classified as:

Honesty disclosure on “float”. The “float” metric on this surface uses shares_outstanding (total shares issued, from the most recent annual filing) — not true free float (outstanding minus restricted and insider-held blocks). Oxford Ledge does not currently carry a separate free-float figure; true free float requires SEC Form 144 and Schedule 13D/G data that is not yet integrated. Shares outstanding is always greater than or equal to free float, so using it as the denominator makes the 1% threshold slightly more conservative than a true-float threshold would be (the chip is marginally less likely to fire). This is the safe direction: no false “INSIDERS BUYING”. The wire field is named float for frontend compatibility, but the numeric value is shares_outstanding. This honesty disclosure was ratified in the 2026-05-22 BOARD CYCLE P2 sweep and is documented in the route docstring at routes/routes_analysis_fastapi/options_insiders.py lines 92–99.

The 1%-of-float threshold filters out single-employee transactions that are too small to be directionally meaningful on a company-wide basis. For a 200-million-shares-outstanding company, a single 15,000-share open-market buy by one director clears the threshold; a 500-share tax-withholding does not.

One percent is policy, not a tuning knob. It was chosen because it is high enough to filter routine compensation-plan activity and low enough that real cluster-buying still trips it on mid-cap and large-cap companies. The constant lives at static/js/ticker-renderer.ts as floatShares * 0.01.

4. The em-dash chip (fail-closed)

When the backend cannot determine the company’s float — usually because the most recent annual filing has not been indexed yet, or for a newly-listed ticker where shares-outstanding has not been reported — the chip renders as INSIDERS — (em-dash) rather than FLAT.

This is a deliberate visual distinction. Before 2026-04-27, a missing float silently collapsed the 1% threshold to zero, which painted every single-share net-buy as INSIDERS BUYING. The em-dash chip exists so that “we don’t know the float” reads differently than “we know the float and activity was balanced.” The aria-label and hover title on the em-dash chip carry the explanatory text.

5. Lookback window + caching

The lookback is a rolling 90 calendar days from the moment the page is loaded. Older Form 4 transactions are still readable on the insider tab; they just don’t affect the chip.

The 90-day window is now enforced in SQL (corrected 2026-09-08). This paragraph used to say the opposite, and it was accurate for about three and a half months: the chip’s figures were summed over the most recent 100 transactions with no SQL-side date filter, so a low-volume issuer could have its whole filing history counted into a number captioned “90-day”. It said so here while §2 above claimed the documented window — one page, both claims. The counts, share totals and net value are now aggregated by a windowed query that reads the entire window rather than a capped page, and the enforced number is shipped alongside the figures so this caption cannot drift from the query that produced it again.

One distinction the §2 wording above flattens. The chip’s figures are windowed. The transaction list on the insider tab is deliberately not — it stays newest-first without a date bound, because date-bounding it would empty the tab for exactly the thinly-filed issuers this correction was written for. So: older Form 4 transactions remain readable, and they do not affect the chip.

The chip caches its result for 5 minutes per ticker per browser session. A fresh fetch happens on every new ticker, on every page load after the cache expires, and on every hard refresh. The cache lives in memory only; closing the tab clears it.

6. Click behavior

Clicking the chip scrolls the page to #insider-feed-section — the table of underlying Form 4 transactions that produced the label. Keyboard users can use Enter or Space to trigger the same scroll. The chip never opens a separate page or modal; the full transactions are inline so a reader can audit the classification.

7. What we deliberately do not do

8. Changelog

DateChange
2026-05-27 PROFESSOR methodology-accuracy sweep correction. §2 transaction-code table rewritten to count only P and S (matching the 2026-05-22 P1 bucketing fix in ticker-renderer.ts:1873–1888); the prior table had still listed A as BUY and D as SELL despite the code change shipping 5 days earlier. §3 “float” definition rewritten to disclose that the value is shares_outstanding, not true free float (matching the route docstring honesty disclosure ratified in the 2026-05-22 P2 sweep). §5 LIMIT-100-approximates-90-days caveat added.
2026-05-22 BOARD CYCLE DATA_CZAR P1: A (RSU grants / awards) and D (dispositions to issuer, including tax withholding) removed from buy/sell bucketing in ticker-renderer.ts:1873–1888. Previously the chip painted “INSIDERS BUYING” on a pure RSU vest because the A code was counted; that was directional misinformation. The chip now counts only open-market purchases (P) and sales (S).
2026-05-13 Initial publication of this methodology page. Thresholds and behaviors mirror the active code in static/js/ticker-renderer.ts and routes/routes_analysis_fastapi/options_insiders.py as of this date.
2026-05-12 A1 (audit doc): chip became click-to-scroll to #insider-feed-section with Enter / Space keyboard parity per WCAG 2.1.1. Previously the chip carried only a hover tooltip and required users to scroll manually to find the underlying transactions.
2026-04-27 Run 1 item 5: missing-float fail-closed path made visually distinct via the em-dash chip. Before this date, a missing float silently set the threshold to zero and painted every net-buy as INSIDERS BUYING. The Run 2 follow-on hardened the contract test so the route’s float field cannot regress.
2026-04-26 Run 2 item 1: backend started surfacing shares_outstanding as float on the /api/insiders response so the frontend could compute the threshold without an extra round-trip. The underlying defect — chip computing data.float * 0.01 against an undefined float — was the original incident that motivated this entire methodology page.
2026-04-26 earlier EW-3 ship: chip introduced. 90-day window and 1%-of-float threshold are unchanged since this date.

Source code and references

Backend route: routes/routes_analysis_fastapi/options_insiders.py (api_insiders). Frontend chip renderer: static/js/ticker-renderer.ts (_renderInsiderNetFlowChip + _applyInsiderNetFlowChip). Contract tests: tests/test_routes_insiders_contract.py (pins the float field presence and the error-response shape).

This page mirrors the source files named above and is reviewed on the date shown at the top. How we keep every figure honest — the contract tests, freshness reviews, and public incident log behind the data — is documented in the Trust Dossier.

Corrections: oxfordledge@gmail.com.