Write Simple BTC Quantitative Trading System Using Python in One Hour

Let the program help you make money

Photo by André François McKenzie on Unsplash

Disclaimer: This article is for education purposes only. I am only sharing my opinions with no guarantee of gains or losses. Your investments are solely your own responsibility. It is very important for you to conduct your own research or consult a financial adviser before you make any investment decisions.

As of this writing, Bitcoin price has crossed $19,000 and is expected to hit $20,000 in its 12-year history high by the end of 2020.

BTC-USD From Coindesk

In recent years, some people have used quantitative trading strategies to exchange cryptocurrency, and they’ve been getting satisfactory profits.
As a programmer, I will work with you to build a simple quantitative Bitcoin trading system.

What is Quantitative Trading

Quantitative trading consists of trading strategies based on quantitative analysis, which rely on mathematical computations and number crunching to identify trading opportunities.

— Investopedia

A typical quantitative trading system has several modules: Market Data Handler, Strategy Module, Backtesting Module, Order Module, Storage, etc.

A Typical Quantitative Trading System
  • Market Data Handler: Get market data and account from the Exchange.
  • Strategy Module: Based on market data and the algorithm send buy and sell command to order module.
  • Backtesting Module: Test and optimize a strategy using historical data.
  • Order Module: Receive buy and sell orders from the strategy module, package, and forward them to the exchange.
  • Storage/Log: Save data in the database and records operation information in the logging system.

As a beginner in quantitative trading, we will focus on Market Data Handler, Strategy, and Backtesting modules in this article.

Due to Python’s excellent data analysis capabilities, large third-party libraries, widely using in data science and machine learning, we chose Python language to develop our quantitative trading system.

Market Data Handler

Our system will use the APIs by the digital currency exchange to automate queries, place orders, withdraws orders, and other networking operations. Usually, an exchange offers two types of APIs: REST(REpresentational state transfer) and WebSocket.

WebSocket vs. REST

If you’re familiar with network programming, you know about these two protocols. There are many articles about the performance comparison between REST and WebSocket on the internet. For our system, the price of BTC is constantly changing, we need to request new prices in a short time from the exchange. I choose the WebSocket protocol for the below advantages:

  • receive notifications from the exchange in real-time
  • reduce the amount of data you have to transfer over the network
  • reduce latency introduced by polling interval.

Example

We will demonstrate our example using the API by the Gemini exchange. Gemini offers both public and private APIs. If you want to manage both orders and funds, you need to use private APIs. You should create an account and request a key. Remember: save your KEY and SECRET for future use.

Notice: Our example is running on Gemini’s sandbox site that is an instance of the Gemini Exchange that offers full exchange functionality using test funds.

GEMINI WebSocket REQUEST API

wss://api.gemini.com/v1/marketdata/:symbol

Gemini’s Market data is a public API that streams all the market data on a given symbol.

Code:

We have created the GeminiOrderBook class to store the bid and ask price of Bitcoin in the Gemini exchange. In GeminiOrderBook , we use

In the GeminiOrderBook class, we use two dictionary variables bids and asks to store the current trade data, the dictionary key is the price and value stores the remaining data. For the bid price, we rank the highest price first, and for the ask price we rank the lowest price first, this sorting is good for matching prices between buyers and sellers. In addition, in this example, we keep only the top 5 data.

The MarketDataCrawler class, we use WebSocket to receive data from the exchange. In on_message= , we use a lambda function — the anonymous function to simplify our code.

For more information, please refer to the official documentation of the Gemini Exchange.

This example saves the results into the BTC_OrderBook.txt . In practice, we often store the data into a database for later use in our projects.

Strategy and Backtesting Modules

The strategy module is the brain of a quantitative trading system. Before applying a trading strategy, we must test our strategy. This is the backtesting, which is the general method for seeing how well a strategy or model would have done ex-post. Backtesting accesses the viability of a trading strategy by discovering how it would play out using historical data.

