Congressional Disclosure Agent

Congressional disclosure AI trading team workflow

This example reads the public House Clerk periodic transaction report. It downloads the yearly index at the House financial-pdfs ZIP, then the member PDF. The bot trades only after that filing is public. It is a disclosure-following example, not a claim that the member traded on the publication date or that copying the trade is profitable. Amounts on the report are ranges, and the report can be up to 45 days late.

Availability

The source TransactionDate describes when the reported transaction occurred. ReportDate (normalized as published_at) is when the example first makes the record visible. Federal disclosure rules may permit a report as late as 45 days after the transaction, so this is not a low-latency signal and the example must never backdate availability to TransactionDate.

House and Senate periodic transaction reports are public filings. The House source is the Clerk’s yearly index ZIP and the PTR PDF named in that index. Official instructions say an option row should name the underlying security, put or call, strike, and expiration. Real filings are PDFs, and some rows leave the contract fields incomplete. Stock mode needs the ticker and the buy or sell. Option mode also needs call or put, strike, and expiration. A row without strike and expiration is skipped. Gifts, spinoffs, private companies, and money-market funds are skipped.

This example does not ship sample trades. Pass parsed official filings in disclosures or a JSON file of those filings in disclosures_path. Running the module with neither argument stops instead of inventing a portfolio. A backtest on this page is real only after those filings and market prices are supplied. Amounts on the filings are ranges, not exact share counts.

Architecture

disclosure_researcher cannot trade. trading_risk_manager is the only agent with trading tools and caps a new position at the configured percentage. Already processed disclosure IDs are ignored and old records are rejected by the configured age limit. Records stay hidden until ReportDate.

  1"""Nancy Pelosi congressional-disclosure strategy.
  2
  3Python creates the agents and runs them. It does not download filings or place orders.
  4The research agent fetches the public House reports. The trading agent places the orders.
  5"""
  6
  7from lumibot.example_strategies.agent_cycle import add_agent, run_cycle, trader_prompt
  8from lumibot.strategies import Strategy
  9
 10_FILING_URLS = (
 11    "https://disclosures-clerk.house.gov/public_disc/ptr-pdfs/2026/20033725.pdf",
 12    "https://disclosures-clerk.house.gov/public_disc/ptr-pdfs/2026/20034836.pdf",
 13    "https://disclosures-clerk.house.gov/public_disc/ptr-pdfs/2026/20035143.pdf",
 14)
 15_BOOK = (
 16    "Use filings whose report date is on or before the session date. "
 17    "Each filing line has a ticker in parentheses and an asset code in square brackets. "
 18    "Count [ST] and [AB]. Skip [OP]. "
 19    "P is a buy. S, including S (partial), is a sell. "
 20    "A line with transaction E, or a description that says gift, spinoff, or donor-advised, is not a trade. "
 21    "Each amount is a dollar range. The midpoint is dollars, never a share count. "
 22    "A sell is not a buy. For each ticker, net_dollars = buy midpoint minus sell midpoint. "
 23    "Keep every counted sell. A ticker that has both a buy and a sell uses both. "
 24    "If net_dollars is zero or negative, the weight is zero and you do not buy it, even if another agent calls it a buy. "
 25    "Example: AAA has only a buy of $3,000,000, so it can be bought. BBB has only a $15,000,000 sale, so it is not bought. "
 26    "CCC has a $375,000 buy and a $3,000,000 sell, so the net is a sale and it is not bought. "
 27    "DDD is a units line whose bracket code is AB and whose only trade is a buy, so it can be bought. "
 28    "Weights are each positive net divided by the sum of positive nets, and those weights sum to 100% of account value. "
 29    "Do not calculate shares yourself. For each positive-net ticker, call risk_calculate_stock_quantity with "
 30    "maximum_notional equal to account value times that weight and available_cash equal to cash still unspent. "
 31    "Submit exactly the quantity that tool returns. After each fill, the next order uses the cash that is left. Never short."
 32)
 33_EXIT = (
 34    "Sell a name with the order tool when a later visible filing is a sale or its scaled "
 35    "weight fell. Otherwise keep the replica invested, with cash near 0% to 5%."
 36)
 37
 38
 39class AICongressDisclosuresStrategy(Strategy):
 40    parameters = {
 41        "member": "Nancy Pelosi",
 42        "filing_urls": list(_FILING_URLS),
 43    }
 44
 45    def initialize(self):
 46        self.sleeptime = "1D"
 47        add_agent(
 48            self,
 49            "congress_researcher",
 50            (
 51                "Research public House periodic transaction reports for the named member. "
 52                "Use http_request to fetch each filing URL. Each transaction is already one line. "
 53                "Read the report date in the filing text. Ignore any filing whose report date is after as_of. "
 54                "A transaction date is not the public date. "
 55                "The ticker is the symbol in parentheses. The code in square brackets is the asset type. "
 56                "Count [ST] and [AB]. Skip [OP]. "
 57                "P is a buy. S, including S (partial), is a sell. "
 58                "Skip a line whose transaction is E, or whose description says gift, spinoff, or donor-advised. "
 59                "For each ticker write one line: TICKER buy_dollars sell_dollars net_dollars. "
 60                "Add every counted buy into buy_dollars and every counted sell into sell_dollars. "
 61                "Do not drop a sell because the same ticker also has a buy. "
 62                "buy_dollars and sell_dollars are range midpoints in dollars. "
 63                "net_dollars = buy_dollars - sell_dollars. A sale is not a buy. Do not submit orders."
 64            ),
 65            allow_trading=False,
 66        )
 67        add_agent(
 68            self,
 69            "bull",
 70            "Argue for copying the visible buys, using range midpoints. Do not submit orders.",
 71            allow_trading=False,
 72        )
 73        add_agent(
 74            self,
 75            "bear",
 76            "Argue the risks: stale filings, wide ranges, and names that should be sold. Do not submit orders.",
 77            allow_trading=False,
 78        )
 79        add_agent(
 80            self,
 81            "interpreter",
 82            "Weight only [ST] and [AB] lines whose net_dollars is positive. Name every zero or negative net as do not buy. Do not submit orders.",
 83            allow_trading=False,
 84        )
 85        add_agent(
 86            self,
 87            "trading_risk_manager",
 88            trader_prompt(book_rule=_BOOK, exit_rule=_EXIT),
 89            allow_trading=True,
 90        )
 91
 92    def on_trading_iteration(self):
 93        as_of = self.get_datetime()
 94        context = {
 95            "as_of": as_of.isoformat(),
 96            "member": self.parameters["member"],
 97            "filing_urls": list(self.parameters["filing_urls"]),
 98            "clock_rule": (
 99                "Ignore any filing whose report date is after as_of. "
100                "Transaction date is not the public date."
101            ),
102            "risk_policy": {
103                "cash_target": "0% to 5%",
104                "sizing": "scale visible filing range midpoints to account value",
105                "never_short": True,
106            },
107        }
108        run_cycle(
109            self,
110            context,
111            researcher="congress_researcher",
112            bull="bull",
113            bear="bear",
114            interpreter="interpreter",
115            trader="trading_risk_manager",
116            research_task="Fetch the filings and report only the rows already public on as_of.",
117            bull_task="Make the bull case for copying the visible book.",
118            bear_task="Make the bear case against copying the visible book.",
119            interpret_task="Assign account weights from the filing range midpoints.",
120            trade_task=(
121                "Buy only tickers whose research line has positive net_dollars. "
122                "Call risk_calculate_stock_quantity for each of those tickers and submit that quantity. "
123                "Do not buy a ticker another agent likes if its net_dollars is zero or negative."
124            ),
125        )