Adding Bollinger bands to a stock price graph

I have a price chart that displays closing price over time (blue), a moving average (red), and the upper and lower bounds of a Bollinger band (black). It looks something like this:

Ignore for now how ugly it looks. What I want to do is add a semi-transparent grey area between the two black lines. I’m not sure what Glyph to use for this. At first, it seemed like Segment would work, since it takes two sets of x and y points, but it doesn’t behave how I expected - it created a bunch of vertical lines at each data point, without any transparency. I’m looking to shade the entire area below the upper boundary and above the lower boundary, instead.

Is there an object I can use that will do this? Or is there a different method that would work better?

You need to use a use the "patch" glyph, there is an example in "examples/plotting/file/glyphs.py". Basically you just supply all the point of the a polygon. So for two bands like this, reverse the top set of points, and then append it to the bottom set, and use those at the points for the patch glyph.

Bryan

···

On Nov 27, 2013, at 9:57 PM, Rebecca Paz <[email protected]> wrote:

I have a price chart that displays closing price over time (blue), a moving average (red), and the upper and lower bounds of a Bollinger band (black). It looks something like this:

Ignore for now how ugly it looks. What I want to do is add a semi-transparent grey area between the two black lines. I'm not sure what Glyph to use for this. At first, it seemed like Segment would work, since it takes two sets of x and y points, but it doesn't behave how I expected - it created a bunch of vertical lines at each data point, without any transparency. I'm looking to shade the entire area below the upper boundary and above the lower boundary, instead.

Is there an object I can use that will do this? Or is there a different method that would work better?

--
You received this message because you are subscribed to the Google Groups "Bokeh Discussion - Public" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/69044422-26c2-4814-872d-0d4c1d62c33e%40continuum.io\.
For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out\.

Ohh, so that’s where the Glyphs examples went! Okay, this helps.

So just to document what I’m doing: for Patch, the set of x is the dates index of the data and the set of y is, in semi-psuedocode, lowerband.extend(upperband.reverse()). Correct?

The Pandas TimeSeries structure associates the data points with a date (e.g. 2013-11-22 519.80). If I reorder the structure, the order will change, but the points will keep their associated date index. Will this display differently on a plot, or does the fact that each stock price (y) is associated with a date (x) mean that it won’t look any different?

···

On Thu, Nov 28, 2013 at 1:32 AM, Bryan Van de Ven [email protected] wrote:

You need to use a use the “patch” glyph, there is an example in “examples/plotting/file/glyphs.py”. Basically you just supply all the point of the a polygon. So for two bands like this, reverse the top set of points, and then append it to the bottom set, and use those at the points for the patch glyph.

Bryan

On Nov 27, 2013, at 9:57 PM, Rebecca Paz [email protected] wrote:

I have a price chart that displays closing price over time (blue), a moving average (red), and the upper and lower bounds of a Bollinger band (black). It looks something like this:

Ignore for now how ugly it looks. What I want to do is add a semi-transparent grey area between the two black lines. I’m not sure what Glyph to use for this. At first, it seemed like Segment would work, since it takes two sets of x and y points, but it doesn’t behave how I expected - it created a bunch of vertical lines at each data point, without any transparency. I’m looking to shade the entire area below the upper boundary and above the lower boundary, instead.

Is there an object I can use that will do this? Or is there a different method that would work better?

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/69044422-26c2-4814-872d-0d4c1d62c33e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/45fNzvSOnaY/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/13D47493-A148-4FA0-BD55-89682D9F46FC%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

You need to append a reversed set of x values too (x and y for patch should be the same length). I would just make a copy of the date series for the patch glyph.

···

On Thu, Nov 28, 2013 at 1:32 AM, Bryan Van de Ven [email protected] wrote:

You need to use a use the “patch” glyph, there is an example in “examples/plotting/file/glyphs.py”. Basically you just supply all the point of the a polygon. So for two bands like this, reverse the top set of points, and then append it to the bottom set, and use those at the points for the patch glyph.

Bryan

On Nov 27, 2013, at 9:57 PM, Rebecca Paz [email protected] wrote:

I have a price chart that displays closing price over time (blue), a moving average (red), and the upper and lower bounds of a Bollinger band (black). It looks something like this:

Ignore for now how ugly it looks. What I want to do is add a semi-transparent grey area between the two black lines. I’m not sure what Glyph to use for this. At first, it seemed like Segment would work, since it takes two sets of x and y points, but it doesn’t behave how I expected - it created a bunch of vertical lines at each data point, without any transparency. I’m looking to shade the entire area below the upper boundary and above the lower boundary, instead.

Is there an object I can use that will do this? Or is there a different method that would work better?

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/69044422-26c2-4814-872d-0d4c1d62c33e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/45fNzvSOnaY/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/13D47493-A148-4FA0-BD55-89682D9F46FC%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

Almost there!