Although there are many experienced python backtesting systems available, such as Backtrader, Zipline, PyAlgoTrade, we will build a simple backtesting framework from scratch to test our first trading strategy - the SMA Crossover Strategy.

OHLCV

An OHLC chart shows the open, high, low, and close price for a given period, which, together with the volume, makes up the OHLCV data. It is widely used for technical analysis of stocks, futures, digital currencies, and other market conditions.

We use BTC’s historical OHLCV data as our test data. You can download the one-year historical data of BTC-USD from yahoo finance.

Golden Cross & Death Cross Strategy

This strategy uses the concept of SMA (Simple Moving Average) that calculates the average of a selected range of prices, usually closing prices, by the number of periods in that range.

The golden cross is a candlestick pattern that is a bullish signal in which a relatively short-term moving average crosses above a long-term moving average.

The death cross is a technical chart pattern indicating the potential for a major selloff. The death cross appears on a chart when a stock’s short-term moving average crosses below its long-term moving average.

— Investopedia

Here is an example of a death cross and a golden cross on the S&P 500 in March and May of 2020.

Chart from Yahoo! Finance, Edit by author

We can simply think of a death cross as a sell signal and a golden cross as a buy signal.

We use Pandas to easily compute SMA, death cross, and golden cross.

In calSMA function, we use pandas.Series.rolling to calculate the rolling window. The parameter window is the size of the moving window.

In crossover function, we check if the two series cross at some moment. There is a crossing when, for a given moment, series1 is less than series2 and the previous moment series1 is greater than series2, or vice versa.

Strategy module

We define the strategy class as an abstract class that can be inherited to accomplish a specific trade strategy by implementing the init and next methods.

The SMACrossover class inherits from BTCStrategy, and we have chosen the MA20 and MA50 as short-term and long-term indicators to find the golden cross and death cross. In this example, we use to buy full and sell full.

Backtesting & Demo Trading

In this module, we use the closing prices in OHLC as test data and simulate trades to test the profitability of the strategy.

The Exchange Demo class is responsible for simulation trading. For simplicity, we use close price in OHLC as the reference price for buying and selling. We assume that the market has sufficient liquidity so that our trade orders can be filled immediately.

The Backtest uses Pandas and Numpy libraries to perform vector operations on OHLCV data to backtest trading strategies.

Backtest input:OHLCV data, Initial Cash, Commission, ExchangeDemo class, Strategy class

Backtest output: Revenue

There are three functions in Backtest:

  • init: Pass in parameters, cleaning, sorting, and validation of OHLCV data.
  • run: Iterate over all the historical data, calculate the profit, and return the result.
  • compute: Calculate the profit.

We put the functions for error message handling, reading CSV files, calculating SMA and crossover into the BTC_utils.py.

Finally, running our backtesting system in the main function, we backtest the SMA strategy using the most recent year of BTC-USD OHLCV data, BTC-USD.csv. Considering the price spike of the BTC price, the initial cash is $100,000 and the commission rate is 0.003.

Initial Cash: $ 100000.000000
Market Value: $ 312877.573814
Revenue: $ 212877.573814
Revenue of MA20 and MA50

TA-DA! You can see that our returns from this strategy are still quite impressive. Our BTC assets boost by more than 300%.

If you use MA30 and MA60, your returns will also different. You can try it out for yourself.

Revenue of MA30 and MA60

It is true that the real market is more complex and variable than this, the probability that we will achieve such performance is very low. So, this program can only be used as an example and not for actual transactions.

Conclusion

In practice, we have to backtest various more complex strategies, and sometimes the strategies have to be able to respond to special events. In terms of the system, we also need to add database systems, stream-processing platforms, messaging systems, and monitoring systems. For hardware, we use more and higher performance distributed servers and rent a high-speed network. We will discuss these in later articles.

I hope this article can as a “Hello World! ” program lead you into quantitative trading programming.

Lastest News

Thu Dec 17 Update

BTC-USD From Coindesk

Bitcoin breaks above $20,000 for the first time ever.

Take care, and stay all safe and healthy.

Software Engineer, Kaggle Competitions Expert

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store