Insider Sentiment
Monthly insider buying and selling per company, netted from Form 4 open-market trades: shares and dollars bought versus sold.
insider_sentiment — the dataset name to pass to the Obscura API.
What one row means
Monthly insider buying and selling per issuer — a read-only VIEW that nets the open-market Form 4 transactions (`transaction_code` P and S) in `edgar_insider_transactions` into one row per company per month: shares bought vs sold, net dollar flow, and the buy/sell trade counts. Derived entirely from public SEC filings — no vendor data.
One row per One row per (cik, month) — one issuer's netted insider activity for one calendar month..
Derived in-database from edgar_insider_transactions.
Point-in-time availability
Every Obscura dataset carries available_date: the calendar day the publisher made the row
available, day-of, with no session rounding. It is the one column a backtest filters on, and it means the
same thing on every dataset in the catalog.
For insider_sentiment: derived aggregate: available_date = MAX of the constituent Form 4s' available_date for the (cik, month) bucket — the row is only fully backed by public data once its LATEST supporting filing is public (migration 000101's rule, applied here by 000169). It previously exposed the `month` bucket itself, i.e. day 1, while aggregating filings through month end: a look-ahead of up to 30 days. OPEN GRAIN QUESTION: the view buckets on the FILING month (edgar_insider_transactions.available_date), not the transaction month the dataset's name and `month` doc imply — a Postgres view binds to column OIDs, so migration 000085's global event_date -> available_date rename silently changed which column it groups by. The availability leak is fixed; the grain is a product decision still to be made.
Schema — 10 columns
The full public column list for insider_sentiment, with the meaning of every field. The same
schema is served unauthenticated at https://api.obscura.trade/v1/catalog/insider_sentiment.
| Column | Type | Description |
|---|---|---|
| cik | bigint · not null | SEC Central Index Key of the issuer whose insiders traded; the join key to `edgar_filings`, `edgar_tickers` and the rest of the EDGAR family. |
| issuer_name | text | Issuer name as reported on the Form 4s in the bucket. |
| symbol | text | Issuer ticker as reported on the Form 4s; the equity join key. |
| month | date · not null | First day of the calendar month the activity is bucketed into — the reporting PERIOD this row summarizes, not an availability date. NOTE the bucket is currently the month the Form 4s were FILED in, not the month the trades were executed in (see the dataset's `availability`). |
| shares_bought | double precision | Shares acquired in the month across open-market purchases (Form 4 transaction code `P`). |
| shares_sold | double precision | Shares disposed of in the month across open-market sales (Form 4 transaction code `S`). |
| net_dollar_flow | double precision | Net USD flow for the month: purchase notional minus sale notional (shares x price per share). Positive means insiders were net buyers. |
| buys | bigint | Number of open-market purchase transactions in the month. |
| sells | bigint | Number of open-market sale transactions in the month. |
| available_date | date | The conformed point-in-time column: the LATEST `available_date` among the Form 4 filings that make up this month's aggregate. The bucket is not computable from public data until its last constituent filing is public, so this is always >= `month` and is the column to filter/join on. |
Access insider_sentiment
Two delivery paths, one identifier. Both require an Obscura account and an active subscription; the catalog entry and the schema above are public.
import obscura
client = obscura.Client("obs_live_…")
df = client.query(
dataset="insider_sentiment",
symbols=["NVDA", "AAPL"],
start="2024-01-01",
)
Create a free account Browse all 95 datasets
Frequently asked questions
What is in the insider_sentiment dataset?
Monthly insider buying and selling per company, netted from Form 4 open-market trades: shares and dollars bought versus sold. Monthly insider buying and selling per issuer — a read-only VIEW that nets the open-market Form 4 transactions (`transaction_code` P and S) in `edgar_insider_transactions` into one row per company per month: shares bought vs sold, net dollar flow, and the buy/sell trade counts. Derived entirely from public SEC filings — no vendor data.
How do I avoid look-ahead bias with insider_sentiment?
Filter on insider_sentiment.available_date, the day the publisher made the row public. For this dataset that date is derived as follows — derived aggregate: available_date = MAX of the constituent Form 4s' available_date for the (cik, month) bucket — the row is only fully backed by public data once its LATEST supporting filing is public (migration 000101's rule, applied here by 000169). It previously exposed the `month` bucket itself, i.e. day 1, while aggregating filings through month end: a look-ahead of up to 30 days. OPEN GRAIN QUESTION: the view buckets on the FILING month (edgar_insider_transactions.available_date), not the transaction month the dataset's name and `month` doc imply — a Postgres view binds to column OIDs, so migration 000085's global event_date -> available_date rename silently changed which column it groups by. The availability leak is fixed; the grain is a product decision still to be made. A query of the form WHERE available_date <= '<as-of date>' never sees a row before it existed.
In what formats can I get insider_sentiment?
As a Parquet bulk export (POST https://api.obscura.trade/v1/download) or as JSON from the typed query API (POST https://api.obscura.trade/v1/query), both with dataset="insider_sentiment". The column schema is public at https://api.obscura.trade/v1/catalog/insider_sentiment.
Can I filter insider_sentiment by company or symbol?
Yes. insider_sentiment carries symbol, the column the API's symbols filter resolves against.