Skip to content

About

US Congress filings pipeline: PTR ingest, post-trade returns, leaderboard

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

CongressQuantTracker

Congressional trading intelligence + CI://TERMINAL market desk

Track House and Senate periodic transaction reports (PTRs), score them, estimate post-trade performance with yfinance, and explore the book in a Next.js app plus CI://TERMINAL — a dense Bloomberg-style ASCII desk (no Bloomberg marks or logos).

Product name: CongressInvests / CI.
Open-source repository. Do not commit .env, API keys, or the SQLite database.


What it does

Area Capability
Disclosures House Clerk FD (zip/PDF) + Senate eFD with fallbacks
Scoring 0–100 suspicion score and tags (routine → high_alert)
Market Price since trade date, estimated shares/PnL, charts (yfinance + cache)
Web UI Dashboard, politicians, monthly trades, stocks, signals, leaderboard, analyze
CI://TERMINAL Monthly wire, member photos, co-holders, sectors, candles, returns board, CI://COPILOT (English)
Copilot Tool-calling analyst (Groq / OpenAI / local). Always answers in English.

Architecture

┌───────────────────────┐          ┌───────────────────────────┐
│  web_fused (Next.js)  ├─────────►│  FastAPI :8000            │
│  :3000                │          │  SQLite + pipelines       │
└───────────────────────┘          │  yfinance market data     │
                                   │  /terminal/  (static)     │
