The Bollinger Stochastic Indicator in Python.
Creating & Charting the Bollinger Stochastic Indicator Using Python.
What if we fuse together two known powerful technical indicators? What would that give and how can we use it in trading? This article discusses the Bollinger bands and the stochastic oscillator from the perspective of a unified strategy.
I have just released a new book after the success of the previous book. It features advanced trend following indicators and strategies with a GitHub page dedicated to the continuously updated code. Also, this book features the original colors after having optimized for printing costs. If you feel that this interests you, feel free to visit the below Amazon link, or if you prefer to buy the PDF version, you could contact me on LinkedIn.
Trend Following Strategies in Python: How to Use Indicators to Follow the Trend.
Amazon.com: Trend Following Strategies in Python: How to Use Indicators to Follow the Trend.: 9798756939620: Kaabar…www.amazon.com
The Concept of Normalization
This great technique allows us to trap the values between 0 and 1 (or 0 and 100 if we wish to multiply by 100). The concept revolves around subtracting the minimum value in a certain lookback period from the current value and dividing by the maximum value in the same lookback period minus the minimum value (the same in the nominator).
To be able to manipulate the data, we first need to have an OHLC array (not a data frame) and define the following three small manipulation functions:
# The function to add a certain number of columns
def adder(Data, times):
for i in range(1, times + 1):
z = np.zeros((len(Data), 1), dtype = float)
Data = np.append(Data, z, axis = 1)
return Data
# The function to deleter a certain number of columns
def deleter(Data, index, times):
for i in range(1, times + 1):
Data = np.delete(Data, index, axis = 1)
return Data
# The function to delete a certain number of rows from the beginning
def jump(Data, jump):
Data = Data[jump:, ]
return Data
We can try to code the function of normalization in python. The below normalizes a given time series:
def normalizer(Data, lookback, what, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i, what] - min(Data[i - lookback + 1:i + 1, what])) / (max(Data[i - lookback + 1:i + 1, what]) - min(Data[i - lookback + 1:i + 1, what]))
except ValueError:
pass
Data[:, where] = Data[:, where] * 100
Data = jump(Data, lookback)
return Data
If we apply the function to the closing price of the EURUSD hourly time frame with a 50 lookback period (meaning, the function will look at the last 50 values and select the minimum and maximum values from there) we will have the following chart.
# Using the function
my_data = normalizer(my_data, 50, 3, 4)
Creating the Stochastic Oscillator Step-by-Step
The Stochastic Oscillator seeks to find oversold and overbought zones by incorporating the highs and lows using the normalization formula as shown below:
An overbought level is an area where the market is perceived to be extremely bullish and is bound to consolidate. An oversold level is an area where market is perceived to be extremely bearish and is bound to bounce. Hence, the Stochastic Oscillator is a contrarian indicator that seeks to signal reactions of extreme movements.
We will create the below function that calculates the Stochastic on an OHLC data:
def stochastic(Data, lookback, what, high, low, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i, what] - min(Data[i - lookback + 1:i + 1, low])) / (max(Data[i - lookback + 1:i + 1, high]) - min(Data[i - lookback + 1:i + 1, low]))
except ValueError:
pass
Data[:, where] = Data[:, where] * 100
return Data
# The Data variable refers to the OHLC array
# The lookback variable refers to the period (5, 14, 21, etc.)
# The what variable refers to the closing price
# The high variable refers to the high price
# The low variable refers to the low price
# The where variable refers to where to put the Oscillator
The above plot shows the EURUSD values plotted with a 14-period Stochastic Oscillator. Notice that the indicator will always be bounded between 0 and 100 due to the nature of its normalization function that traps values between the minimum and the maximum.
If you are also interested by more technical indicators and strategies, then my book might interest you:
The Book of Trading Strategies
Amazon.com: The Book of Trading Strategies: 9798532885707: Kaabar, Sofien: Bookswww.amazon.com
The Bollinger Bands
One of the pillars of descriptive statistics or any basic analysis method is the concept of averages. Averages give us a glance of the next expected value given a historical trend. They can also be a representative number of a larger dataset that helps us understand the data quickly. Another pillar is the concept of volatility. Volatility is the average deviation of the values from their mean. Let us create the simple hypothetical table with different random variables.
Let us suppose that the above is a timely ordered time series. If we had to naively guess the next value that comes after 10, then one of the best guesses can be the average the data. Therefore, if we sum up the values {5, 10, 15, 5, 10} and divide them by their quantity (i.e. 5), we get 9. This is the average of the above dataset. In python, we can generate the list or array and then calculate the average easily:
# Importing the required library
import numpy as np
# Creating the array
array = [5, 10, 15, 5, 10]
array = np.array(array)
# Calculating the mean
array.mean()
Now that we have calculated the mean value, we can see that no value in the dataset really equals 9. How do we know that the dataset is generally not close to the dataset? This is measured by what we call the Standard Deviation (Volatility).
The Standard Deviation simply measures the average distance away from the mean by looping through the individual values and comparing their distance to the mean.
# Calculating the mean
array.std()
The above code snippet calculates the Standard Deviation of the dataset which is around 3.74. This means that on average, the individual values are 3.74 units away from 9 (the mean). Now, let us move on to the normal distribution shown in the below curve.
The above curve shows the number of values within a number of standard deviations. For example, the area shaded in red represents around 1.33x of standard deviations away from the mean of zero. We know that if data is normally distributed then:
About 68% of the data falls within 1 standard deviation of the mean.
About 95% of the data falls within 2 standard deviations of the mean.
About 99% of the data falls within 3 standard deviations of the mean.
Presumably, this can be used to approximate the way to use financial returns data, but studies show that financial data is not normally distributed but at the moment we can assume it is so that we can use such indicators. The flawness of the method does not hinder much its usefulness.
Now, with the information below, we are ready to start creating the Bollinger Bands indicator:
Financial time series data can have a moving average that calculates a rolling mean window. For example a 20-period moving average calculates each time a 20-period mean that refreshes each time a new bar is formed.
On this rolling mean window, we can calculate the Standard Deviation of the same lookback period on the moving average.
What are the Bollinger Bands? When prices move, we can calculate a moving average (mean) around them so that we better understand their position regarding their mean. By doing this, we can also calculate where do they stand statistically.
Some say that the concept of volatility is the most important one in the financial markets industry. Trading the volatility bands is using some statistical properties to aid you in the decision making process, hence, you know you are in good hands.
The idea of the Bollinger Bands is to form two barriers calculated from a constant multiplied by the rolling Standard Deviation. They are in essence barriers that give out a probability that the market price should be contained within them. The lower Bollinger Band can be considered as a dynamic support while the upper Bollinger Band can be considered as a dynamic resistance. Hence, the Bollinger bands are simple a combination of a moving average that follows prices and a moving standard deviation(s) band that moves alongside the price and the moving average.
To calculate the two Bands, we use the following relatively simple formulas:
With the constant being the number of standard deviations that we choose to envelop prices with. By default, the indicator calculates a 20-period simple moving average and two standard deviations away from the price, then plots them together to get a better understanding of any statistical extremes. This means that on any time, we can calculate the mean and standard deviations of the last 20 observations we have and then multiply the standard deviation by the constant. Finally, we can add and subtract it from the mean to find the upper and lower band.
Clearly, the below chart seems easy to understand. Every time the price reaches one of the bands, a contrarian position is most suited and this is evidenced by the reactions we tend to see when prices hit these extremes. So, whenever the EURUSD reaches the upper band, we can say that statistically, it should consolidate and when it reaches the lower band, we can say that statistically, it should bounce.
To create the Bollinger Bands in Python, we need to define the moving average function, the standard deviation function, and then the Bollinger Bands function which will use the former two functions.
Now, we have to add some columns to the OHLC array, define the moving average and the Bollinger functions, then finally, use them.
# Adding a few columns
Data = adder(Data, 20)def ma(Data, lookback, what, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i - lookback + 1:i + 1, what].mean())
except IndexError:
pass
return Datadef volatility(Data, lookback, what, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i - lookback + 1:i + 1, what].std())
except IndexError:
pass
return Datadef BollingerBands(Data, boll_lookback, standard_distance, what, where):
# Calculating mean
ma(Data, boll_lookback, what, where)
# Calculating volatility
volatility(Data, boll_lookback, what, where + 1)
Data[:, where + 2] = Data[:, where] + (standard_distance * Data[:, where + 1])
Data[:, where + 3] = Data[:, where] - (standard_distance * Data[:, where + 1])
return Data
# Using the function to calculate a 20-period Bollinger Band with 2 Standard Deviations
Data = BollingerBands(Data, 20, 2, 3, 4)
The Bollinger Stochastic
The idea of the indicator is to apply the Bollinger Bands on the Stochastic Oscillator’s values, thus forming an envelope and eliminating the need for upper and lower barriers as support/resistance proxies. This can be particularly useful for long-term Stochastic Oscillator as they are less volatile than 2-period or 10-period oscillators.
The Bollinger Stochastic’s default parameters will be the following:
A 55-period Stochastic Oscillator applied as usual on the the high, low, and closing prices.
A 10-period Bollinger Bands applied onto the Stochastic Oscillator with a standard deviation of 1.5.
From the above chart, it is clear that we will interpret the blue line as the overbought level and the orange line as the oversold level. Therefore, the extremes strategies can be pretty simple:
Go long (Buy) whenever the 55-period Stochastic Oscillator touches or surpasses the upper band of the 10-period Bollinger.
Go short (Sell) whenever the 55-period Stochastic Oscillator touches or breaks the lower band of the 10-period Bollinger.
To create the indicator, we can follow this code:
boll_lookback = 10
standard_deviation = 1.5
stochastic_lookback = 55
my_data = stochastic(my_data, rsi_lookback, 3, 4, genre = 'High-Low')
my_data = BollingerBands(my_data, boll_lookback, standard_deviation, 4, 5)
Another variation of the indicator is to simply net the values, meaning that we subtract the Stochastic’s readings from the bands so that we have a less noisy indicator such as the below:
The above signal indicator is created following these two formulas:
If the Stochastic Oscillator is above the upper Bollinger Band, then the current value of the signal indicator is 1.
If the Stochastic Oscillator is below the lower Bollinger Band, then the current value of the signal indicator is -1.
for i in range(len(my_data)):
if my_data[i, 5] - my_data[i, 4] < 0:
my_data[i, 9] = 1elif my_data[i, 4] - my_data[i, 6] < 0:
my_data[i, 9] = -1
Coming back to the regular version of the indicator. The strategy works well when combined with proper risk management based on volatility indicators. The below shows the signal chart on the EURUSD.
def signal(Data, stochastic_column, upper_boll, lower_boll, buy, sell):
Data = adder(Data, 10)
for i in range(len(Data)):
if Data[i, stochastic_column] < Data[i, lower_boll] and Data[i - 1, stochastic_column] > Data[i - 1, lower_boll]:
Data[i, buy] = 1
elif Data[i, stochastic_column] > Data[i, upper_boll] and Data[i - 1, stochastic_column] < Data[i - 1, upper_boll]:
Data[i, sell] = -1
return Data
The frequency of signals is quite healthy and offer a lot of possibilities to manage the orders based on risk techniques and profit conservation methods.
Remember to always do your back-tests. You should always believe that other people are wrong. My indicators and style of trading may work for me but maybe not for you.
I am a firm believer of not spoon-feeding. I have learnt by doing and not by copying. You should get the idea, the function, the intuition, the conditions of the strategy, and then elaborate (an even better) one yourself so that you back-test and improve it before deciding to take it live or to eliminate it. My choice of not providing specific Back-testing results should lead the reader to explore more herself the strategy and work on it more.
One Last Word
I have recently started an NFT collection that aims to support different humanitarian and medical causes. The Society of Light is a set of limited collectibles which will help make the world slightly better as each sale will see a percentage of it sent directly to the charity attributed to the avatar. As I always say, nothing better than a bullet list to outline the benefits of buying these NFT’s:
High-potential gain: By concentrating the remaining sales proceedings on marketing and promoting The Society of Light, I am aiming to maximize their value as much as possible in the secondary market. Remember that trading in the secondary market also means that a portion of royalties will be donated to the same charity.
Art collection and portfolio diversification: Having a collection of avatars that symbolize good deeds is truly satisfying. Investing does not need to only have selfish needs even though there is nothing wrong with investing to make money. But what about investing to make money, help others, and collect art?
Donating to your preferred cause(s): This is a flexible way of allocating different funds to your charities.
A free copy of my book in PDF: Any buyer of any NFT will receive a free copy of my latest book shown in the link of the article.