Congress Trades

Methodology

How disclosures become rows, how rows become tickers, and how tickers become an estimated portfolio. The parameters below are the pipeline's own, captured with the data snapshot.

Truth hierarchy

Everything derived can be traced to a filing: portfolio positions → normalized transactions → raw rows → the official document.

  • Official fields: filer name, office, filing date, transaction date, notification date, asset description, transaction type, reported dollar range, owner.
  • Derived / estimated fields: ticker match and confidence, midpoint dollars, estimated shares, current value, weights, returns, sector allocation, reporting-lag statistics.

Nothing derived is ever written back onto a raw row.

How this is calculatedmodel parameters · click to expand
Shares formula
amount_mid / close(tx_date)
Return index
100 * (value + realized) / invested
Benchmark
SPY
Portfolio start date
2020-01-01
Price provider
yfinance
Price lookup window (days)
5
Ticker publish threshold
0.9
Positions floored at zero
Yes
Cash modelled
No
Dividends modelled
No

Full method, tiers of ticker matching, and the review queue are documented on the methodology page.

Smart portfolio (estimated) — v1 methodology

For each politician, over portfolio-eligible rows (published ticker, asset_class in (stock, etf), tx_date, amount_mid, tx_type in buy/sell/partial_sale), in date order:

1. est_shares_traded = amount_mid / close(tx_date) — close on the transaction date, else the next trading day within 5 days, else the row is excluded (no_price). 2. Buy: position += shares; invested_cum += amount_mid; cost basis += amount_mid. 3. Sell / partial sale: shares_sold = min(position, est_shares_traded); realized_cum += shares_sold × close; cost basis reduced pro-rata. Any excess (sell with no modelled shares) is recorded as unmatched_sell_dollars and does not create a short — positions are floored at zero. 4. Exchange / unknown rows are excluded from modelling and counted in excluded. 5. Daily revaluation: est_value(t) = Σ position × close(t) from first trade to latest price date. 6. Cash is not modelled (we only see trades, never balances). Dividends are not modelled. 7. Benchmark: a shadow SPY portfolio receives the identical cash flows — each buy of $X on date d buys X / SPY_close(d) SPY shares; each modelled sell of $Y sells Y / SPY_close(d) SPY shares (floored at 0). 8. Return index (money-in / money-out neutral): index(t) = 100 × (value(t) + realized_cum(t)) / invested_cum(t); portfolio_return_pct = index(latest)/100 − 1; same formula for the SPY shadow. This answers "what did each disclosed dollar turn into" and is comparable across the two. 9. est_value_change_30d = value(t) − value(t−30d) − (buys − modelled sell proceeds in the window).

Politician stats: - avg_reporting_lag_days = mean(filing_date − tx_date). - avg_filing_interval_days = mean gap between distinct filing dates. - days_since_last_filing = today − max(filing_date). - top_holdings = est_value / total; sector_allocation = Σ est_value by sector (security_metadata, else "Unclassified").

Prices are for enrichment; the filing tells us a dollar range, not shares — every share figure is a model output.

Normalization rules

  • Transaction type → buy | sell | partial_sale | exchange | unknown. House codes P / S / S (partial) / E; Senate Purchase / Sale (Full) / Sale (Partial) / Exchange.
  • Amount "$15,001 - $50,000" → amount_low=15001, amount_high=50000, amount_mid=32500.5. "Over $50,000,000" → low=50000001, high=NULL, mid=low and reason open_ended_amount.
  • Owner → self | spouse | joint | dependent | unknown (House SP/JT/DC, blank = self; Senate Self/Spouse/Joint/Child).
  • Asset class → stock | etf | mutual_fund | option | bond | crypto | other | unknown from House [XX] codes, Senate "Asset Type", then text hints.
  • Reporting lag = filing_date − tx_date in days (official dates, derived number).

Review queue: a normalized row gets needs_review=true (and is kept, never discarded) when any of: amount_missing, amount_unparseable, amount_single_value, open_ended_amount, tx_date_missing, tx_type_unknown, ticker_below_threshold, ticker_conflict (printed ticker ≠ matched ticker), low_parser_confidence, asset_class_unknown.

