Logic & Config

All rules and thresholds the dashboard uses. Edit and save below — changes write to config_overrides.json and override the code defaults without touching source files.

Slack Alert Rules

Webhook configured

Three alert types fire after each real-time ingest run. Backfills never fire alerts. Each match fires exactly once — dedup prevents re-firing across runs.

Any open market buy (code P) at or above this value triggers an alert.

Lower threshold applied specifically to CEO/CFO title matches.

How many days back to look when counting cluster insiders.

Minimum distinct insiders buying at same issuer to flag as a cluster.

Case-insensitive partial match against the insider_title field. Fuzzy by design — titles vary wildly.

Filter Defaults

These are the pre-filled values when you load the dashboard. You can always override them per-session with the filter bar.

$100k default keeps noise low. Lower to $0 to see everything.

Pre-scheduled sales add noise. Most editorial use cases want to hide them.

% Holdings Column

The % Held column shows how significant this trade was relative to the insider's total position. A high % means this trade moved their stake materially — low % means it was a small slice.

For Buys (code P)

shares_bought ÷ shares_owned_after × 100

Example: bought 10,000 shares, now owns 50,000 → 20% — they added 20% to their existing stake.

For Sells (code S)

shares_sold ÷ (shares_owned_after + shares_sold) × 100

Example: sold 10,000, still owns 40,000 → prior position was 50,000 → 20% sold.

Values above 20% are highlighted in yellow — a strong signal that the insider has real conviction (or is dramatically reducing exposure). Blank means shares_owned_after was not reported in the filing.

Conviction Score Weights

Every open market buy (code P) is scored 1–10 at page load. Sells always score 0 — only buys carry the signal. Adjust point values below. Changes save to config_overrides.json.

Floor score for any open market purchase. All other bonuses add to this.

Added when insider title matches your C-Suite keywords.

Added when 3+ distinct insiders bought at the same issuer within the cluster window.

Added when the filing is NOT a pre-planned 10b5-1 sale.

Tiered bonuses — only the highest matching tier applies per category:

Trade Value tier

≥ $5,000,000 pts
≥ $1,000,000 pts
≥ $250,000 pts

% Holdings tier

≥ 50% of position pts
≥ 20% of position pts

Max score: 10 — scores are capped here regardless of weights.

Green badge = score ≥ 8  |  Amber badge = score ≥ 5  |  Gray badge = score < 5

Research basis: cluster buying (3+) → 2%+/mo outperformance. CEO/CFO buys → 7.8–10%/yr. % holdings >20% → high conviction. Source: Are Insider Trades Informative? (Lakonishok et al.)

C-Suite Filter

The C-Suite only toggle on the dashboard restricts both tables to insiders whose title contains any of the keywords below. Titles on Form 4s are free-text and highly inconsistent — fuzzy matching catches most cases.

Current keywords (edit above in Alert Rules):

CEO Chief Executive CFO Chief Financial

Matching is case-insensitive and partial — "CEO" matches "Co-CEO", "Chief Executive Officer", etc.

Amendment Resolution (Form 4/A)

When a Form 4/A amendment is ingested, the system attempts to find and mark the original filing it corrects. Superseded rows are hidden from the dashboard and issuer views by default.

Matching criteria (all 5 must match)

  • issuer_cik — same company
  • insider_cik — same person
  • transaction_date — same date
  • transaction_code — same type (P, S, etc.)
  • shares — same share count

Ambiguous matches

If 0 or 2+ original rows match, the amendment is stored but no row is marked superseded. This prevents accidental mis-attribution. Ambiguous cases are rare in practice.

To backfill amendment resolution on historical data: python ingest.py --resolve-amendments

Sortable Columns

Click any column header on the dashboard to sort. Click again to reverse. The sort is applied server-side — the full filtered dataset is re-ranked, not just the visible page.

Column Sorts by Default direction
$ Valuetotal_valueDesc (largest first) ← default
SharessharesDesc
Priceprice_per_shareDesc
Tickerissuer_tickerAsc (A→Z)
Insiderinsider_nameAsc (A→Z)
Filedfiled_atDesc (newest first)

Transaction Code Glossary

Code Meaning Default
P Open market purchase
S Open market sale
A Award / grant
M Option exercise
F Tax withholding sale
G Gift
D Sale back to issuer
J Other acquisition/disp.
X Exercise of derivative
C Conversion of derivative
E Expiration of short deriv
H Expiration of long deriv
I Discretionary transaction
K Equity swap settled
L Small acquisition (<$10k)
O Exercise out-of-money
U Tender of shares
W Will / inheritance
Z Deposit into voting trust

