Building a Mean Reversion Strategy with the lemon.markets API & hosting it in the cloud

Marius Sprenger
lemon.markets
Published in
8 min readSep 8, 2021

Hi there. My name is Marius and I am our community developer at lemon.markets šŸ‹. We are building an API that allows you to build your own brokerage experience at the stock market. This may include, among other possibilities, your very own automated trading strategy. To inspire you a little bit for your first project with us: Might I suggest a starting point?

In this post, I want to dive into how you can use the lemon.markets API to build one of the most well-known trading strategies: the mean reversion strategy. And, to set you up for success, I will also walk you through the steps to host your strategy up in the cloud using Heroku, to make sure your program continues to run, even when your laptop is closed.

The premise of the mean-reversion strategy (I am going to call it MR strategy from now on because who likes words that fill up entire lines?) is easily explained: behind it stands the assumption that a stock will eventually converge towards a mean (or ā€œaverageā€) value. So imagine you have a stock from the up-and-coming online supermarket ā€œSuperCompanyā€ that has a mean share price of ā‚¬97.00 (e.g. over the past two weeks) and is currently traded at ā‚¬92.50. The MR strategy assumes that the price will soon converge towards the average share price, meaning that now would be a good time to buy (#buythedip, anyone?). On the other hand, if the current share price was ā‚¬103.50 right now, it would be (if we follow the MR logic) a good idea to sell the stock, as it is currently higher than the average share price over the past few weeks and we therefore expect it to decrease soon.

Sounds simple, right? It is.

And more importantly, the logic behind it is easy to implement if we have the right infrastructure in place. And, Iā€™m sure you guessed it: thatā€™s where lemon.markets comes into play. Using the lemon.markets API, you can build a MR strategy on your own with very little effort. Word has it that Jim Simonsā€™ early successes can be attributed to a MR-based strategy. For anyone interested in diving deeper inside the mean reversion strategy, we can recommend this article.

But for now, letā€™s dive right in.

Implementing the Mean Reversion Strategy

You can find the whole implementation, ready to host in the cloud, in our GitHub repository. However, for this article, let us take a look at some of the main characteristics of the mean reversion code.

One crucial ingredient to the project is the lemon.markets Python SDK. The SDK makes communicating with the API a lot easier and saves us a ton of time, as we do not need to specify endpoint function calls on our own and can simply use the ones defined in the SDK. You can easily install it via:

pip install lemon

Afterwards, you have access to all functions and can place orders or retrieve market data. We will see in a second how that comes in handy for our mean reversion project.

Environment Variables

As we do not want to expose sensitive data (e.g. our API Keys) in our main script, we use a number of environment variables. If you want to run your script locally, we suggest that you create a .env file containing the following variables, which can then be accessed via

os.environ.get(ā€œENV-VARIABLE")
Environment Variables for Mean Reversion Python script

After we took care of the project set up, we can start writing the general mean reversion logic in our main script.

At first, we use the SDK to create an API client, like so:

As you can see, we use our previously established environment variables to instantiate the client. Now we can use the client to make all subsequent API requests and define the mean reversion logic.

Defining our main script

Moving Average

In order to be able to make a decision based on a mean stock price, we obviously need to make sure that we actually have a calculated mean price that we can use. In our script, we actually implemented two different ways to calculate the mean value:

  1. the simple moving average (which is the ā€œstandardā€ mean value, where you divide the sum of results by n)
  2. the exponential moving average (where newer prices are weighted higher)

Later in the script, you can choose which one you want to use for your mean reversion decision. To calculate the mean data we use the lemon.markets Market Data API, specifically the OHLC endpoint, which allows us to retrieve historical Open-High-Low-Close Data for specific instruments:

Mean Reversion Logic

After weā€™ve calculated the moving average value(s), we can use it to define our mean reversion logic:

Mean Reversion Decision

Using the /ohlc endpoint, we can select a specific instrument via its ISIN to calculate both the moving average and the latest close price. Following the idea behind the mean reversion strategy, in line 18 we define a simple IF/THEN-clause to decide whether we want to buy (ā€œTrueā€) or sell (ā€œFalseā€). We can subsequently use that logic to perform the mean reversion logic ā€œin actionā€.

We therefore define our main function mean_reversion(). Here, we pass a specific instrument (Volkswagen in this case, but you can obviously change that to the one you are interested in), check if our Trading Venue is currently open and execute our mean reversion logic. We also use our previously defined mean_reversion_decision function to come to a decision for the specific instrument. Based on that, we either buy (if we have enough cash to do so), or sell (if we own enough shares to do so).

Scheduling

The big perk of an automated strategy is that it is (well) automated, meaning you define the logic once and then do not need be manually involved in placing trades anymore. However, to make sure that our mean reversion logic is executed regularly, we need to use scheduling to perform the script each x hours. In our case, we use the Advance Python scheduler (apscheduler) to execute our script hourly on each day of the week the stock exchange is open. The package makes it super easy to do that, using a few lines of code at the end of our script:

And that was basically it. You can find the whole repo on GitHub ā€” feel free to test it out. Obviously, weā€™d be super grateful if you decide to contribute by opening a PR or sending us a message to support@lemon.markets. Looking forward to your comments/improvements šŸ™‚.

Hosting in the Cloud

Obviously, an important part of a trading algorithm is to make sure that is constantly running. There are a number of possibilities to host your Python (or any other) script in the cloud. We decided to go with Heroku, as it is extremely convenient and fast to set up.

To host a Python script in the cloud, go to your dashboard and create a new application. After this step is done, go to the applicationā€™s ā€œDeployā€ tab and connect to your GitHub repository, where the script is hosted. Choose automatic deploys if you want to trigger a new deploy every time you make changes to the repository, or manual deploy if you wish to have a bit more ā€œmanual controlā€ over your Heroku deploys.

For those of you who read this blog post carefully, you will have noticed that we still need to configure our environment variables. You can do so by either entering them in the dashboard under Settings/Config Vars or by logging into the Heroku CLI and setting them using:

heroku config:set ENV_VAR=value

Afterwards, you can deploy your application. It might take a few minutes until your app is up and running. You can check the status by typing:

heroku logs

in your terminal/console). If the app is not running, try typing:

heroku ps:scale worker=1

Take a look at this, this or this article if you should get stuck at some point during the Heroku setup.

If everything is up and running, you can relax, sit back, order some pizza and let the algorithm do the work for you šŸ˜Ž. Because at the end, this is what lemon.markets is there for: automating your trades so you have more time for other things.

Additional Considerations

There are a few additional decisions you need to make when building your own MR strategy. For example, how to determine the mean? Will you look at a time frame of two weeks, like we did? Or, will you look at hourly data? In addition, you do not need to restrict MR to prices, you can also look, for example, at a stockā€™s price-to-earnings (P/E) ratio. In our code snippet, we make trades if they are absolutely bigger or smaller than the mean, but perhaps you have reason to build your strategy such that orders are only placed if the current price is >0.05% larger than the mean.

As you can see, there is more than one way to make this base strategy more complex (and hopefully sophisticated).

Mean Reversion or Momentum?

You might have noticed that the MR strategy is built upon a critical assumption, namely that any extreme price movement will be followed by a return to long-run averages. But, is this a reasonable assumption to make? After all, a dramatic drop in instrument price might be persistent, for example, if it turns out that a stock loses its relevance in the market.

The MR strategy is based on regression to the mean, a statistical concept that describes the phenomenon that an unlikely event is usually followed by an expected event, rather than a more unlikely one. Whatā€™s the catch? This concept works only for systems with a normal distribution, which the stock market isnā€™t. Instead, stock returns more closely resemble a distribution with fat tails. In other words, in the stock market, extreme events happen more frequently than expected.

Why is MR so widely used, then? Many traders believe that the stock market oscillates between periods of mean reversion and momentum. In simple English, when an instrument price is increasing, it continues to increase (and the same can be said for downwards movements). (By the way: periods of momentum are why we see fat tails!) Mean reversion might not reflect the market always, but it does sometimes. So, how can you know whether weā€™re in a period of mean reversion or momentum? Thatā€™s the big question šŸ˜‰ There are a few measures that can be applied to historical price data, such as the Hurst exponent. You can use this scalar to characterise a time series as mean-reverting, random-walk or trending. Based on that, you might want to decide whether to employ a mean reversion or trend following strategy. If you are interested in this sort of stuff, you can continue reading here.

I hope you got an idea of what you can do with the lemon.markets API. Let us know what you think, tell us about a bug you found or share a strategy that you built. Simply hit us up at support@lemon.markets or join our Slack community. Weā€™d love to hear from you šŸ‹ šŸ’› .

Marius

--

--

Marius Sprenger
lemon.markets

Half building lemon.markets, half PhD student focusing on the intersection between sports and technology. Interested in movies, sports and (surprise) technology