The plot is almost correct now, but the dates show up as NaN for some reason. This might be because I changed the x and y points of the basic stock data to just a numpy array of the price and date values instead of a pandas data structure, to make it simpler. I’ll have to change both the raw data’s date series as well as the band’s date series to a Pandas DatetimeIndex, by doing something like this:

pandas.to_datetime(banddates)

where banddates is the Numpy array version of the raw dates with a reversed version of itself appended to it. So, it’s converting a Numpy array to a DatetimeIndex - and that seems to work!

Everything displays correctly now (as far as I can see). This wasn’t immediately obvious, and I know others might want to add bands to their stock data, so here’s a snippet of how I got the band to display correctly and how I got the right data formats:

from bokeh.plotting import *

import datetime

import pandas

import pandas.io.data as web

start = datetime.date(2012, 1, 1)

end = datetime.date.today()

data = web.DataReader(‘AAPL’, ‘google’, start, end)

close = data[‘Close’].values # Type: Numpy array

dates = data.index.values # Type: Numpy array

Plotting raw stock data.

x = data.index # Type: Pandas DatetimeIndex

y = close # Type: Numpy array

line(x, y, color=‘blue’, x_axis_type=‘datetime’) # DatetimeIndex vs. Numpy array

Define simple moving average:

sma50 = pandas.rolling_mean(close,50,min_periods=50) # Type: Numpy array

Define upper and lower Bollinger band lines:

stdev = pandas.rolling_std(close,50,min_periods=50) # Type: Numpy array

upperband = sma50 + (2 * stdev) # Type: Numpy array

lowerband = sma50 - (2 * stdev) # Type: Numpy array

Bollinger shading glyph:

reverse_upper = upperband[::-1] # Type: Numpy array

bandprice = np.append(lowerband, reverse_upper) # Type: Numpy array

banddates = np.append(dates, dates[::-1]) # Type: Numpy array

patch(pandas.to_datetime(banddates), bandprice, color=‘#A6CEE3’, fill_alpha=0.3, x_axis_type=‘datetime’) # DatetimeIndex vs. Numpy array

There might be a simpler way of explaining this, but this is the best I can do. I’m not too great at documentation, so if anyone needs clarification, I implore you to ask!

···

Anyway, it finally works. Thanks, Bryan! I did also find a bug of sorts: resizing a graph gets kinda sketchy if you move the cursor too quickly. I’m using Google Chrome, and if you move too fast, the resizing “stops”. It’s kinda hard to explain, so try turning the resize function on, holding onto the corner of the graph, and move the cursor really quickly to the right. You’ll see what I mean.

Also, any advice for adding functionality or making this look nicer would be greatly appreciated!

On Thursday, November 28, 2013 2:14:43 PM UTC-5, Bryan Van de ven wrote:

You need to append a reversed set of x values too (x and y for patch should be the same length). I would just make a copy of the date series for the patch glyph.

On Nov 28, 2013, at 13:09, Rebecca Paz [email protected] wrote:

Ohh, so that’s where the Glyphs examples went! Okay, this helps.

So just to document what I’m doing: for Patch, the set of x is the dates index of the data and the set of y is, in semi-psuedocode, lowerband.extend(upperband.reverse()). Correct?

The Pandas TimeSeries structure associates the data points with a date (e.g. 2013-11-22 519.80). If I reorder the structure, the order will change, but the points will keep their associated date index. Will this display differently on a plot, or does the fact that each stock price (y) is associated with a date (x) mean that it won’t look any different?

On Thu, Nov 28, 2013 at 1:32 AM, Bryan Van de Ven [email protected] wrote:

You need to use a use the “patch” glyph, there is an example in “examples/plotting/file/glyphs.py”. Basically you just supply all the point of the a polygon. So for two bands like this, reverse the top set of points, and then append it to the bottom set, and use those at the points for the patch glyph.

Bryan

On Nov 27, 2013, at 9:57 PM, Rebecca Paz [email protected] wrote:

I have a price chart that displays closing price over time (blue), a moving average (red), and the upper and lower bounds of a Bollinger band (black). It looks something like this:

Ignore for now how ugly it looks. What I want to do is add a semi-transparent grey area between the two black lines. I’m not sure what Glyph to use for this. At first, it seemed like Segment would work, since it takes two sets of x and y points, but it doesn’t behave how I expected - it created a bunch of vertical lines at each data point, without any transparency. I’m looking to shade the entire area below the upper boundary and above the lower boundary, instead.

Is there an object I can use that will do this? Or is there a different method that would work better?

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/69044422-26c2-4814-872d-0d4c1d62c33e%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

You received this message because you are subscribed to a topic in the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this topic, visit https://groups.google.com/a/continuum.io/d/topic/bokeh/45fNzvSOnaY/unsubscribe.

To unsubscribe from this group and all its topics, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/13D47493-A148-4FA0-BD55-89682D9F46FC%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/CAOEN1_%3DCFYF7idbGt8eh2cS5%3DBL-BnpXovG%3Daczopd%2BcbvTEUA%40mail.gmail.com.

For more options, visit https://groups.google.com/a/continuum.io/groups/opt_out.