Calculating Bollinger Band Correctly
My bollinger band comes out like the below, which doesn't seem right. Any idea what is wrong with my code for calculating upper and lower bollinber bands?
I obtained my data from here
start, end = dt.datetime(1976, 1, 1), dt.datetime(2013, 12, 31) sp = web.DataReader('^GSPC','yahoo', start, end) here are my bollinger calculations
calculation for bollinger band
ave = pd.stats.moments.rolling_mean(self[name], window) std = pd.stats.moments.rolling_std(self[name], window) self['upper'] = ave + (2 * std) self['lower'] = ave - (2 * std)
I am not into python but looks like that your average (ave) time series does not look right in relation to "SP", at least ave does not converge with "SP".
Perhaps try to plot `ave` to see where it is, and perhaps on a different window plot `std` to see its size. Providing a full code might be helpful as well.
@Bach I second the recommendation on providing more code (or perhaps a simplified version that can reproduce the plot from scratch).
In Pandas 0.19.2++:
def Bolinger_Bands(stock_price, window_size, num_of_std): rolling_mean = stock_price.rolling(window=window_size).mean() rolling_std = stock_price.rolling(window=window_size).std() upper_band = rolling_mean + (rolling_std*num_of_std) lower_band = rolling_mean - (rolling_std*num_of_std) return rolling_mean, upper_band, lower_band def main(): price_series = get_data(ticker, dates) # it is a Pandas series... rolling_avg_price, upper_band, lower_band = Bolinger_Bands(price_series, 20, 2) do_other_processing(rolling_avg_price, upper_band, lower_band) ...
def bbands(price, length=30, numsd=2): """ returns average, upper band, and lower band""" ave = pd.stats.moments.rolling_mean(price,length) sd = pd.stats.moments.rolling_std(price,length) upband = ave + (sd*numsd) dnband = ave - (sd*numsd) return np.round(ave,3), np.round(upband,3), np.round(dnband,3) sp['ave'], sp['upper'], sp['lower'] = bbands(sp.Close, length=30, numsd=1) sp= sp[-200:] sp.plot()
I believe that the answers given here are incorrect as they return the sample standard deviation while the the population measure is the correct calculation for Bollinger Bands. The bands usign the sample calc will be too wide. Pandas does not appear to allow a choice between the sample and population calculations for either solution presented here.
sd = pd.stats.moments.rolling_std(price,length) rolling_std = stock_price.rolling(window=window_size).std()
Numpy does allow a choice, so it should be used until a proper pandas solution is presented.
a = np.array([1,2,3,4,5]) print np.std(a, ddof=1) # sample print np.std(a, ddof=0) # population >>> 1.58113883008 1.41421356237 >>>
John Bollinger, CFA, CMT
Well, it appears that pandas has caught up with me. This works correctly now.
b = pd.DataFrame([1,2,3,4,5]) print b.rolling(window=5).std() # sample print b.rolling(window=5).std(ddof=0) # population