ZipLime/insider-sale-notices
US Insider Sale Notices — SEC Form 144 Every notice a corporate insider files before selling restricted or control stock, normalized into a point-in-time schema and rebuilt daily. 124 886 notices covering 2023-01-04 to 2026-09-04, from 4 237 issuers and 23 871 sellers, with the acceptance timestamp of every filing to the second. The pipeline that produces this dataset lives in recipe/ inside this same repository, at the same revision as the data. See PIPELINE.md for the method… See the full description on the dataset page: https://huggingface.co/datasets/ZipLime/insider-sale-notices.
US Insider Sale Notices — SEC Form 144
Every notice a corporate insider files before selling restricted or control stock, normalized into a point-in-time schema and rebuilt daily.
124 886 notices covering 2023-01-04 to 2026-09-04, from 4 237 issuers and 23 871 sellers, with the acceptance timestamp of every filing to the second.
The pipeline that produces this dataset lives in `recipe/` inside this same repository, at the same revision as the data. See PIPELINE.md for the method, including what it refuses to do.
What makes this form different from everything else
*A Form 144 is filed before the sale.* Form 4 reports a trade that already happened, within two business days. Form 144 announces a trade that has not happened yet — the insider states how many shares they intend to sell, through which broker, and on approximately what date.
That inverts the usual relationship between the two dates in this dataset:
knowledge_date the second EDGAR accepted the notice — when you could read it
event_date the day the seller says the sale may begin — usually laterIn 91% of notices the intended sale date falls on or after the day the notice became public. Do not normalise this away. A pipeline that assumes disclosure follows the event will read these rows as broken and repair them into uselessness; the forward-looking date is the entire content of the form.
The join that makes it worth having
issuer_cik and owner_cik are the same identifiers used by ZipLime/insider-trading, the Form 4 dataset. entity_id in the pit config is the issuer CIK in both, so the two point-in-time tables join directly — no ticker dictionary in between, no name matching.
That gives you the pair the market cannot see in either form alone:
Follow-through — how much of the announced amount was actually sold, and how fast — is computable from the two datasets and is not shipped precomputed: the answer depends on the window you consider, and baking a window in would be a choice made for you.
from datasets import load_dataset
notices = load_dataset("ZipLime/insider-sale-notices", "notices", split="train")
form4 = load_dataset("ZipLime/insider-trading", "transactions", split="train")
# join on (issuer_cik, owner_cik / reporting_owner_cik) and compare
# units_to_be_sold against the shares actually disposed of afterwardsRule 10b5-1 plan dates
43% of notices disclose the date the seller's Rule 10b5-1 trading plan was adopted (plan_adoption_date), and days_from_plan_to_notice measures the gap. Form 4 carries only a flag saying a plan existed; this form says when it was put in place, which is what separates a sale scheduled months earlier from one arranged the week before a disclosure.
This field exists in no comparable commercial feed.
Coverage, and where it starts
Electronic filing of Form 144 became mandatory on 2023-04-13. Discovery starts on 2023-01-01 and keeps the 843 structured submissions filed voluntarily before the deadline, so the transition is visible in the data rather than cut off at a round date.
Everything earlier is out of reach. Before the mandate the form went in on paper or as free-form HTML — between 83 and 184 submissions a quarter, none of them structured. Parsing those would be an OCR project against a layout that changes per filer agent, for under 1% of the volume; the boundary is stated here rather than papered over.
After the mandate the form runs at roughly 8 749 filings a quarter.
Configs
Schema — notices
Schema — pit
system pit_event_id, logical_notice_id, revision, operation,
entity_id, event_date, knowledge_date, knowledge_estimated
values issuer_cik, issuer_name, issuer_ticker, owner_cik, owner_name,
relationship, is_officer, is_director, is_ten_percent_owner,
security_class, units_to_be_sold, aggregate_market_value_usd,
pct_of_units_outstanding, has_10b5_1_plan, plan_adoption_date,
days_from_plan_to_notice, past_3m_units_sold, broker_name,
is_amendmententity_id is the issuer CIK. A 144/A is stored as a second revision of the same logical_notice_id; both stay in the table, and a point-in-time read returns whichever was current at the moment you ask:
import polars as pl
from datetime import datetime, UTC
pit = pl.read_parquet("data/pit/knowledge_year=*/*.parquet")
visible = pit.filter(pl.col("knowledge_date") <= datetime(2025, 6, 30, tzinfo=UTC))
current = (visible.sort(["logical_notice_id", "revision", "knowledge_date"])
.unique(subset=["logical_notice_id"], keep="last"))The table is append-only: a rebuild adds what it has not seen and never rewrites what is there. Changing what counted as known, after the fact, would make any backtest built on it unreproducible.
Schema — features
Daily per-issuer aggregates keyed on knowledge_day, never on the intended sale date: n_notices, n_sellers, units_to_be_sold, notice_value_usd, pct_of_units_outstanding, max_single_notice_value_usd, share_under_10b5_1_plan, n_officer_notices, n_director_notices, n_ten_percent_owner_notices, median_days_to_sale, plus 30- and 90-day rolling sums. An amended notice is counted once, at its latest revision.
Using it with ziplime
manifest.json describes the bundle; the Delta table it points at is data/pit/insider_sale_notices.delta.
bundle = "data/pit/insider_sale_notices.delta" # bundle_storage_data.table_uriKnown gaps
- No pre-2023 history. See Coverage above.
- A notice is intent, not execution. Insiders file and then sell less, or later, or not at all. Treat
units_to_be_soldas an upper bound announced by an interested party, and use the Form 4 dataset for what actually happened. - Tickers are a current mapping. An issuer that changed symbol carries today's symbol on its whole history. Join on
issuer_cikwhen this matters. - Relationship is free text. The boolean flags are pattern-derived and the raw string is published beside them; a seller who wrote
SAMEisis_other_affiliate. - Amendments are rare (1.1% of filings) but real. Deduplicate on
logical_notice_idbefore summing.
Provenance and updates
Source: SEC EDGAR, Form 144 — Notice of Proposed Sale of Securities under Rule 144. US Government work, public domain. Requests are made under SEC Fair Access with a declared User-Agent, below the published rate threshold.
Rebuilt daily at 06:35 UTC by a Hugging Face Job whose script (`jobs/run.py`) lints, tests, ingests, verifies, and only then publishes. A failed gate leaves the previous revision standing.
