# Merging Bollinger Bands with Stochastic Oscillator: A Python Guide
Written on
Chapter 1: Introduction to the Combined Indicator
What happens when we blend two powerful technical indicators? This article explores the integration of Bollinger Bands and the Stochastic Oscillator into a cohesive trading strategy.
I have recently published a book titled "Contrarian Trading Strategies in Python," which encompasses a variety of advanced contrarian indicators and trading strategies. The accompanying code is continually updated on a dedicated GitHub page. If you're interested, you can purchase the PDF version for 9.99 EUR via PayPal. Please ensure to include your email in the payment note so that you receive the document at the correct address. Don't forget to download it from Google Drive once you have access.
Understanding Normalization
Normalization is an effective technique that confines values within a range of 0 to 1 (or 0 to 100 if multiplied by 100). The method involves subtracting the minimum value from the current value and then dividing by the difference between the maximum and minimum values observed over a designated lookback period.
Before we can manipulate the data, we need an OHLC array (not a DataFrame) and to define three basic manipulation functions:
# Function to add specified 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
# Function to remove specified columns
def deleter(Data, index, times):
for i in range(1, times + 1):
Data = np.delete(Data, index, axis=1)return Data
# Function to remove a specified number of rows from the beginning
def jump(Data, jump):
Data = Data[jump:, ]
return Data
Next, we can implement a normalization function in Python to normalize 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
By applying this function to the EURUSD's closing prices on an hourly basis with a 50-period lookback, we can visualize the normalized data.
Normalizing EURUSD Data
# Applying normalization
my_data = normalizer(my_data, 50, 3, 4)
I have recently teamed up with Lumiwealth, offering various detailed courses that cover algorithmic trading, blockchain, and machine learning. Feel free to explore the link below for more information.
Constructing the Stochastic Oscillator
The Stochastic Oscillator identifies oversold and overbought conditions by applying the normalization formula:
An overbought level indicates a market that is excessively bullish and likely to consolidate, while an oversold level suggests extreme bearishness with a probable bounce back. Thus, the Stochastic Oscillator serves as a contrarian indicator, signaling responses to extreme market movements.
The following function computes the Stochastic Oscillator from 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 represents the OHLC array, while the lookback variable indicates the period (such as 5, 14, or 21). The what variable denotes the closing price, high refers to the highest price, low to the lowest price, and where indicates where to store the Oscillator.
Visualizing the Stochastic Oscillator
The plot below shows the EURUSD data along with a 14-period Stochastic Oscillator. This indicator remains confined between 0 and 100, thanks to the normalization function's design.
Check out this video on Backtesting Rayner Teo's Stochastic Trading Strategy for further insights:
The Role of Bollinger Bands in Trading
Averages form a crucial part of descriptive statistics and analytical methods. They provide insights into expected values based on historical trends and can summarize larger datasets for quick comprehension. The concept of volatility—measuring how much values deviate from their mean—is equally essential.
For example, if we consider a time series dataset, the average can be calculated as follows:
# Importing necessary library
import numpy as np
# Creating the array
array = [5, 10, 15, 5, 10]
array = np.array(array)
# Calculating the mean
array.mean()
While the mean may not exactly match any individual value in the dataset, the Standard Deviation (volatility) measures how closely values cluster around the mean:
# Calculating the standard deviation
array.std()
The resulting standard deviation gives a sense of how far values typically stray from the mean.
Introducing Bollinger Bands
Bollinger Bands are calculated using a moving average that reflects a rolling mean window, such as a 20-period moving average. By applying this rolling mean, we can also determine the standard deviation over the same lookback period.
Bollinger Bands help traders assess where prices stand relative to their mean. The two bands—upper and lower—are established by applying a constant multiplier to the rolling Standard Deviation. These bands act as dynamic support and resistance levels.
To calculate the Bollinger Bands, we utilize the following formulas:
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:
passreturn Data
def 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:
passreturn Data
def BollingerBands(Data, boll_lookback, standard_distance, what, where):
ma(Data, boll_lookback, what, where)
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
Creating the Bollinger Stochastic Indicator
The Bollinger Stochastic Indicator combines the Bollinger Bands with the Stochastic Oscillator, thus forming an envelope that negates the need for traditional support and resistance levels. This method is particularly beneficial for long-term Stochastic Oscillators, which tend to exhibit less volatility.
The default parameters for the Bollinger Stochastic are as follows:
- A 55-period Stochastic Oscillator applied to high, low, and closing prices.
- A 10-period Bollinger Band applied to the Stochastic Oscillator with a standard deviation of 1.5.
The following code can be used to create this indicator:
boll_lookback = 10
standard_deviation = 1.5
stochastic_lookback = 55
my_data = stochastic(my_data, stochastic_lookback, 3, 4)
my_data = BollingerBands(my_data, boll_lookback, standard_deviation, 4, 5)
Using the Signal Indicator
An alternative approach involves netting the values by subtracting the Stochastic readings from the bands, resulting in a less erratic indicator.
The current value of the signal indicator can be determined with the following logic:
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
The strategy works effectively when paired with robust risk management based on volatility indicators.
Conclusion
In conclusion, my goal is to contribute to the realm of objective technical analysis by promoting transparent techniques and strategies that require thorough back-testing prior to implementation. This approach aims to enhance the credibility of technical analysis and eliminate its subjective reputation.
Before adopting any trading technique or strategy, remember to:
- Maintain a critical perspective and avoid emotional decisions.
- Conduct back-tests using realistic simulations and conditions.
- If potential is found, optimize and run a forward test.
- Factor in transaction costs and slippage in your simulations.
- Incorporate risk management and position sizing in your tests.
Always stay vigilant, as market dynamics can shift and render strategies unprofitable.
Explore more on Charting Software and Indicators in this informative video: