Mastering Python for Trading: Crafting a Basic Strategy

Exploring the foundations of building a basic trading strategy using Python

In this blog, we will cover the below topics

  • What are technical indicators?
  • What are Bollinger Bands?
  • How to access the data from yahoo finance?
  • How to build Bollinger Bands and visualize them in Python?
  • Building a basic buy/sell trading strategy

What are technical indicators?

The technical indicators are mathematical calculations that are carried out on historical data such as open, price, volume, etc that indicate the potential sell or buy proposition. It is widely used in technical analysis and by active traders to analyze price movements and make a profit by timing the entry and exit points. There are various technical indicators and most popular being moving averages, RSI, MACD, and Bollinger Bands. Our focus in this blog will be on the Bollinger Bands.

What are Bollinger Bands?

The Bollinger Bands is a technical indicator to identify the over-sold and over-bought signals and was developed by John Bollinger. There are three trends line that composes the Bollinger Band.

  • Upper Band: This is typically 2 standard deviations away from the middle band on the positive side. If the price reaches this band, it signals over-bought.
  • Middle Band: The simple moving average (20 days)
  • Lower Band: This is typically 2 standard deviations away from the middle band on the negative side. If the price touches this band, it signals over-sold.

If the upper and lower bands are wide then the volatility of the stock is high and on the contrary, if both bands are closer, it indicates low volatility. According to John Bollinger, a period of sustained low volatility (aka BB Squeeze) is often followed by high volatility and price can move either way.

Source: Author

How to access the data from yahoo finance?

We will use yahoo finance to load the stock data and use standard Python libraries like pandas and numpy.

import pandas as pd
import numpy as np
import yfinance as yf
import yahoo_fin.stock_info as si
import matplotlib.pyplot as plt

Accessing data from Yahoo Finance

We will set the stock name and period for data extraction and define a function to achieve this. Also, plot the close price to visualize the trend.

tickers = ['AAPL']
start_date = '2020-01-01'
end_date = '2022-04-30'
def load_data(tickers):
try:
data = pd.DataFrame(columns = tickers)
for ticker in tickers:
data[ticker] = yf.download(ticker, start_date, end_date)['Close']

return data
except Exception as e:
print(f'An exception occurred while executing load_data: {e}')
df = load_data(tickers)

OUTPUT:
Close
Date
2019-12-31 73.412498
2020-01-02 75.087502
2020-01-03 74.357498
2020-01-06 74.949997
2020-01-07 74.597504
... ...
2022-04-25 162.880005
2022-04-26 156.800003
2022-04-27 156.570007
2022-04-28 163.639999
2022-04-29 157.649994
fig, ax = plt.subplots(figsize=(16,8))
plt.title(f'Bollinger Band - {tickers[0]}')
plt.ylabel('Price in USD')
plt.xlabel('Dates')
ax.plot(bb['Close'], label = 'Close Price', alpha = 0.25, color = 'black')
Source: Author

Building and visualizing the Bollinger Band

As seen in the earlier section, let’s create the 3 trend lines that are part of Bollinger Band i.e. Upper band, middle band, and lower band.

sma = df.rolling(window=30).mean().dropna()
rstd = df.rolling(window=30).std().dropna()

upper_band = sma + 2 * rstd
lower_band = sma - 2 * rstd


upper_band = upper_band.rename(columns={'Close': 'upper'})
lower_band = lower_band.rename(columns={'Close': 'lower'})
df_bollinger_band = df.join(upper_band).join(lower_band)
df_bollinger_band = df_bollinger_band.dropna()


OUTPUT:
Close upper lower
Date
2020-02-12 81.800003 82.904511 73.869656
2020-02-13 81.217499 82.868477 74.426023
2020-02-14 81.237503 82.953769 74.750731
2020-02-18 79.750000 82.775439 75.288561
2020-02-19 80.904999 82.699774 75.761226
... ... ... ...
2022-04-25 162.880005 182.023020 154.763647
2022-04-26 156.800003 181.270568 155.928100
2022-04-27 156.570007 181.112080 156.185255
2022-04-28 163.639999 180.924628 156.642707
2022-04-29 157.649994 181.145311 156.224024

We have already plotted the Close price chart, let’s add upper and lower trend lines to the plot. The Red indicates the upper band and the Blue represents the lower band.

ax.plot(df_bollinger_band['upper'], label = 'Upper Band', alpha = 0.25, 
color = 'red')
ax.plot(df_bollinger_band['lower'], label = 'Lower Band', alpha = 0.25,
color = 'blue')
Source: Author

Building a basic buy/sell trading strategy

We will keep our strategy very simple. If the close price of the stock crosses the upper band then we sell the stock and if crosses the lower band, we buy the stock.

Close price > Upper Band → Sell

Close price < Upper Band → Buy

We will have markers that act as indicators, the one in RED is for Sell and the GREEN is for Buy. Let’s update the previous plot with markers.

ax.scatter(buyers.index, buyers['Close'], label = 'Buy', alpha = 1, 
marker = '^', color = 'green')
ax.scatter(sellers.index, sellers['Close'], label = 'Sell', alpha = 1,
marker = 'v', color = 'red')
Source: Author

It will be good to have a shaded area indicating the Bollinger bandwidth along with legends making it easier to read and interpret. Let’s bring all the pieces together.


fig, ax = plt.subplots(figsize=(16,8))
plt.title(f'Bollinger Band - {tickers[0]}')
plt.ylabel('Price in USD')
plt.xlabel('Dates')
ax.plot(df_bollinger_band['Close'], label = 'Close Price', alpha = 0.25,
color = 'black')
ax.plot(df_bollinger_band['upper'], label = 'Upper Band', alpha = 0.25,
color = 'red')
ax.plot(df_bollinger_band['lower'], label = 'Lower Band', alpha = 0.25,
color = 'blue')
ax.fill_between(df_bollinger_band.index, df_bollinger_band['upper'],
df_bollinger_band['lower'], color = '#F9E79F')

ax.scatter(buyers.index, buyers['Close'], label = 'Buy', alpha = 1,
marker = '^', color = 'green')
ax.scatter(sellers.index, sellers['Close'], label = 'Sell', alpha = 1,
marker = 'v', color = 'red')
plt.legend()
plt.show()
Source: Author

Here are the key observations:

  • The Red marker indicates the sell and each of the sell indicators is near the upper band. Also notice that immediately after the series of sell indicators, the stock price drops. So our sell strategy seems to be in place and indicators are telling us to book profit and sell.
  • Similarly, the Green marker indicates the buy and each of the buy indicators is near the lower band. The buy indication is always just before the stock price shoots up and in the vicinity of the lower band.
  • Our buy/sell strategy is as we had planned i.e. buy at a low price and sell at a high price and most importantly time it as accurately as possible.

Validation with other stocks & configuration

We have successfully built a trading strategy for Apple stock. Let’s try with a different stock (GOOGLE) with different configurations as below to make sure our code and the strategy work across stocks.

  • Change the timeline to 5 years i.e 2018–01–01 to 2023–04–30
  • Change the shaded band color from yellow to light blue.
tickers = ['GOOG']
start_date = '2018-01-01'
end_date = '2023-04-30'
df = load_data(tickers)

ax.fill_between(bb.index, bb['upper'], bb['lower'], color = '#DBE9FA')
Source: Author

Closing thoughts

We have explored a very simplistic version of the trading strategy and this by no means is a comprehensive method to make trading decisions. There are a lot of macro and microeconomic factors that play a big role in stock performance. It is recommended that Bollinger Bands be used and interpreted along with other indicators before buying/selling. The objective of the blog was to use Python for stock analysis and to build Bollinger bands similar to the one on the trading platform. This should serve as a strong foundation to build more advanced trading strategies.

I hope you liked the article and found it helpful.

You can connect with me — on Linkedin and Github

Disclaimer

The blog is only educational and should not be used as professional advice for real-world financial decisions.

References

Investopedia

Leave a Reply

Your email address will not be published. Required fields are marked *