insidertracker
A Python wrapper for OpenInsider.com that scrapes SEC Form 4 insider trading data and caches it locally in DuckDB.
Installation
pip install insidertracker
Quick Start
from insidertracker import InsiderTracker
tracker = InsiderTracker()
# Insider trades for one or more tickers
df = tracker.ticker.get_insider_trades("AAPL")
df = tracker.ticker.get_insider_trades(["AAPL", "TSLA", "NVDA"])
# Latest cluster buys (multiple insiders buying the same stock)
df = tracker.cluster_buys.get_cluster_buys()
# CEO/CFO purchases over $25k (high-signal)
df = tracker.ceo_cfo_purchases_25k.get_ceo_cfo_purchases_25k()
Endpoints
| Attribute | Method | Source Page |
|---|---|---|
ticker |
get_insider_trades(ticker) |
Screener filtered by ticker |
ticker |
get_insider_sales(ticker) |
Same, filtered to sales only |
cluster_buys |
get_cluster_buys() |
/latest-cluster-buys |
insider_purchases |
get_insider_purchases() |
/insider-purchases |
insider_sales |
get_insider_sales() |
/insider-sales |
insider_purchases_25k |
get_insider_purchases_25k() |
/latest-insider-purchases-25k |
ceo_cfo_purchases_25k |
get_ceo_cfo_purchases_25k() |
/latest-ceo-cfo-purchases-25k |
ceo_cfo_sales_100k |
get_ceo_cfo_sales_100k() |
/latest-ceo-cfo-sales-100k |
top_officer_purchases_week |
get_top_officer_purchases_week() |
/top-officer-purchases-of-the-week |
screener |
get(**kwargs) |
/screener with full filter support |
All methods return a Polars DataFrame.
Common Parameters
All endpoint methods accept these optional parameters:
| Parameter | Type | Description |
|---|---|---|
stale_threshold |
timedelta |
How old cached data can be before re-fetching |
force_update |
bool |
Bypass cache and always re-fetch |
min_date |
datetime |
Only return rows with filing_date after this date |
max_date |
datetime |
Only return rows with filing_date before this date |
import datetime as dt
df = tracker.cluster_buys.get_cluster_buys(
stale_threshold=dt.timedelta(days=1),
force_update=False,
min_date=dt.datetime(2025, 1, 1, tzinfo=dt.timezone.utc),
max_date=dt.datetime(2025, 12, 31, tzinfo=dt.timezone.utc),
)
Screener
The screener module exposes the full OpenInsider screener with 30+ filter parameters:
df = tracker.screener.get(
ticker="AAPL",
transaction_value_min_usd_thousands=100,
filing_date_within_days=30,
page_size=200,
)
Data Schema
Ticker / Latest Purchase & Sale endpoints
| Column | Type | Description |
|---|---|---|
filing_date |
TIMESTAMPTZ |
SEC filing timestamp |
trade_date |
DATE |
Date the trade occurred |
ticker |
VARCHAR |
Stock symbol |
company_name |
VARCHAR |
Company name |
insider_name |
VARCHAR |
Name of the insider |
title |
VARCHAR |
Insider's role (CEO, CFO, Dir, etc.) |
trade_type |
VARCHAR |
e.g. S - Sale, P - Purchase |
price |
DOUBLE |
Trade price per share |
quantity |
DOUBLE |
Number of shares traded |
owned |
DOUBLE |
Shares owned after trade |
ownership_change |
DOUBLE |
Fractional change in ownership (e.g. -0.20) |
value |
DOUBLE |
Total value of trade in USD |
Cluster Buys
Same as above, with insider_name and title replaced by:
| Column | Type | Description |
|---|---|---|
industry |
VARCHAR |
Industry classification |
num_insiders |
VARCHAR |
Number of insiders who bought |
Database
Data is cached in a local DuckDB database. The path is resolved in this order:
INSIDERTRACKER_DBenvironment variabledatabasekey in the config file- Default:
~/.config/insidertracker/insidertracker.db(Linux),~/Library/Application Support/insidertracker/insidertracker.db(macOS),%APPDATA%\insidertracker\insidertracker.db(Windows)
To use a custom path:
export INSIDERTRACKER_DB=/path/to/my.db
Or create a config file at the platform default config path:
{
"database": "/path/to/my.db"
}
Individual Classes
You can import and use each module independently without going through InsiderTracker:
from insidertracker import CeoCfoPurchases25k
ceo = CeoCfoPurchases25k()
df = ceo.get_ceo_cfo_purchases_25k(force_update=True)
Metadata
Release files for insidertracker 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| insidertracker-0.1.2.tar.gz | 8.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| insidertracker-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.5 kB
Release files / insidertracker-0.1.2.tar.gz
| Download URL | insidertracker-0.1.2.tar.gz |
|---|---|
| Size | 8.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d05a1877cbbf5506d69918f9bc0daa0384ca1c917f99ef8a1e19290c9a0f4e9
|
|
BLAKE2b-256 checksum How to use checksums |
10b242836abd16b9dcfe14fdd8d9291dfbd7b5d969bd95093fa605589b3d24af
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|
Release files / insidertracker-0.1.2-py3-none-any.whl
| Download URL | insidertracker-0.1.2-py3-none-any.whl |
|---|---|
| Size | 15.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0e8fda6f89fbc263406196150eec75ce41b565af5c85069ed88da15f30b7306e
|
|
BLAKE2b-256 checksum How to use checksums |
134f2170e5cb6b91b2975ebcbdeec7f42abae7b3d0535c9186f0757d4210f8b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.12
|