Insider trading visualised with Python & sec-api.io

Jan L. Schroeder
Aug 24 · 4 min read

  • Reed Hastings (CEO, Netflix) sold $15M of his shares 2 days before a class action lawsuit hit the company and the stock crashed
  • Mark Zuckerberg (CEO, Facebook) sold $296M of his shares before the stock plunged

Let’s explore how we can get the data telling us this story and how we can use it to perform due diligence on investment ideas and to monitor risks impacting our investment portfolios.

You can run the tutorial as Python notebook in your browser (click here). Or clone the GitHub repo.

First, what are insider trades?

Insider trades are derivative and non-derivative transactions recorded in SEC filings of type 4 (namely: statement of changes in beneficial ownership of securities).

If the owner of a security (e.g. Mark Zuckerberg) wants to sell some of his shares (or acquire new shares), he is obligated to report this transaction to the SEC using Form 4. The SEC publishes the report (aka filing) on their SEC EDGAR page. We call him “Reporter”.

The company (e.g. Facebook) that issued the shares (the shares that Zuckerberg sold) is obligated to report this transaction, too. The call the company “Issuer”.

Both, the Report and Issuer file Form 4. In this case, we end up with two filings stating the same amount of transactions. Later in our analysis we need to be aware of such “double ups” and remove them.

Figure 1) Mark Zuckerberg, Form 4, SEC Filing

Figure 1 shows a Form 4 stating Zuckerberg’s $23M transaction performed on 19.8.2019. In order to derive at $23M, we have to sum up all “disposal” transactions in table 1 and subtract the sum of all “acquisition” transactions.

Each row in table 1 represents a transaction — either a disposal (marked with a capital D) or acquisition (capital A) of derivatives. The amount of shares sold and the price paid is also shown.

There are two versions published: a HTML version (see an example here) and a TXT version including XML (see an example here). We use the TXT version for our analysis.

Who are insiders?

anyone who is an owner of more than 10% of a company, or any director or officer of the issuer of such a security

Source: Sections 16(a) and 23(a) of the Securities Exchange Act of 1934

When is the sale/acquisition by an insider reported?

before the end of the second business day following the day on which a transaction resulting in a change in beneficial ownership has been executed

Source: Sections 16(a) and 23(a) of the Securities Exchange Act of 1934

How do we know when an insider transaction has been reported?

Forms 3, 4, and 5 [are] electronically [filed]

For this tutorial we only focus on Form 4. In the real world inside a production system you have to consider Form 3 and 5 as well. We use the query API provided by sec-api.io to access historical Form 4s. SEC API also provides a real-time live feed of filings that can be used to generate trading signals (not relevant here).

If you’re keen to understand more about Form 4, check out the SEC’s official documentation here.

Let’s Start

We use sec-api.io in order to query SEC filings. sec-api provides a RESTful API to search and filter all SEC filings filed since 1993 by CIK, ticker, form type, filing data and company name.

In this tutorial, we only use Form 4 but you can built applications on top of it analysing 10-Qs, 8-Ks (or any other of the 150 form types).

Boilerplate

Let’s fetch all filings of type 4 filed between 2019–07–01 and 2019–08–01.

Fetch filings from api.sec-api.io

Print the JSON to inspect the format. We expect 21,521 filings of type 4 to be published in this period.

Check the JSON output

Compressing Filings (for demo purposes only)

We reduce the number of filings considered per day to a maximum of 5 for demo purposes so that you can run this notebook on your local machine. You can run it without reducing the size, but it takes significantly longer because each SEC filing is downloaded in series.

Feel free to add a parallel downloader to accelerate the process.

Download Filing 4 Data

Let’s implement the download and XML parse methods. The XML parser extracts all non-derivative transactions listed in the 4 filing. It considers disposal and acquisition of items and calculates the sum of all transactions (sold and bought).

Important: the downloader doesn’t differentiate between filing issuer and reporter. In other words, we download the issuer’s and reporter’s filing. The reported transactions in both filings are the same and we double count transactions. That’s OK for demonstration purposes but has to be cleaned when building a production version.

Preparation for plotting

We transform `filings` into a pandas dataframe with the following columns: filedAt, type, CIK, ticker, companyName, linkToTxt, linkToHtml, nonDerivativeTransactions (previously added)

Bucketize

For each day we summarise all transactions and create a new dictionary bins.

Plotting

We plot a bar chart where each bar represents the total transactions per day.

Figure 2) Insider Trades per Day (in million USD)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade