Trade alongside the insiders with the API

blog photo
Joanne SnelFebruary 4, 2022

‘Insider trading’ has a pretty bad connotation. And for good reason, if insiders are using non-public information to inform their trading habits, that would pose as an unfair advantage on the stock market (also, this is very illegal). For companies publicly listed in the United States, certain employees are required to report any holdings, sales and purchases of their company’s securities to the Securities and Exchange Commission (SEC) in the effort to mitigate the information asymmetry that may arise otherwise. In other words, if reported according to the rules set forth by the SEC, insider trading is completely legal. Luckily, this information is publicly available. We can leverage this data to inform our trades under the expectation that insider trades are informative. We might assume that if insiders are buying their company’s stock, they might expect the stock price to increase in the future (which means we should also place a buy order). 

In this article, we’re going to explore the implications behind following insider trades and write an automated trading strategy that uses this information to place trades using the trading API. Find the full code in this GitHub repository.

Title Card for "Trade alongside the insiders with the API"

Why listen to the insiders? 👂

Academic literature remains divided on the information gain from following insider trades. Several papers suggest that insider trades can predict stock returns, some suggest that not all insider trades are informative and others show that following insider trades in the long term can lead to negative returns. Therefore, it’s important to do your own research and supplement the information obtained from insider trades with additional research.

In the United States, officers, directors and shareholders holding more than 10% of a company’s outstanding stock must file an SEC Form 4 whenever they trade their company’s securities. Following each buy/sell order or option exercise, these so-called ‘insiders’ must report to the SEC within two working days. The information on this form becomes public record — for example, see the following Form 4 filed by the CPO of Coinbase Global, Inc. on 6 January 2022. 

Filing Sheet

If you want to take a closer look, this filing can be found here

You’ll notice that Chatterjee reported the security he traded, the type of trade, the amount and at what price. There are a number of reasons why he might place such a trade. For example, he might have insights into the company’s projected performance (note that insider trading is only illegal when it is not publicly reported). Or, he might simply be selling for liquidity or diversification purposes. It’s difficult to discern for what reason an insider is trading purely by looking at this data, but it might be indicative of future stock returns. 

Automating insider knowledge 🤖 

In order to automate trades based on insider trades, we need to:

  • obtain insider trades, 
  • determine whether that company is tradable on the exchange you’re using,
  • set up certain trade rules,
  • place your trades with and 
  • schedule your code to run at regular intervals. 

If you’re interested in the steps, keep reading. Otherwise, you can find the GitHub repository, here

Obtaining insider trades 🔍 

Form 4 information is publicly listed on the SEC website, but there are third-party providers that report this information in an easily legible format. This means that everything you need is in one place, removing the need to parse through all submitted SEC forms. For this tutorial, we decided to go with FinViz, but OpenInsider is another good option.

A screenshot of the FinViz page, taken on 30 January 2022. 

A screenshot of the FinViz page, taken on 30 January 2022. 

We scraped the information using the requests library and BeautifulSoup. If you’d like to see a more in-depth explanation of this scraping process, you can follow the steps outlined in this article

Is it tradable? ✅

Before we can set up our trade rules, we need to do some general housekeeping on the data. For example, because SEC filings concern companies publicly listed in the US, tickers listed on FinViz are those corresponding to American exchanges. Therefore, in order to trade on, we need to obtain the corresponding German ticker. This can be done by using the OpenFIGI API, as shown in this article. If the German ticker cannot be found, we drop the instrument from the dataset. 

Setting up the trade rules 🤔 

After your dataset is usable, all that’s left is setting up the trading logic and order execution. Which decision rules you settle on is entirely up to you, but we’re using some of the general guidelines listed in this Investopedia article. For our example project we only consider buy or sell orders placed by company executives because those at the head of the company probably know more about the company’s future compared to directors. In addition, we also only consider trades when they constitute more than 1% of that individual’s total holdings. In our project, this is translated to code as follows:

1def get_trade_decisions(self):
2    buy = set()
3    sell = set()
4    # directors know less about a company's outlook than executives
5    trusted_relationships = ["CEO", "CFO", "COO", "CTO"]
6    for index, row in self._df.iterrows():
7        transaction_type = row["Transaction"]
8        relationship = row["Relationship"]
9    # if insider buys large amount, we also want to buy
10    if transaction_type == "Buy" and (relationship in trusted_relationships or "Officer" in relationship):
11        if row["Number of Shares"] / row["Total Shares"] > 0.01:  # trade >1% of total shares
12            buy.add(row["isin"])
13            print(f'Buy {row["gm_ticker"]}.')
14        # if insider sells large amount, we also want to sell
15    elif transaction_type == "Sale" and (relationship in trusted_relationships or "Officer" in relationship):
16        if row["Number of Shares"] / row["Total Shares"] > 0.01:  # trade >1% of total shares
17            sell.add(row["isin"])
18            print(f'Sell {row["gm_ticker"]}.')
19    return buy, sell

This method returns two sets: a selection of instruments to buy and a selection of instruments to sell.

Placing trades with 🍋 

The trading API makes it easy to execute orders once you’ve decided which instruments to trade.