┌───────────────────────┐          │  /politicians/*.jpg       │
│  CI://TERMINAL        ├─────────►│  /api/terminal/*          │
│  ci_terminal/         │          └───────────────────────────┘
└───────────────────────┘
Component Path Port
API server/api_server.py 8000
Web UI web_fused/ 3000
Terminal ci_terminal/ served at /terminal/ via 8000
Domain src/congress_quant_tracker/ —
Photos data/politicians/{bioguide}.jpg /politicians/{bioguide}.jpg

Quick start

Prerequisites

  • Python 3.12+ and uv (or standard pip)
  • Node.js 20+ (for web_fused)
  • Windows / macOS / Linux

1. Clone and install

git clone https://github.com/CostaJr007/congress-quant-tracker.git
cd congress-quant-tracker

# Using uv (recommended):
uv sync

# Or using standard pip:
pip install -e .

# Install frontend dependencies:
cd web_fused && npm install && cd ..

2. Environment

copy .env.example .env   # Windows
# cp .env.example .env   # Unix
Variable Default Role
MARKET_DATA_ENABLED 1 yfinance (charts, returns, enrich)
NO_YF 0 skip yfinance in the scorer only
GROQ_API_KEY — optional PDF extraction + Copilot
OPENAI_API_KEY — optional Copilot provider
TAVILY_API_KEY — optional search / ticker resolve
DISCORD_WEBHOOK_URL — optional alerts on new / flagged trades
HTTP_PROXY — HTTPS proxy if Senate eFD is blocked
DATABASE_URL local SQLite database URL
API_HOST 127.0.0.1 API bind address (0.0.0.0 exposes on LAN)
API_PORT 8000 API port

3. Run API + UI

Windows shortcuts:

  • run_ui.bat (API + Next.js + terminal)
  • start.bat (API + terminal only)

Manual launch:

# Terminal 1: API (market data ON)
set MARKET_DATA_ENABLED=1
python server/api_server.py
# (or with uv: uv run python server/api_server.py)

# Terminal 2: Next.js Web UI
cd web_fused
echo NEXT_PUBLIC_API_URL=http://localhost:8000 > .env.local
npm run dev -- -p 3000
URL App
http://localhost:3000 CongressInvests UI
http://localhost:8000/terminal/ CI://TERMINAL
http://localhost:8000/docs OpenAPI / Swagger Docs

4. Data pipelines

python scripts/update_official.py   # House Clerk (incremental by default)
python scripts/update_senate.py     # Senate (direct, then proxy)
python scripts/enrich_all.py        # sectors + photos + options + rescore
python scripts/rescore.py           # rescore only
python scripts/reparse_ptr_pdfs.py  # re-read already-downloaded PTR PDFs

(You can also prefix commands with uv run if uv is installed). Pipelines are incremental: each completed run saves a screener checkpoint (pipeline_state) and the next run only fetches filings newer than the watermark minus a 7-day overlap for late/amended disclosures — never further back than DATA_WINDOW_DAYS (2 years). Pass --days N to force a window. Repair jobs run in dry-run mode unless --apply is passed: scripts/merge_duplicate_politicians.py (same person registered under several name spellings), scripts/purge_sample_data.py (demo rows, and --trades-only to leave company market caps alone), scripts/repair_data_quality.py (absurd dates, zero→NULL amounts, bogus options) and scripts/prune_old_trades.py (rows older than the window).

HTTP equivalents live under POST /api/pipeline/*.

House PTR filings come in two shapes: born-digital PDFs with a text layer, and scanned/hand-filled pages that are images only. The parser handles both: parsers/pdf_text.py walks pdfplumber → pypdf → pypdfium2 → OCR per page, and parsers/ptr_form.py reads the printed table of scanned pages, where the side is an X under "Purchase"/"Sale"/"Exch" and the amount is an X in one of the ten lettered amount columns. Scanned filings are read through OCR, which needs an extra dependency:

uv pip install -e ".[ocr]"     # or: pip install -e ".[ocr]"

Without an OCR engine, image-only filings are reported as unread (method=empty) instead of yielding a silent zero. scripts/reparse_ptr_pdfs.py --dry-run shows what each cached PDF parses to before anything is written.

Data guarantees

All sources funnel through one ingestion path (src/congress_quant_tracker/services/ingest.py):

  • Validation & normalization before anything touches the DB (ticker, side, dates via the option-expiration sanitizer, value ranges, bounded strings).
  • Provenance on every row: Trade.notes stores the source tag (house_official, senate, ...).
  • Same-day/same-side duplicates are merged (widened ranges, backfilled fields), never silently dropped.
  • A disclosed trade is never dropped for lack of a ticket symbol: the symbol is resolved from the asset name when the company directory knows it, and otherwise stored under a stable XX…… pseudo-symbol (notes carries ;unlisted) so the disclosure stays visible.
  • Demo/sample payloads are rejected at the door.
  • scripts/purge_sample_data.py removes legacy seeded rows (dry-run by default; --apply to execute). The old scripts/seed_database.py refuses to touch the production DB unless SEED_ALLOW=1 and a disposable DATABASE_URL are set.

CI://TERMINAL

Monospace black canvas, orange bars. Brand is CI://TERMINAL.

Main widgets (CONGRESS preset)

Widget Role
MEMBERS · BY MONTH Browse by filed/traded month; photo cards; collapse heavy filers
RETURNS LEADERBOARD Rank by Δ% / ADJ% (BUY: +Δ%, SELL: −Δ%) and estimated PnL$
FOCUSED ASSET Daily candles (or line) + TX marker on the trade date
ASSET HOLDERS Who else traded the same ticker
POLITICIAN BOOK Member tickers + TX/FILED dates
SECTOR DESK House & Senate overlap by sector
CI://COPILOT F2 — English-only desk analyst

Presets: CGS (default) · GLB · EQ · MET · NWS
Editable layout (EDIT / drag) stored in localStorage (layout.v3).

First load: if an old layout hides RETURNS, click RESET.

Terminal API

Endpoint Description
GET /api/terminal/dataset?dataset=tape|stocks|... yfinance market payloads
GET /api/terminal/congress/wire Disclosures (month, chamber, party, side, q)
GET /api/terminal/congress/months Months with trades
GET /api/terminal/congress/holders/{ticker} Co-holders
GET /api/terminal/congress/sector Sector desk
GET /api/terminal/congress/politician?name= Member book
GET /api/terminal/congress/returns Returns leaderboard
GET /api/terminal/market/{ticker}?from_date= Daily OHLCV
POST /api/terminal/chat Copilot (English)
GET /api/analyze/overview Party / sector / options / suspicious
POST /api/pipeline/enrich Sectors + photos + rescore

LIVE config: ci_terminal/js/live.config.js (same-origin).

Data definitions

  • Disclosures use value ranges, not exact shares → shares/PnL are midpoint estimates.
  • change_pct = asset move since trade date (yfinance, auto_adjust).
  • return_side_adj = BUY: +Δ% / SELL: −Δ% (side-adjusted outcome).
  • Metals on the tape use Yahoo futures (GC=F, etc.) as spot proxies.
  • News wire is DEMO unless a live RSS feed succeeds. Do not invent live headlines.

See ci_terminal/DATA_DEFINITIONS.md and ci_terminal/README.md.


Web UI (web_fused)

  • Dashboard, Trades (month filter + grouping), Politicians, Stocks, Signals, Leaderboard, Analyze
  • Sidebar search + CI Terminal link
NEXT_PUBLIC_API_URL=http://localhost:8000

Repository layout

congress-quant-tracker/
├── server/
│   ├── api_server.py              # FastAPI app factory + static mounts
│   ├── deps.py                    # shared DB session, serializers, aggregates
│   └── routers/                   # one module per resource area
│       ├── core.py                #   health, dashboard, search, meta
│       ├── trades.py              #   trade list/detail, months, market
│       ├── politicians.py         #   list/detail, leaderboard
│       ├── stocks.py              #   stock aggregation
│       ├── analyze.py             #   party / sector / options analyzers
│       ├── pipeline.py            #   update / rescore / enrich triggers
│       └── terminal.py            #   CI://TERMINAL live feed + copilot
├── src/congress_quant_tracker/    # fetchers, parsers, scoring, analyzers
│   ├── enrichers/                 # market, terminal, sectors
│   └── agent/                     # CI://COPILOT
├── ci_terminal/                   # CI://TERMINAL static desk
├── web_fused/                     # Next.js UI
├── scripts/                       # update, enrich, rescore, purge
├── tests/                         # pytest (unit + API via TestClient)
├── pyproject.toml
└── README.md

Security

Do not commit: .env, *.db, data/, API keys, proxies with credentials.
.gitignore already covers secrets, price cache, node_modules, and PDFs.

Photos are served from data/politicians/ at /politicians/{bioguide}.jpg.


Useful commands

Command Action
python server/api_server.py API :8000 + /terminal/
start.bat API + open terminal
run_ui.bat API + web UI + terminal
cd web_fused && npm run dev UI :3000
python scripts/update_official.py House
python scripts/update_senate.py Senate
python scripts/enrich_all.py Sectors + photos + options + rescore
python -m pytest Unit tests + API tests (temp SQLite, no network)

Known limits

  • Yahoo/yfinance: delay and rate limits; first returns-leaderboard load can be slow.
  • Senate eFD: Akamai/403 — try a working HTTPS proxy; the pipeline falls back to CongressInvests and retries direct if the proxy is dead.
  • Some obscure tickers still have no sector; the desk uses a static ticker→sector map plus yfinance when enabled.
  • Exchange holiday calendar is not applied; the session clock may show OPEN on holidays.
  • Share and PnL figures are not official positions.

License / use

Internal research. Official House/Senate disclosures and unofficial Yahoo quotes.
Not investment advice. Do not copy Bloomberg trademarks or logos.

About

US Congress filings pipeline: PTR ingest, post-trade returns, leaderboard

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages