[Tut] Bitcoin – Trading Moving Averages or HODL? A Python Script Uncovers the Answer! - Printable Version +- Sick Gaming (https://www.sickgaming.net) +-- Forum: Programming (https://www.sickgaming.net/forum-76.html) +--- Forum: Python (https://www.sickgaming.net/forum-83.html) +--- Thread: [Tut] Bitcoin – Trading Moving Averages or HODL? A Python Script Uncovers the Answer! (/thread-100604.html) |
[Tut] Bitcoin – Trading Moving Averages or HODL? A Python Script Uncovers the Answer! - xSicKxBot - 01-18-2023 Bitcoin – Trading Moving Averages or HODL? A Python Script Uncovers the Answer! <div> <div class="kk-star-ratings kksr-auto kksr-align-left kksr-valign-top" data-payload='{"align":"left","id":"1065786","slug":"default","valign":"top","ignore":"","reference":"auto","class":"","count":"1","legendonly":"","readonly":"","score":"5","starsonly":"","best":"5","gap":"5","greet":"Rate this post","legend":"5\/5 - (1 vote)","size":"24","width":"142.5","_legend":"{score}\/{best} - ({count} {votes})","font_factor":"1.25"}'> <div class="kksr-stars"> <div class="kksr-stars-inactive"> <div class="kksr-star" data-star="1" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" data-star="2" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" data-star="3" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" data-star="4" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" data-star="5" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> </p></div> <div class="kksr-stars-active" style="width: 142.5px;"> <div class="kksr-star" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> <div class="kksr-star" style="padding-right: 5px"> <div class="kksr-icon" style="width: 24px; height: 24px;"></div> </p></div> </p></div> </div> <div class="kksr-legend" style="font-size: 19.2px;"> 5/5 – (1 vote) </div> </p></div> <p>I’ve always wondered if a slow and high-level trading strategy focusing on long-term trends could outperform a buy-and-hold strategy.</p> <p>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. </p> <p>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. </p> <p class="has-base-background-color has-background"><strong>What would have happened if I had used the following strategy between the turbulent years 2020 and 2022 in Bitcoin?</strong> Read on to find out! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f447.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <h2>General Idea</h2> <div class="wp-block-image"> <figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="495" height="881" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-165.png" alt="" class="wp-image-1066579" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-165.png 495w, https://blog.finxter.com/wp-content/uploads/2023/01/image-165-169x300.png 169w" sizes="(max-width: 495px) 100vw, 495px" /></figure> </div> <p>The idea of this algorithm is to allow traders to automate their Bitcoin trading decisions using two moving averages. </p> <p class="has-base-background-color has-background"><img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f449.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /> <strong>Finxter Academy</strong>: <a href="https://academy.finxter.com/course/setting-up-binance-and-development-environment-3/" data-type="URL" data-id="https://academy.finxter.com/course/setting-up-binance-and-development-environment-3/" target="_blank" rel="noreferrer noopener">Complete Python Trading Course (Binance) — Simple Moving Average</a></p> <p>The algorithm will enter buy positions when the shorter-term moving average (<code>MA1</code>) is higher than the longer-term moving average (<code>MA2</code>) 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. </p> <p>When the moving averages cross, the algorithm will close any existing positions and reverse the trading direction.</p> <h2>Algorithm Steps</h2> <figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="683" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-166-1024x683.png" alt="" class="wp-image-1066580" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-166-1024x683.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/01/image-166-300x200.png 300w, https://blog.finxter.com/wp-content/uploads/2023/01/image-166-768x512.png 768w, https://blog.finxter.com/wp-content/uploads/2023/01/image-166.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure> <p>My strategy follows these simple steps:</p> <ol> <li>Initialize two moving averages, <code>MA1</code> and <code>MA2</code>, with different lookback periods.</li> <li>Calculate the current value of each moving average.</li> <li>If <code>MA1 > MA2</code>, enter a buy position in the Bitcoin market.</li> <li>If <code>MA1 < MA2</code>, enter a sell position in the Bitcoin market.</li> <li>Monitor the market for any changes in the moving averages.</li> <li>When the moving averages cross, close any existing positions and reverse the trading direction (buy if previously selling, sell if previously buying).</li> <li>Repeat steps 2 to 6.</li> </ol> <h2>Python Program to Automate It</h2> <div class="wp-block-image"> <figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="684" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-167-1024x684.png" alt="" class="wp-image-1066593" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-167-1024x684.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/01/image-167-300x200.png 300w, https://blog.finxter.com/wp-content/uploads/2023/01/image-167-768x513.png 768w, https://blog.finxter.com/wp-content/uploads/2023/01/image-167.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure> </div> <p>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. </p> <p>I’ll explain the code in a minute!</p> <pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">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)) </pre> <h2>Code Explanation</h2> <div class="wp-block-image"> <figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="684" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-168-1024x684.png" alt="" class="wp-image-1066595" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-168-1024x684.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/01/image-168-300x200.png 300w, https://blog.finxter.com/wp-content/uploads/2023/01/image-168-768x513.png 768w, https://blog.finxter.com/wp-content/uploads/2023/01/image-168.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure> </div> <p>This code implements the algorithm described above. </p> <p>The first portion of the code is getting the daily Bitcoin price data from the API and converting it into a <a href="https://blog.finxter.com/how-to-create-a-dataframe-in-pandas/" data-type="post" data-id="16764" target="_blank" rel="noreferrer noopener">DataFrame</a>. </p> <p>Next, the code creates two moving averages, <code>MA1</code> and <code>MA2</code>, based on the open price of Bitcoin. Then, the code initializes the position variable to 0.</p> <p>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 <code>MA1</code> is higher than the longer-term <code>MA2</code>, the code will enter a buy position. </p> <p>Similarly, if the shorter-term <code>MA1</code> is lower than the longer-term <code>MA2</code>, 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.</p> <p>Finally, if the <code>MA1</code> and <code>MA2</code> cross, the code will close any existing position and reverse the trading direction.</p> <h2>Backtesting the Strategy</h2> <div class="wp-block-image"> <figure class="aligncenter size-full"><img decoding="async" loading="lazy" width="587" height="881" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-169.png" alt="" class="wp-image-1066596" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-169.png 587w, https://blog.finxter.com/wp-content/uploads/2023/01/image-169-200x300.png 200w" sizes="(max-width: 587px) 100vw, 587px" /></figure> </div> <p>Let’s have a look at an example run — note to read this from bottom to top! <img src="https://s.w.org/images/core/emoji/14.0.0/72x72/1f447.png" alt="?" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p> <pre class="EnlighterJSRAW" data-enlighter-language="raw" data-enlighter-theme="" data-enlighter-highlight="1,22,23" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">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</pre> <p>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. </p> <p>And ignoring the fact that Bitcoin has had huge up and down volatility, which should be great for trading. That is — in theory.</p> <h2>Conclusion</h2> <div class="wp-block-image"> <figure class="aligncenter size-large"><img decoding="async" loading="lazy" width="1024" height="711" src="https://blog.finxter.com/wp-content/uploads/2023/01/image-170-1024x711.png" alt="" class="wp-image-1066604" srcset="https://blog.finxter.com/wp-content/uploads/2023/01/image-170-1024x711.png 1024w, https://blog.finxter.com/wp-content/uploads/2023/01/image-170-300x208.png 300w, https://blog.finxter.com/wp-content/uploads/2023/01/image-170-768x533.png 768w, https://blog.finxter.com/wp-content/uploads/2023/01/image-170.png 1113w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure> </div> <div style="height:45px" aria-hidden="true" class="wp-block-spacer"></div> <p>Buy and HODL!</p> </div> https://www.sickgaming.net/blog/2023/01/17/bitcoin-trading-moving-averages-or-hodl-a-python-script-uncovers-the-answer/ |