However, before we can get started, we need to do some base work.

The easiest way to communicate with the API is to make use of the Python SDK, which can easily be installed through:

1pip install lemon

The initial step for using the SDK (and subsequently making requests to the API) is to instantiate a client, like this:

1def __init__(self):
2        self.client = api.create(
3            market_data_api_token=os.getenv("DATA_API_KEY"),
4            trading_api_token=os.getenv("TRADING_API_KEY"),
5            env="paper"
6    )

Note that in line 3 and 4 we are accessing environment variables, which you need to create and define before that step, typically in a .env file. Here, we are using separate API Keys for market data and trading, as required by the API. You can create your Trading and Market Data API Keys in the Dashboard.

Now, we are ready to place and activate orders:

1def place_trades(self, buy: List[str], sell: List[str]):
2        order_ids = []
3        expires_at = 0
4        quantity = 1
5        # place buy orders
6        for isin in buy:
7            side = "buy"
8            if isin == "NA":
9                continue
10            price = self.client.market_data.quotes.get_latest(isin=isin).results[0].a * quantity
11            if price < 50:
12                print(f"Order cannot be placed as total price, €{price}, is less than minimum order amount of €50.")
13                continue
14            order =
15                isin=isin, expires_at=expires_at, quantity=quantity, side=side
16            )
17            order_ids.append(
18            print(f"You are {side}ing {quantity} share(s) of instrument {isin}.")
19        positions =
20        positions_isins = []
21        for item in positions:
22            positions_isins.append(item.isin)
23        # place sell orders
24        for isin in sell:
25            if isin == "NA":
26                continue
27            if isin in positions_isins:
28                side = "sell"
29                price = self.client.market_data.quotes.get_latest(isin=isin).results[0].b * quantity
30                if price < 50:
31                    print(f"Order cannot be placed as total price, €{price}, is less than minimum order amount of €50.")
32                    continue
33                order =
34                    isin=isin, expires_at=expires_at, quantity=quantity, side=side
35                )
36                order_ids.append(
37                print(f"You are {side}ing {quantity} share(s) of instrument {isin}.")
38            else:
39                print(
40                    f"You do not have sufficient holdings of instrument {isin} to place a sell order."
41                )
42        return order_ids
43    def activate_orders(self, order_ids):
44        for order_id in order_ids:

Scheduling your code ⏰

In order to ensure that the code executes autonomously, we’ve used the Advanced Python Scheduler library to scrape the website once every weekday and place trades if the inside trades adhere to the decision rules we defined above. 

Further improvements 🛠

This project provides a solid starting point, but can be extended to reflect your customised priorities. As follows, a few suggestions:

  • only consider cluster buying, i.e. 3+ executives trading within a short amount of time,
  • only consider small- to mid-size companies because executives probably have a more holistic view of business operations (compared to those at the head of large companies), 
  • only trade based on recent information, i.e. drop datapoints more than 3 days old, 
  • ensure that you’re not using the same information twice, i.e. store past trades. 

Besides these improvements, perhaps you also want to host your strategy in the cloud such that it is always running. 

In broad lines, that’s about all you need to know to start setting up your insider trades following strategy. Clone the repository and get started adding your own adjustments! If you’re not yet a part of, you can sign-up here

If you have any questions, feel free to reach out to us at or join our vibrant Slack community. Thanks for reading and happy trading!

Joanne from 🍋.markets

The content of this article is not investment advice. It is for general, educational purposes only and does not take into account your individual needs.

You might also be interested in

blog photo

Using Time Series Forecasting to predict stock prices 🔮

In this article you will learn what time series forecasting is and how its application in finance looks like. Then you'll also dive into Facebook's Prophet Model for Time Series Forecasting and use it together with the Market Data API to forecast the development of the Tesla Stock.

blog photo

Dummies Guide to Trading with Machine Learning

Ever wonder how a trader with decades of experience on thousands of stocks and lightning fast reaction times might perform in the market? With some machine learning knowledge, you might be able to automate such a trader yourself! 💻 📈

blog photo

4 reasons why YOU should automate your trading strategy

In the current volatile market conditions, everyone is trying to find ways to minimise portfolio loss. In that context, have you ever thought about automating your trading strategy? In this article, we will dive into 4 reasons for doing so. Expect to learn how it can save you time, make your trading more efficient and lead to data-based decisions.

Dive Deeper

Find more resources to get started easily

Check out our documentation to find out more about our API structure, different endpoints and specific use cases.


Interested in building with us?

We are always looking for great additions to our team that help us build a brokerage infrastructure for the 21st century.

Need any help?
Get started with our DocumentationGet started with our DocumentationGet inspired on our BlogGet inspired on our Blog
© 2023Privacy PolicyImprint
Systems are down

As a tied agent under § 3 Sec. 2 WplG on the account and under the liability of DonauCapital Wertpapier GmbH, Passauer Str. 5, 94161 Ruderting (short: DonauCapital), GmbH offers you the receipt and transmission of orders for clients (§ 2 Sec. 2 Nr. 3 WpIG) of financial instruments according to § 2 Sec. 5 WpIG as well as brokerage of accounts.