←Back to the notebook

Python Political Trading Examples: Five Scripts for Congressional Stock Trades

Five Python scripts for congressional stock trades, each runs as written: this week's disclosures, what Congress is buying, one stock's filings, filing lag by chamber, one member's history. pip install, one free key; two scripts need PRO for full counts.

SentiSense Team
SentiSense Team
September 21, 2026 · 4 min read

The fastest way to work with political trading data in Python is pip install sentisense, one API key, and the five scripts below. Each one runs as written. Together they cover the questions people actually ask of congressional trade data: what was disclosed this week, what Congress is buying, who traded a given stock, how late the filings arrive, and what one member's history looks like.

The data behind them is the STOCK Act disclosure record: House filings via the Clerk of the House, Senate filings via the Senate eFD system, each trade reported as a dollar range within 45 days of the transaction. If you want the background on where every congressional dataset comes from, the trackers comparison covers it. This page is only code.

Setup

pip install sentisense
export SENTISENSE_API_KEY=ss_live_YOUR_KEY

Every script starts the same way:

import os
from sentisense import SentiSenseClient

client = SentiSenseClient(api_key=os.environ["SENTISENSE_API_KEY"])

1. What did Congress disclose this week?

get_politician_activity returns trades across every tracked member, most recently disclosed first. The window is the disclosure date, so a trade from June that was filed yesterday shows up today.

trades = client.get_politician_activity(lookback_days=30, limit=500)
print(f"{len(trades.data)} of {trades.total_count} disclosures in the last 30 days")

for t in trades.data[:10]:
    print(f"{t.disclosureDate}  {t.politicianName:24} {t.chamber:6} {t.state}  "
          f"{t.transactionType:8} {t.ticker:6} {t.amountRange}  {t.owner or '-'}")

The fields worth knowing: transactionType is PURCHASE, SALE, EXCHANGE or OTHER (not BUY and SELL, which is the insider vocabulary), amountMin and amountMax are the parsed ends of the range, owner says whether the filer, a spouse, a child or a joint account traded, and assetType separates stocks, ETFs and options, with the strike and expiry under assetMetadata when it is an option.

2. Which tickers is Congress buying?

The 90-day window holds more rows than one response returns, so page through it with limit and offset, then count purchases.

from collections import Counter

rows, offset = [], 0
while True:
    page = client.get_politician_activity(lookback_days=90, limit=500, offset=offset)
    rows.extend(page.data)
    offset += len(page.data)
    if not page.data or offset >= page.total_count:
        break

buys = Counter(t.ticker for t in rows if t.transactionType == "PURCHASE" and t.ticker)
for ticker, n in buys.most_common(10):
    print(f"{ticker:6} {n} purchases")

A count of filings is not a count of dollars. Weight by amountMin if you want a rough dollar view, remembering that a range of $1,001 to $15,000 is the most common bucket by far, so the low end understates and the high end overstates.

3. Who in Congress traded one stock?

nvda = client.get_politician_filings("NVDA", lookback_days=180)
for t in nvda.data:
    print(t.transactionDate, t.politicianName, t.transactionType, t.amountRange)

Pair this with the ticker's own data if the question is "did they trade before the move". The same client has get_stock_chart for the price history and get_stock_sentiment for the SentiSense Score around those dates.

4. How late are the disclosures?

Every row carries disclosureDelayDays, the gap between the trade and the filing. Grouping it by chamber answers a question no tracker page shows.

import statistics
from collections import defaultdict

lag = defaultdict(list)
for t in rows:                      # from script 2
    if t.disclosureDelayDays is not None:
        lag[t.chamber].append(t.disclosureDelayDays)

for chamber, days in lag.items():
    late = sum(1 for d in days if d > 45)
    print(f"{chamber:6} n={len(days):4}  median={statistics.median(days):5.0f} days  "
          f"past the 45-day rule: {late}")

For the ninety days of filings before this post was written, the House median was 28 days and the Senate median was 116, with most Senate rows past the 45-day rule. Run it on the day you read this; the number moves with each filing batch.

5. What does one member trade?

Find the slug first, then pull the member. The directory is not tier-gated and does not count against your quota, so it is the right place to resolve names.

hit = client.get_politician_directory(q="Pelosi")
slug = hit["members"][0]["urlSlug"]          # "Nancy-Pelosi"

member = client.get_politician_member(slug)
print(member.data.profile.displayName, "trades on record:", member.total_count)
print("most traded:", member.data.topTickers[:5])
for t in member.data.recentTrades[:5]:
    print(t.transactionDate, t.ticker, t.transactionType, t.amountRange)

recentTrades is one page, newest transaction first; total_count is the whole history, so page with limit and offset the same way as script 2.

What the free key returns

Every result is a PreviewResult: .data holds the rows, .is_preview says whether the tier trimmed them, and on a preview .upgrade carries the message and link to lift it. On a free key the activity feed returns the five most recent disclosures, a ticker's filings the top three, and a member page a preview. The directory is full on every tier. Scripts 2 and 4 page through the whole window, so they need PRO to produce the counts above; scripts 1, 3 and 5 run on the free key and show you the shape of the data.

An AI agent gets the same five answers without the script: npx -y sentisense congress and npx -y sentisense congress NVDA in the sentisense CLI, the congressional tools on the MCP connector, or the politicians-stock-tracker skill for Claude Code, Codex and OpenClaw. Same shape, other verticals: Python stock sentiment examples and Python earnings examples.

Ready to run script one? Get a free API key → and paste it into the export line above.