Scanned filings (House paper PTRs and their broker attachments, Senate paper filings) are read by OCR (parser_version ocr_grid_v1): each page is straightened, the form's grid recovered, text read by OCR and the X or check in each choice cell read as ink. Every OCR row carries a confidence and the reasons it may be wrong (for example ocr_owner_unreadable, ocr_date_uncertain); below 0.8 it goes to review, and the site marks rows from scans with an OCR tag. Filings with raw_status in (needs_ocr, needs_review, error) appear in the filing review list: not yet read, read without recoverable rows (often handwriting), or failed. Analysts fix rows through manual_overrides (raw row untouched; normalization re-applies).

Truth hierarchy: official fields (filer, office, filing date, transaction date, asset text, transaction type, reported dollar range, owner) are copied from the filing; everything else (ticker match, midpoint dollars, shares, values, weights, returns, sector allocation, stats) is derived and labelled Estimated. Every derived row traces back: portfolio_positions → transactions_normalized → transactions_raw → filings.source_document_url.

Entity resolution (ticker matching)

Tiers, first hit wins; each tier has a fixed confidence:

1. Ticker printed in the filing (Senate Ticker column, or (NVDA) / NYSEARCA: DIA in House text) AND exists in securities_master — 0.98 (0.95 if the issuer name similarity < 0.5, reason ticker_conflict). 2. Exact normalized issuer-name match (clean_issuer_name) — 0.95. 3. Alias match (curated aliases + SEC name variants) — 0.92. 4. Fuzzy (rapidfuzz token-set ratio on cleaned names, top-1 ≥ 90 and margin ≥ 5 over top-2) — 0.90 × ratio/100 (so ≥ 0.81, i.e. below the publish threshold → review). 5. None — 0.0.

Published ticker is set only when confidence ≥ 0.90. Otherwise the row displays as text-only with ticker_candidate visible in the review queue. Options, bonds, mutual funds without a ticker, and other classes are never modelled in portfolios even if a ticker matches.

Securities universe: SEC company_tickers_exchange.json (~10.4K issuers). Sector / industry / market cap come from the market-data provider (yfinance by default, Polygon optional).

Most held by Congress (estimated)

The sum of every member's estimated position, per security: members holding it, the party split, the estimated value, the largest holder and their share of the total, and members buying or selling it in the last 90 days. A position is what a member's disclosed trades since the portfolio start date add up to, valued at the latest close. Holdings owned before a member's disclosed trades began are not visible, so this measures what Congress has been buying, not a full balance sheet. A large value can rest on a single member, which is why the top holder's share is always shown.

Options trades

Strike, expiry, call or put, and contract count are read from each option trade's filed text; a field the filer did not state is left empty. Most filers state strike and expiry; few state the number of contracts.

Where the contract count is stated, a bought contract is valued at its intrinsic value: what it would be worth exercised at the stock's close on its expiry date, or today if still open (max(0, price - strike) x 100 x contracts for calls, the reverse for puts). This leaves out the premium paid, time value and any early sale, so it is an estimate, not profit; the disclosed dollar range is the only official figure.

Stock prices are adjusted for splits and filed strikes are not, so the price is restated in the share terms of the trade date using the stock's split history before comparing it with the strike.

"Went their way" counts bought contracts whose stock then moved in the direction the contract bets. "Open" means unexpired with no later sale or exercise of the same contract filed.

Legal

Independent third-party platform; not affiliated with or endorsed by any member of Congress.

Data sourced from publicly available filings and records.

Portfolio, holdings, returns, and allocations are estimates and may differ from actual values.

Informational and educational only; not investment advice.

Insider data (SEC Form 4)

Corporate insiders (officers, directors and 10% owners) report their transactions on SEC Form 4. The company universe is the S&P 500, the Nasdaq-100 and the 150 tickers Congress trades most (extendable by hand). Per company the pipeline reads the EDGAR submissions index, takes every Form 4 and 4/A, and parses the ownership XML into non-derivative and derivative rows (holdings-only rows are flagged). Values are exact as filed and carry a Filed label, never an Estimated one.

  • Filed fields: shares, price, transaction value, post-transaction holdings, transaction code, direct/indirect ownership, the Rule 10b5-1 plan flag, and the filing and report dates.
  • Transaction kind from the Form 4 code: P → open_market_buy, S → open_market_sale, A → award, M/X → option_exercise, F → tax_withholding, G → gift, C → conversion, anything else → other. Only open-market buys and sales enter the buy, sell and net figures.
  • Executive = the title matches CEO, CFO, COO, President (not Vice), Chair, Founder or CTO. Insider and company stats (12-month and 90-day buy, sell and net value, share of sale value under a 10b5-1 plan, last trade) are sums of filed values.
  • Every insider row links to its EDGAR filing folder and to the Form 4 XML. SEC fair-access limits are respected and raw XML is cached.

