Introduction

The STOCK Act of 2012 requires US Senators to publicly disclose their stock trades within 45 days. Lazzaretto (2024) finds that the stocks Senators buy earn abnormal returns once those disclosures become public. The strategy in this research post copies the disclosed purchases by holding an equal-weighted portfolio of the US common stocks that Senators disclosed buying over the last 30 days. From September 2021 to September 2026, the strategy achieved a 1.054 Sharpe ratio, outperforming the 0.363 Sharpe ratio for a buy-and-hold position in the SPY.

Background

Since the STOCK Act of 2012, members of Congress must disclose each stock trade within 45 days in a Periodic Transaction Report, which lists the stock, whether the trade was a purchase or a sale, the transaction date, and the trade size as one of 11 dollar ranges. Lazzaretto (2024) finds that, measured from the disclosure date, the stocks purchased earn more than 90 basis points of abnormal return over the following month, peaking about 30 days after the report becomes public.

Lazzaretto (2024) traces the post-disclosure return to other investors copying the disclosed trades. They copy because some Senator trades are highly profitable, earning about 9 basis points per day, often in industries under heavy government oversight such as oil and gas, chemicals, semiconductors, and defense. Investors can't tell at disclosure which trades are the profitable ones, so they copy every disclosed purchase and push prices up. Fishman and Hagerty (1995) predict this effect in a general model of insider-trade disclosure, where a disclosed trade moves prices even when the insider is uninformed, as long as the market believes the insider might be informed. Because the price reaction does not depend on knowing which trades are informed, a systematic strategy can copy every disclosed purchase.

To capture the post-disclosure return, the strategy in this research post forms an equal-weighted portfolio of the US common stocks that Senators disclosed purchasing over the trailing 30 days. Every time a stock enters or exits this set, the portfolio rebalances. Since the portfolio is formed from disclosure dates rather than transaction dates, the strategy only trades on purchases after they become public.

Implementation

To implement this strategy, we start by defining the holding period and adding a universe of US Congress trades in the initialize method so the algorithm receives the new disclosures each day.

# Define the holding period.
self._holding_period = timedelta(30)
# Add the stream of Senate purchase disclosures.
self.add_universe(QuiverQuantCongressUniverse, self._record_disclosures)
self._last_report_date_by_symbol = {}
self._needs_rebalance = False
# Warm up to load the previous 30 days of disclosures before we start trading.
self.set_warm_up(self._holding_period)

We also add a second universe that selects the stocks to trade each day, along with a Scheduled Event that checks whether to rebalance the portfolio at 8 AM Eastern Time (ET) every trading day.

# Add a universe that selects the assets we'll trade: US common stocks with a
# Senate purchase reported over the last 30 days.
self.universe_settings.resolution = Resolution.DAILY
self._universe = self.add_universe(self._select_assets)
# Add a Scheduled Event to rebalance every day at 8 AM.
self.schedule.on(self.date_rules.every_day('SPY'), self.time_rules.at(8, 0), self._rebalance)

Each day, the _record_disclosures universe selection function records the latest report date of each stock that Senators disclosed buying.

def _record_disclosures(self, data: List[QuiverQuantCongressUniverse]) -> List[Symbol]:
    for d in data:
        if d.house == Congress.SENATE and d.transaction == OrderDirection.BUY:
            self._last_report_date_by_symbol[d.symbol] = d.report_date
            self._needs_rebalance = True

It then drops the stocks with a last reported purchase more than 30 days old. The method leaves the universe unchanged, so the Congress trading universe collects disclosures without adding any securities to the algorithm.

cutoff = self.time - self._holding_period
for symbol in [s for s, date in self._last_report_date_by_symbol.items() if date < cutoff]:
    self._last_report_date_by_symbol.pop(symbol)
    self._needs_rebalance = True
return Universe.UNCHANGED

Each day, the _select_assets universe selection function selects the subset of these stocks that are US common stocks, excluding ADRs and REITs.

def _select_assets(self, fundamentals: List[Fundamental]) -> List[Symbol]:
    if self.is_warming_up:
        return []
    return [
        f.symbol for f in fundamentals
        if (f.symbol in self._last_report_date_by_symbol and
            f.company_reference.country_id == "USA" and
            f.security_reference.security_type == "ST00000001" and
            not f.security_reference.is_depositary_receipt and
            not f.company_reference.is_reit)
    ]

Finally, on the days when a new purchase is reported or an old purchase drops out of the 30-day lookback window, the _rebalance method forms an equal-weighted portfolio of the current universe constituents, liquidating the stocks that left the selection.

def _rebalance(self) -> None:
    if not self._needs_rebalance or self.is_warming_up:
        return
    self._needs_rebalance = False
    self.set_holdings([PortfolioTarget(symbol, 1 / len(self._universe.selected)) for symbol in self._universe.selected], True)

Results

We backtested the strategy from September 2021 to September 2026. Over that period, the strategy earned a 1.054 Sharpe ratio. In contrast, a buy-and-hold position in the SPY over the same time period achieved a 0.363 Sharpe ratio. Therefore, the strategy outperformed the benchmark.

We ran a parameter optimization job to test the sensitivity of the chosen parameter. The holding period sets how many days a stock stays in the portfolio after a Senator has reported purchasing it. We tested holding periods of 20 to 40 days in steps of 1 day. Of the 21 holding periods, 21/21 (100%) produced a greater Sharpe ratio than the benchmark. The following image shows the Sharpe ratios of the tested holding periods:

The red circle in the preceding image identifies the holding period we chose as the strategy's default. We chose a holding period of 30 days because it matches the 30 day horizon over which Lazzaretto (2024) finds the post-disclosure return.

The Sharpe ratio peaks at 1.264 with a 24-day holding period and stays between 1.219 and 1.264 from 23 to 26 days, but the edges of that range are abrupt, with the Sharpe ratio jumping from 0.988 at 22 days to 1.260 at 23 days and falling from 1.219 at 26 days to 0.954 at 27 days. Because a one-day change in the holding period moves the Sharpe ratio this much, the 23- to 26-day range likely reflects a few trades in this sample rather than a lasting property of the strategy. Beyond 33 days, the Sharpe ratio drifts down to between 0.859 and 0.931, which is consistent with older disclosures carrying a weaker signal.

The strategy outperformed the benchmark for all 21 of the holding periods we tested, with Sharpe ratios between 0.840 and 1.264. So in this sample, its advantage over the benchmark does not hinge on an exact holding period. Future research could add a short leg in the stocks that Senators disclosed selling. Another direction is to rank Senators by the past performance of their disclosed purchases and copy only the top performers.

References