A local dashboard that pulls SEC EDGAR Form 4 (insider transaction) filings and makes them actually readable: decodes the transaction code, computes the dollar value of each transaction (shares × price — EDGAR never shows this), and merges the "Reporting person" / "Issuer" index-pair into a single record automatically.
Search by company name, ticker, person name, or raw CIK — no need to already know a CIK number.
- Live EDGAR data — pulls a filer's real Form 4 history via SEC's submissions and filing-index APIs
- Full transaction code glossary — all 19 official SEC codes (P, S, V, A, D, F, I, M, C, E, H, O, X, G, L, W, Z, J, K), grouped by category, with plain-language descriptions
- Computed dollar values — shares × price per transaction, plus a portfolio-level acquired/disposed/net value summary
- Accession-number merging — automatically collapses the paired "Reporting"/"Issuer" index entries EDGAR shows separately into one record
- Name/ticker resolution — type a company name, ticker, or person's name; handles ambiguous matches with a picker, and EDGAR's "Last First" name ordering (e.g. "Tim Cook" -> "Cook Timothy D")
- Live progress tracking — fetches run in the background with a real progress bar, since pulling a prolific filer's full history is genuinely slow (each filing costs 2 HTTP requests, rate-limited)
- Search and filter — free-text search across issuer/ticker/person/ accession, plus click-to-filter by transaction code
Requires Python 3.9+ and pip on your PATH.
pip install -r requirements.txtSEC requires every request to identify who's making it, or it returns a 403. Set this before running (replace with your real name and email):
macOS / Linux:
export EDGAR_USER_AGENT="Your Name your.email@example.com"Windows (PowerShell):
$env:EDGAR_USER_AGENT="Your Name your.email@example.com"Windows (Command Prompt):
set EDGAR_USER_AGENT=Your Name your.email@example.compython3 app.py(On Windows, python app.py if python3 isn't recognized.)
Then open http://127.0.0.1:5000 in a browser.
Type a company name, ticker, person name, or CIK into the search box and click "Load filings." For a prolific filer, this can take a little while — watch the progress bar (and the terminal, which logs each filing as it's fetched).
pip install -r requirements-dev.txt
pytest tests/ -vThe suite runs entirely offline using real captured EDGAR responses saved
in sample_data/ — no live network calls, no rate-limit concerns. Several
tests are direct regression tests for bugs found during manual testing
(e.g. EDGAR's legacy feed rendering broken ARRAY(0x...) text instead of a
name for individual filers, or "Tim Cook" returning zero results in natural
word order since EDGAR stores names as "Last First").
edgar_client.py— all HTTP calls to EDGAR: submissions API, filing index, raw filing documents, ticker list, and the browse-edgar name searchresolve.py— turns whatever the user typed (name/ticker/CIK) into one or more concrete CIK candidatesform4_parser.py— parses a Form 4 XML document into flat transaction records (both Table I non-derivative and Table II derivative)codes.py— the full official transaction code table (label, category, direction, description) — kept in sync withstatic/codes.jsfetch_and_merge.py— orchestrates fetch -> parse -> decode -> group-by-accession for one CIK, with progress callback supportapp.py— Flask server: serves the dashboard and exposes/api/resolve,/api/filings/start+/api/filings/status/<job_id>(background job + polling, for the progress bar), and/api/searchstatic/— the dashboard frontend (vanilla HTML/CSS/JS + Chart.js, no build step)sample_data/— real captured EDGAR responses (Form 4 XML, browse-edgar search feeds — including the ones behind real bugs found in testing), used both for offline testing and as pytest fixturestests/— pytest suite covering the parser, code glossary, and resolution logic, including regression tests for real bugs found during manual testing
- Only pulls the most recent slice of a filer's history (EDGAR's submissions API returns "recent" filings in one call; older history is paginated into separate files this tool doesn't fetch yet)
- Fetches are capped at 40 filings by default (
limitquery param on/api/filings/start) to keep load times reasonable for prolific filers - No linking yet for insider-to-insider transfers that use two separate accession numbers (e.g. a gift where one person's disposal and another's acquisition are reported in different filings) — see Roadmap
- Form 3 (initial ownership statement) support — establishes the ownership baseline that Form 4 transactions are changes against
- Heuristic linking of insider-to-insider transfers that use two separate accession numbers rather than one shared one
- Deploy beyond localhost once the local version is fully working
MIT — see LICENSE.