Congressional figures remain disclosed dollar ranges and range midpoints; the two tiers are never mixed in one number.

Whale layer

Everything in the whale layer is derived and labelled Estimated. Politician activity score (365-day window): volume_12m is the sum of range midpoints over buys and sells; largest_trade_mid and median_trade_mid likewise; late_filings counts trades with a reporting lag over 45 days; the forward return is close(t + 30 trading days) / close(t) − 1, sign-adjusted (buys positive, sells negative); a trade is well timed when that sign-adjusted return is at least +15%.

  • Whale score = 100 × (0.5 × percentile of 12-month volume + 0.3 × percentile of largest trade + 0.2 × percentile of 12-month trade count), percentiles taken among members with at least one trade in the window.
  • Notable = a curated list, plus the top 10 by volume, plus any score of 90 or more; the reason is shown with the flag.

Unusual events are scored 0–100 (clamped) and de-duplicated:

  • whale_trade — range low of $250,001 or more; score 40 + 20 × log10(midpoint / 250,000).
  • cluster_buy / cluster_sell — three or more distinct members, same ticker and side, within a rolling 14 days; 30 + 15 × (n − 3), +10 if it contains a whale trade.
  • late_filing — reporting lag over 45 days (the STOCK Act deadline); 30 + (lag − 45) / 3, +15 if a whale trade.
  • well_timed — sign-adjusted 30-day forward return of +15% or more; 40 + 100 × (return − 0.15), +10 if a whale trade.
  • first_time_ticker — a member's first-ever trade in a ticker with a range low of $50,001 or more; 25 + 15 × log10(midpoint / 50,000).
  • exec_open_market_buy — an executive open-market buy of $100K or more; 45 + 15 × log10(value / 100,000).
  • exec_large_sale — an executive open-market sale of $5M or more; 40 + 15 × log10(value / 5,000,000), −15 under a 10b5-1 plan.
  • insider_politician_overlap — a member trade within ±30 days of an executive open-market trade in the same ticker; 50, +15 if the directions are opposite, +10 if a whale trade.

Insider events use exact filed values; congressional events use range midpoints. Every event links to the congressional filing or the Form 4 behind it.

Committee overlap

Committee rosters come from unitedstates/congress-legislators (committees-current.json, committee-membership-current.json), joined to members by Bioguide id — no name matching. Titles and leadership seats (chair, ranking member, vice chair) come from the same source.

The committee-to-sector map is our editorial judgement, not an official classification, and every surface that shows it says so. A committee is mapped where its published jurisdiction covers an industry's regulation, funding or oversight: Armed Services → Industrials; Banking → Financial Services and Real Estate; Ways and Means → Healthcare and Financial Services; Judiciary → Technology and Communication Services. Broad money committees — Appropriations, Budget, Rules, Ethics, Foreign Affairs — are deliberately unmapped, because a jurisdiction that touches everything would flag everything and mean nothing.

  • committee_conflict fires when a trade has a published ticker with a known sector, an amount low of $15,001 or more, and the member sits on a parent (not sub-) committee whose mapped sectors include that sector.
  • One event per trade. Where several committees qualify, the most pointed wins: a leadership seat first, then the committee with the fewest mapped sectors — the most specific jurisdiction.
  • Coverage limit. The upstream roster is current membership only, so an overlap is asserted only for trades dated on or after 2025-01-03, the start of the current Congress. Earlier trades are never judged against today's committee seats, and former members carry no seats at all.

This describes an overlap of duty and holding: a member traded a stock in a sector a committee they sit on oversees. An overlap of duty and holding is not an allegation of insider trading or of any other violation. Nothing on these pages should be read as one, and the scores rank how large and how specific an overlap is, nothing more.