We already know how to calculate the simple moving average. So, if you need to, please review the Time for action – computing the simple moving average section in this chapter. This example will introduce the NumPy fill
function. The fill
function sets the value of an array to a scalar value. The function should be faster than array.flat = scalar
or you have to set the values of the array one by one in a loop. Perform the following steps to envelope with Bollinger bands:
sma
that contains the moving average values, we will loop through all the data sets corresponding to those values. After forming the data set, calculate the standard deviation. Note that it is necessary, at a certain point, to calculate the difference between each data point and the corresponding average value. If we did not have NumPy, we would loop through these points and subtract each of the values one by one from the corresponding average. However, the NumPy fill
function allows us to construct an array having elements set to the same value. This enables us to save on one loop and subtract arrays in one go.deviation = [] C = len(c) for i in range(N - 1, C): if i + N < C: dev = c[i: i + N] else: dev = c[-N:] averages = np.zeros(N) averages.fill(sma[i - N - 1]) dev = dev - averages dev = dev ** 2 dev = np.sqrt(np.mean(dev))) deviation.append(dev) deviation = 2 * np.array(deviation) upperBB = sma + deviation lowerBB = sma – deviation
t = numpy.arange(N - 1, C) plot(t, c_slice, lw=1.0) plot(t, sma, lw=2.0) plot(t, upperBB, lw=3.0) plot(t, lowerBB, lw=4.0) show()
The following is a chart of the Bollinger bands for our data. The jagged thin line in the middle represents the close price and the slightly thicker, smoother line crossing it is the moving average:
We worked out the Bollinger bands that envelope the close price of our data. More importantly, we got acquainted with the NumPy fill
function. This function fills an array with a scalar value. This is the only parameter of the fill
function (see bollingerbands.py
).
import numpy as np import sys from matplotlib.pyplot import plot from matplotlib.pyplot import show N = int(sys.argv[1]) weights = np.ones(N) / N print "Weights", weights c = np.loadtxt('data.csv', delimiter=',', usecols=(6,), unpack=True) sma = np.convolve(weights, c)[N-1:-N+1] deviation = [] C = len(c) for i in range(N - 1, C): if i + N < C: dev = c[i: i + N] else: dev = c[-N:] averages = np.zeros(N) averages.fill(sma[i - N - 1]) dev = dev - averages dev = dev ** 2 dev = np.sqrt(np.mean(dev)) deviation.append(dev) deviation = 2 * np.array(deviation) print len(deviation), len(sma) upperBB = sma + deviation lowerBB = sma - deviation c_slice = c[N-1:] between_bands = np.where((c_slice < upperBB) & (c_slice > lowerBB)) print lowerBB[between_bands] print c[between_bands] print upperBB[between_bands] between_bands = len(np.ravel(between_bands)) print "Ratio between bands", float(between_bands)/len(c_slice) t = np.arange(N - 1, C) plot(t, c_slice, lw=1.0) plot(t, sma, lw=2.0) plot(t, upperBB, lw=3.0) plot(t, lowerBB, lw=4.0) show()
It is customary to choose the simple moving average to center the Bollinger band on. The second most popular choice is the exponential moving average, so try that as an exercise. You can find a suitable example in this chapter, if you need pointers.
Check that the fill
function is faster or is as fast as array.flat = scalar
, or set the value in a loop.