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.
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.
A typical quantitative trading system has several modules: Market Data Handler, Strategy Module, Backtesting Module, Order Module, Storage, etc.
- 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.
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
Gemini’s Market data is a public API that streams all the market data on a given symbol.
We have created the
GeminiOrderBook class to store the
ask price of Bitcoin in the Gemini exchange. In
GeminiOrderBook , we use
GeminiOrderBook class, we use two dictionary variables
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.
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.
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.
Here is an example of a death cross and a golden cross on the S&P 500 in March and May of 2020.
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.
calSMA function, we use
pandas.Series.rolling to calculate the rolling window. The parameter
window is the size of the moving window.
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.
We define the strategy class as an abstract class that can be inherited to accomplish a specific trade strategy by implementing 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.
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.
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
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
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
Initial Cash: $ 100000.000000
Market Value: $ 312877.573814
Revenue: $ 212877.573814
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.
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.
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.
Thu Dec 17 Update
Bitcoin breaks above $20,000 for the first time ever.
Take care, and stay all safe and healthy.