Green codes = buy signal. Red = sell signal. Gray = non-directional. Faded rows hidden by default.

10b5-1 Detection

Step 1: Check <rule10b5-1Indicator>Y</rule10b5-1Indicator> in the XML. This is the authoritative flag in modern filings.

Step 2: If that element is absent (older filings), scan footnote_text for the substring "10b5-1".

Caveat: pre-2023 filings frequently miss the XML flag entirely. Footnote detection catches most but not all. Flag can be under-reported in backfill data.

Total rows in DB:84,853
Flagged 10b5-1:13,259
Footnote-detected:13,259

Research Basis

What academic and practitioner research says about which signals actually predict future returns.

Signal hierarchy — what predicts most

Strongest: Cluster buying — 3+ insiders within 14 days → 2%+/month abnormal returns. The single most backed signal in research.

Strong: CEO/CFO open market purchases. CFOs especially — they know the numbers. Officers more predictive in small-caps.

Moderate: Any open market purchase where % of holdings change exceeds ~20%. Conviction signal outweighs raw dollar size.

Weak/exclude: Grants (A), option exercises (M), 10b5-1 plan sales, buys under $200K at large-caps.

Buys vs. sells

Purchase stocks outperform sale stocks by 7.8–10% per year. Sells are noisy — insiders sell for diversification, taxes, divorce. They buy for one reason.

Non-10b5-1 discretionary sells are 3× more informative than plan sells. But even discretionary sells are far weaker than buys. Default view should emphasize buys.

Time horizon

~50% of abnormal returns accrue in month 1. Most of the rest through month 6. Signal largely exhausted by 12 months.

Cluster buys: outperformance is strongest in the first 30 days, then decays. Score and alert on these first.

Size & sector effects

Signal is 2–3× stronger in small/micro-cap stocks — less analyst coverage, more informational edge for insiders. Large-cap insider buys are less predictive.

Tech sector insiders sell heavily due to equity comp — sales there are especially noisy. Finance sector is more balanced and more informative.

Insider buys right after negative earnings surprises are highly predictive — they're signaling the market overreacted.

Has the signal decayed over time?

Yes, somewhat. Returns are lower than 1990s studies. EDGAR's public XML access since 2003 has allowed quant funds to arbitrage easy signals away.

However: the anomaly persists in 2024 studies, especially for clusters, small-caps, and trades with high % holdings change. Hard to exploit at scale; still valuable for editorial research and targeted alerts.

Phase 2 Roadmap

  • Conviction score — 1–10 per trade combining role weight, % holdings change, cluster membership, 10b5-1 status. Research-backed weights.
  • Slack alerts — live. Big buy, C-suite buy, cluster detection. Dedup via alerts_sent table.
  • Insider history baseline — is this buy unusual vs. this insider's own past? Flag when size or frequency is an outlier.
  • Earnings proximity flag — mark trades within 10 days of earnings. Research shows these carry strongest info content.
  • Sector enrichment — live. SIC codes fetched from EDGAR, mapped to 11 sectors. Sector filter in dashboard.
  • Watchlist — pin specific tickers or insiders to a personal watchlist tab.
  • Date range view — week/month aggregation alongside the daily view.
  • Amendment resolution — merge 4/A amendments with originals instead of storing as separate rows.
  • CSV export — download filtered table as spreadsheet.
  • Issuer trend chart — rolling 90-day buy/sell ratio sparkline on issuer page.

Sector Enrichment

SIC codes are fetched from data.sec.gov/submissions/CIK{cik}.json and cached for 90 days. Each issuer is mapped to one of 11 sectors based on SIC range. Backfill: python ingest.py --backfill-sectors

Sector Key SIC ranges
Technology3570–3579, 3660–3679, 7370–7379
Healthcare2830–2836, 3841–3851, 8000–8099
Financials6000–6411, 6700–6726
Real Estate6500–6552, 6798
Energy1300–1389, 2900–2911
Consumer Disc5500–5999, 7000–7041, 7200–7299
Consumer Staples2000–2199, 5100–5199, 5400–5499
Industrials1500–1799, 3400–3799, 4210–4599
Materials1000–1299, 2600–2829, 3000–3399
Utilities4900–4991
Communications4800–4899
OtherAnything not in the above ranges

Recent Alerts Sent

No alerts sent yet. Alerts fire after daily ingest runs when thresholds are met.