I’ve always wondered if a slow and high-level trading strategy focusing on long-term trends could outperform a buy-and-hold strategy.
To answer this question, I created a Python script that would utilize a momentum-based strategy to tell me when to buy and when to sell Bitcoin.
Despite my busy life and doubts that day trading would be a successful venture, I was eager to find out if this simple program could beat the market. I can run the Python code daily to decide whether to buy or sell BTC.
What would have happened if I had used the following strategy between the turbulent years 2020 and 2022 in Bitcoin? Read on to find out! π
General Idea
The idea of this algorithm is to allow traders to automate their Bitcoin trading decisions using two moving averages.
π Finxter Academy: Complete Python Trading Course (Binance) — Simple Moving Average
The algorithm will enter buy positions when the shorter-term moving average (MA1
) is higher than the longer-term moving average (MA2
) indicating a positive momentum of the Bitcoin price, and enter sell positions when the shorter-term moving average is lower than the longer-term moving average indicating a negative momentum of the Bitcoin price.
When the moving averages cross, the algorithm will close any existing positions and reverse the trading direction.
Algorithm Steps
My strategy follows these simple steps:
- Initialize two moving averages,
MA1
andMA2
, with different lookback periods. - Calculate the current value of each moving average.
- If
MA1 > MA2
, enter a buy position in the Bitcoin market. - If
MA1 < MA2
, enter a sell position in the Bitcoin market. - Monitor the market for any changes in the moving averages.
- When the moving averages cross, close any existing positions and reverse the trading direction (buy if previously selling, sell if previously buying).
- Repeat steps 2 to 6.
Python Program to Automate It
The following program implements these steps in practice by pulling the Bitcoin price data from an online API, calculating the moving averages (short- and long-term), and trading based on whether the short-term MA is below or above the long-term MA.
I’ll explain the code in a minute!
import pandas as pd import numpy as np import matplotlib.pyplot as plt import requests # Get Bitcoin Price Data URL = 'https://www.alphavantage.co/query?function=DIGITAL_CURRENCY_DAILY&symbol=BTC&market=USD&apikey=APIKEY' response = requests.get(URL) data = response.json() daily_data = data["Time Series (Digital Currency Daily)"] # Convert JSON to DataFrame df = pd.DataFrame(daily_data) df = df.T # Create two Moving Averages MA1 = 20 MA2 = 50 df['MA1'] = df['1a. open (USD)'].rolling(MA1).mean() df['MA2'] = df['1a. open (USD)'].rolling(MA2).mean() # Initialize variables position = 0 my_usd = 10000 my_btc = 0 print('Initial balance:', str(my_usd), 'USD') # Backtest Algorithm for i in range(len(df)): # Get price price = float(df['1a. open (USD)'].iloc[i]) # Buy position if df['MA1'].iloc[i] > df['MA2'].iloc[i] and position == 0: position = 1 my_btc = price / my_usd my_usd = 0 print('Buying at', price, 'on', df.index[i]) # Sell position elif df['MA1'].iloc[i] < df['MA2'].iloc[i] and position == 1: position = 0 my_usd = price * my_btc my_btc = 0 print('Selling at', price, 'on', df.index[i]) print('Final balance:', str(my_usd + my_btc * price)) initial_btc = float(df['1a. open (USD)'].iloc[0]) / 10000 value_today = initial_btc * float(df['1a. open (USD)'].iloc[-1]) print('Final balance (buy and hold):', str(value_today))
Code Explanation
This code implements the algorithm described above.
The first portion of the code is getting the daily Bitcoin price data from the API and converting it into a DataFrame.
Next, the code creates two moving averages, MA1
and MA2
, based on the open price of Bitcoin. Then, the code initializes the position variable to 0.
The backtest algorithm then runs a loop to iterate through the DataFrame to identify when conditions are met to buy or sell. If the shorter-term MA1
is higher than the longer-term MA2
, the code will enter a buy position.
Similarly, if the shorter-term MA1
is lower than the longer-term MA2
, the code will enter a sell position. We don’t assume short selling so “selling” on an empty position just means waiting for the next buy opportunity.
Finally, if the MA1
and MA2
cross, the code will close any existing position and reverse the trading direction.
Backtesting the Strategy
Let’s have a look at an example run — note to read this from bottom to top! π
Initial balance: 10000 USD Buying at 20905.58 on 2022-11-07 Selling at 18809.13 on 2022-09-26 Buying at 21826.87 on 2022-09-12 Selling at 19331.28 on 2022-07-13 Buying at 28424.71 on 2022-06-12 Selling at 41941.7 on 2022-03-10 Buying at 42380.87 on 2022-02-07 Selling at 36660.35 on 2022-01-25 Buying at 41566.48 on 2022-01-08 Selling at 57471.35 on 2021-10-12 Buying at 47674.01 on 2021-08-25 Selling at 44572.54 on 2021-08-08 Buying at 40516.28 on 2021-06-15 Selling at 57351.56 on 2021-03-22 Buying at 57641.0 on 2021-03-19 Selling at 56900.74 on 2021-03-17 Buying at 11318.42 on 2020-08-26 Selling at 9538.1 on 2020-07-25 Buying at 9772.44 on 2020-06-10 Selling at 9315.96 on 2020-05-16 Final balance: 14806.674822101442 Final balance (buy and hold): 15095.029852800002
So, you see, in the period between May 2020 and November 2022, trading wouldn’t have been more profitable than simply buying and holding Bitcoin — even when ignoring trading fees and higher tax burden.
And ignoring the fact that Bitcoin has had huge up and down volatility, which should be great for trading. That is — in theory.
Conclusion
Buy and HODL!