Introduction

Members of Congress in the Senate and the House of Representatives have access to information that can potentially make significant market moves long before the members of the public are informed. This strategy seeks to mirror those congress trades, assuming they are investing on the basis of undisclosed information. In this post, we’ll implement a trading algorithm that buys the same stocks they are buying, and applies portfolio volatility and risk controls. This strategy relies on the US Congress Trading dataset, which is a paid dataset.

Background

The “Stop Trading on Congressional Knowledge” (STOCK) Act of 2012 is legislation designed to combat insider trading by government employees. It requires officials to publicly disclose their financial transactions within 45 days. Quiver Quantitative scrapes the information from SEC reports to produce the US Congress Trading stock-universe dataset in the QuantConnect Dataset Market, which we'll be using in this trading algorithm.

In this micro-study we implement an inverse-volatility weighting scheme to form the portfolio of assets. In inverse-volatility weighting, assets with lower volatility receive higher weights and those with higher volatility receive lower weights. The purpose of this portfolio construction technique is to equalize the risk contribution of all the assets in the portfolio and avoid large exposure to highly volatile assets.

Initially the strategy took large single-stock positions during periods of low congress trading activity resulting in high concentration risk and volatility. To reduce concentration risk in the algorithm we limited the exposure of each asset to 10%. 

Implementation

To implement this strategy on QuantConnect, we'll use the Quiver Quantitative US Congress Trading dataset.

  1. We added US Equities that have been recently bought by members of Congress:
self._universe = self.add_universe(
    QuiverQuantCongressUniverse,
    lambda constituents: [c.symbol for c in constituents if c.transaction == OrderDirection.BUY]
)

2. Schedule a callback of the _trade function to rebalance the portfolio on the first trading day of each week, shortly after market open.

spy = Symbol.create('SPY', SecurityType.EQUITY, Market.USA)
self.schedule.on(self.date_rules.week_start(spy), self.time_rules.after_market_open(spy, 30), self._trade)

3. During a rebalance, we calculate the trailing 6-month volatility of all the assets in the universe and form an inverse-volatility weighted portfolio. This lets us allocate more capital to the least volatile assets. We multiple the volatility by 1.5 to aim for 150% buying power invested. The set_holdings method closes any unselected positions from last week during the rebalance. 

def _trade(self):
    symbols = list(self._universe.selected)
    if len(symbols) == 0: return
    inv_volatility_by_symbol = 1 / self.history(symbols, timedelta(6*30), Resolution.DAILY)['close'].unstack(0).pct_change().iloc[1:].std()
    targets = [
        PortfolioTarget(symbol, min(0.1, 1.5 * (inv_volatility_by_symbol[symbol] / inv_volatility_by_symbol.sum())) )
        for symbol in symbols
        if symbol in inv_volatility_by_symbol
    ]
    self.set_holdings(targets, True)

Conclusion

Members of Congress have privileged access to nonpublic information, which some members exploit for their own private gain. The STOCK Act requires these officials to disclose their trades within 45 days. These disclosures are public information, which we have used in a trading algorithm to copy their trades.

With a light risk control overlay, we could effectively harness the trade information from members of congress to build an interesting investment strategy. The algorithm achieved a 0.934 Sharpe ratio, while the S&P 500 Index ETF (SPY) achieved a 0.7 Sharpe ratio in the same period - outperforming the benchmark in risk-adjusted returns.