散景中 show/hide 行的复选框(股票数据移动平均线)
Checkboxes to show/hide lines in Bokeh (Stock Data Moving Average)
下面的代码显示了一个 Bokeh 脚本示例,它使用三个复选框来 show/hide 行在 Bokeh 图表上。
系列也是原始数据的函数。可以通过滑块访问功能参数。可以在文本框中调整原始数据。
要访问,请在 CMD 中输入以下内容:
bokeh-server --script C:\Path\to\python\Toggle.py
我经常使用 Bokeh 网站上的滑块 example。
MVA 代码来自 python 由 Harrison Kinsley
创建的很棒的网站
import numpy as np
import pandas as pd
from collections import OrderedDict
from bokeh.plotting import figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.properties import Instance
from bokeh.server.app import bokeh_app
from bokeh.server.utils.plugins import object_page
from bokeh.models.renderers import GlyphRenderer
from bokeh.models.widgets import (
HBox,
Slider,
TextInput,
VBoxForm,
CheckboxGroup )
def get_stockdata(ticker):
MyStock = pd.read_csv(
"http://ichart.yahoo.com/table.csv?s="+ticker+"&a=0&b=1&c=2000&d=0&e=1&f=2015",
parse_dates=['Date'])
xyvalues = OrderedDict(AdjClose=MyStock['Adj Close'],Date=MyStock['Date'])
for x in xyvalues.keys():
xyvalues[x] =xyvalues[x][::-1]
return xyvalues
def movingaverage(values,window):
weigths = np.repeat(1.0, window)/window
smas = np.convolve(values, weigths, 'valid')
return smas # as a numpy array
class HackApp(HBox):
extra_generated_classes = [["HackApp", "HackApp", "HBox"]]
inputs = Instance(VBoxForm)
text = Instance(TextInput)
toggle = Instance(CheckboxGroup)
MVA_1 = Instance(Slider)
MVA_2 = Instance(Slider)
plot = Instance(Plot)
source = Instance(ColumnDataSource)
source2 = Instance(ColumnDataSource)
source3 = Instance(ColumnDataSource)
@classmethod
def create(cls):
obj = cls()
obj.source = ColumnDataSource(data=dict(x_y=[], y=[]))
obj.source2 = ColumnDataSource(data=dict(x_z=[], z=[]))
obj.source3 = ColumnDataSource(data=dict(x_a=[], a=[]))
obj.text = TextInput(
title="title", name='title', value='MSFT'
)
obj.toggle = CheckboxGroup( labels=["Closes","MVA_1","MVA_2"],active=[0])
obj.MVA_1 = Slider(
title="MVA_1", name='MVA_1',
value=100, start=-0.0, end=500.0, step=10
)
obj.MVA_2 = Slider(
title="MVA_2", name='MVA_2',
value=200, start=-0.0, end=500.0, step=10
)
toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
plot = figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=obj.text.value,
x_axis_type = "datetime"
)
plot.line('x_y', 'y', source=obj.source,
line_width=3,
line_alpha=0.6,
line_color="red"
)
plot.line('x_z', 'z', source=obj.source2,
line_width=3,
line_alpha=0.6,
line_color="blue"
)
plot.line('x_a', 'a', source=obj.source3,
line_width=3,
line_alpha=0.6,
line_color="green"
)
obj.plot = plot
obj.update_data()
obj.inputs = VBoxForm(
children=[
obj.text,
obj.toggle,
obj.MVA_1,
obj.MVA_2,
]
)
obj.children.append(obj.inputs)
obj.children.append(obj.plot)
return obj
def checkbox_handler(self,active):
self.update_data(active)
def setup_events(self):
super(HackApp, self).setup_events()
if not self.text:
return
self.text.on_change('value', self, 'input_change')
for w in ["MVA_1", "MVA_2"]:
getattr(self, w).on_change('value', self, 'input_change')
self.toggle.on_click(self.checkbox_handler)
def input_change(self, obj, attrname, old, new):
self.update_data()
self.plot.title = self.text.value
def update_data(self,hide=False):
N = 200
a=1
b = self.MVA_1.value
b2 = self.MVA_2.value
print(self.toggle.active,"self.toggle")
ticker = self.text.value
xyvalues=get_stockdata(ticker)
y_min = min(xyvalues['AdjClose'] )*0.9
y_max = max(xyvalues['AdjClose'])*1.1
MA1 = b
MA2 = b2
Av1 = movingaverage(xyvalues['AdjClose'], MA1)
Av2 = movingaverage(xyvalues['AdjClose'], MA2)
SP1 = len(xyvalues['Date'][MA1-1:])
SP2 = len(xyvalues['Date'][MA2-1:])
Av1=Av1[-SP1:]
Av2=Av2[-SP2:]
avgdate1=xyvalues['Date'] [-SP1:]
avgdate2=xyvalues['Date'] [-SP2:]
x_y = []
y = []
x_z = []
z = []
x_a = []
a = []
for p in self.toggle.active:
if p ==0:
x_y = xyvalues['Date']
y = xyvalues['AdjClose']
if p ==1:
x_z = avgdate1
z = Av1
if p ==2:
x_a = avgdate2
a = Av2
self.source.data = dict(x_y=x_y, y=y)
self.source2.data = dict(x_z=x_z, z=z)
self.source3.data = dict(x_a=x_a, a=a)
self.plot.y_range.start=y_min
self.plot.y_range.end=y_max
@bokeh_app.route("/bokeh/hack/")
@object_page("sin")
def make_hack():
app = HackApp.create()
return app
对每次选择的重绘速度不满意,因此我更新了它以更改线条的 alpha 属性。它需要命名和选择在 _list_attr_splat
对象中检索到的字形。这是完整的代码。更改在创建和 checkbox_handler
方法中。
import numpy as np
import pandas as pd
from collections import OrderedDict
from bokeh.plotting import figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.properties import Instance
from bokeh.server.app import bokeh_app
from bokeh.server.utils.plugins import object_page
from bokeh.models.renderers import GlyphRenderer
from bokeh.models.widgets import HBox,Slider,TextInput, VBoxForm, CheckboxGroup
def get_stockdata(ticker):
MyStock = pd.read_csv(
"http://ichart.yahoo.com/table.csv?s="+ticker+"&a=0&b=1&c=2000&d=0&e=1&f=2015",
parse_dates=['Date'])
xyvalues = OrderedDict(AdjClose=MyStock['Adj Close'],Date=MyStock['Date'])
for x in xyvalues.keys():
xyvalues[x] =xyvalues[x][::-1]
return xyvalues
def movingaverage(values,window):
weigths = np.repeat(1.0, window)/window
smas = np.convolve(values, weigths, 'valid')
return smas # as a numpy array
class HackApp(HBox):
extra_generated_classes = [["HackApp", "HackApp", "HBox"]]
inputs = Instance(VBoxForm)
text = Instance(TextInput)
toggle = Instance(CheckboxGroup)
MVA_1 = Instance(Slider)
MVA_2 = Instance(Slider)
plot = Instance(Plot)
source = Instance(ColumnDataSource)
source2 = Instance(ColumnDataSource)
source3 = Instance(ColumnDataSource)
@classmethod
def create(cls):
obj = cls()
obj.source = ColumnDataSource(data=dict(x_y=[], y=[]))
obj.source2 = ColumnDataSource(data=dict(x_z=[], z=[]))
obj.source3 = ColumnDataSource(data=dict(x_a=[], a=[]))
obj.text = TextInput(
title="title", name='title', value='MSFT'
)
obj.toggle = CheckboxGroup( labels=["Closes","MVA_1","MVA_2"],active=[0,1,2])
obj.MVA_1 = Slider(
title="MVA_1", name='MVA_1',
value=100, start=-0.0, end=500.0, step=10
)
obj.MVA_2 = Slider(
title="MVA_2", name='MVA_2',
value=200, start=-0.0, end=500.0, step=10
)
toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
plot = figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=obj.text.value,
x_axis_type = "datetime"
)
plot.line('x_y', 'y', source=obj.source,
line_width=3,
line_alpha=0.6,
line_color="red",
name='closes'
)
plot.line('x_z', 'z', source=obj.source2,
line_width=3,
line_alpha=0.6,
line_color="blue",
name='av1'
)
plot.line('x_a', 'a', source=obj.source3,
line_width=3,
line_alpha=0.6,
line_color="green",
name='av2'
)
obj.plot = plot
obj.update_data()
obj.inputs = VBoxForm(
children=[
obj.text,
obj.toggle,
obj.MVA_1,
obj.MVA_2,
]
)
obj.children.append(obj.inputs)
obj.children.append(obj.plot)
return obj
def checkbox_handler(self,active):
for n,nm in enumerate(['closes','av1','av2']):
sel=self.plot.select(dict(name=nm))
sel[0].glyph.line_alpha= 1 if n in self.toggle.active else 0
def setup_events(self):
super(HackApp, self).setup_events()
if not self.text:
return
self.text.on_change('value', self, 'input_change')
for w in ["MVA_1", "MVA_2"]:
getattr(self, w).on_change('value', self, 'input_change')
self.toggle.on_click(self.checkbox_handler)
def input_change(self, obj, attrname, old, new):
self.update_data()
self.plot.title = self.text.value
def update_data(self,hide=False):
N = 200
a=1
b = self.MVA_1.value
b2 = self.MVA_2.value
print(self.toggle.active,"self.toggle")
ticker = self.text.value
xyvalues=get_stockdata(ticker)
y_min = min(xyvalues['AdjClose'] )*0.9
y_max = max(xyvalues['AdjClose'])*1.1
MA1 = b
MA2 = b2
Av1 = movingaverage(xyvalues['AdjClose'], MA1)
Av2 = movingaverage(xyvalues['AdjClose'], MA2)
SP1 = len(xyvalues['Date'][MA1-1:])
SP2 = len(xyvalues['Date'][MA2-1:])
Av1=Av1[-SP1:]
Av2=Av2[-SP2:]
avgdate1=xyvalues['Date'] [-SP1:]
avgdate2=xyvalues['Date'] [-SP2:]
x_y = []
y = []
x_z = []
z = []
x_a = []
a = []
for p in self.toggle.active:
if p ==0:
x_y = xyvalues['Date']
y = xyvalues['AdjClose']
if p ==1:
x_z = avgdate1
z = Av1
if p ==2:
x_a = avgdate2
a = Av2
self.source.data = dict(x_y=x_y, y=y)
self.source2.data = dict(x_z=x_z, z=z)
self.source3.data = dict(x_a=x_a, a=a)
self.plot.y_range.start=y_min
self.plot.y_range.end=y_max
@bokeh_app.route("/bokeh/hack/")
@object_page("sin")
def make_hack():
app = HackApp.create()
return app
下面的代码显示了一个 Bokeh 脚本示例,它使用三个复选框来 show/hide 行在 Bokeh 图表上。
系列也是原始数据的函数。可以通过滑块访问功能参数。可以在文本框中调整原始数据。
要访问,请在 CMD 中输入以下内容:
bokeh-server --script C:\Path\to\python\Toggle.py
我经常使用 Bokeh 网站上的滑块 example。
MVA 代码来自 python 由 Harrison Kinsley
创建的很棒的网站import numpy as np
import pandas as pd
from collections import OrderedDict
from bokeh.plotting import figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.properties import Instance
from bokeh.server.app import bokeh_app
from bokeh.server.utils.plugins import object_page
from bokeh.models.renderers import GlyphRenderer
from bokeh.models.widgets import (
HBox,
Slider,
TextInput,
VBoxForm,
CheckboxGroup )
def get_stockdata(ticker):
MyStock = pd.read_csv(
"http://ichart.yahoo.com/table.csv?s="+ticker+"&a=0&b=1&c=2000&d=0&e=1&f=2015",
parse_dates=['Date'])
xyvalues = OrderedDict(AdjClose=MyStock['Adj Close'],Date=MyStock['Date'])
for x in xyvalues.keys():
xyvalues[x] =xyvalues[x][::-1]
return xyvalues
def movingaverage(values,window):
weigths = np.repeat(1.0, window)/window
smas = np.convolve(values, weigths, 'valid')
return smas # as a numpy array
class HackApp(HBox):
extra_generated_classes = [["HackApp", "HackApp", "HBox"]]
inputs = Instance(VBoxForm)
text = Instance(TextInput)
toggle = Instance(CheckboxGroup)
MVA_1 = Instance(Slider)
MVA_2 = Instance(Slider)
plot = Instance(Plot)
source = Instance(ColumnDataSource)
source2 = Instance(ColumnDataSource)
source3 = Instance(ColumnDataSource)
@classmethod
def create(cls):
obj = cls()
obj.source = ColumnDataSource(data=dict(x_y=[], y=[]))
obj.source2 = ColumnDataSource(data=dict(x_z=[], z=[]))
obj.source3 = ColumnDataSource(data=dict(x_a=[], a=[]))
obj.text = TextInput(
title="title", name='title', value='MSFT'
)
obj.toggle = CheckboxGroup( labels=["Closes","MVA_1","MVA_2"],active=[0])
obj.MVA_1 = Slider(
title="MVA_1", name='MVA_1',
value=100, start=-0.0, end=500.0, step=10
)
obj.MVA_2 = Slider(
title="MVA_2", name='MVA_2',
value=200, start=-0.0, end=500.0, step=10
)
toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
plot = figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=obj.text.value,
x_axis_type = "datetime"
)
plot.line('x_y', 'y', source=obj.source,
line_width=3,
line_alpha=0.6,
line_color="red"
)
plot.line('x_z', 'z', source=obj.source2,
line_width=3,
line_alpha=0.6,
line_color="blue"
)
plot.line('x_a', 'a', source=obj.source3,
line_width=3,
line_alpha=0.6,
line_color="green"
)
obj.plot = plot
obj.update_data()
obj.inputs = VBoxForm(
children=[
obj.text,
obj.toggle,
obj.MVA_1,
obj.MVA_2,
]
)
obj.children.append(obj.inputs)
obj.children.append(obj.plot)
return obj
def checkbox_handler(self,active):
self.update_data(active)
def setup_events(self):
super(HackApp, self).setup_events()
if not self.text:
return
self.text.on_change('value', self, 'input_change')
for w in ["MVA_1", "MVA_2"]:
getattr(self, w).on_change('value', self, 'input_change')
self.toggle.on_click(self.checkbox_handler)
def input_change(self, obj, attrname, old, new):
self.update_data()
self.plot.title = self.text.value
def update_data(self,hide=False):
N = 200
a=1
b = self.MVA_1.value
b2 = self.MVA_2.value
print(self.toggle.active,"self.toggle")
ticker = self.text.value
xyvalues=get_stockdata(ticker)
y_min = min(xyvalues['AdjClose'] )*0.9
y_max = max(xyvalues['AdjClose'])*1.1
MA1 = b
MA2 = b2
Av1 = movingaverage(xyvalues['AdjClose'], MA1)
Av2 = movingaverage(xyvalues['AdjClose'], MA2)
SP1 = len(xyvalues['Date'][MA1-1:])
SP2 = len(xyvalues['Date'][MA2-1:])
Av1=Av1[-SP1:]
Av2=Av2[-SP2:]
avgdate1=xyvalues['Date'] [-SP1:]
avgdate2=xyvalues['Date'] [-SP2:]
x_y = []
y = []
x_z = []
z = []
x_a = []
a = []
for p in self.toggle.active:
if p ==0:
x_y = xyvalues['Date']
y = xyvalues['AdjClose']
if p ==1:
x_z = avgdate1
z = Av1
if p ==2:
x_a = avgdate2
a = Av2
self.source.data = dict(x_y=x_y, y=y)
self.source2.data = dict(x_z=x_z, z=z)
self.source3.data = dict(x_a=x_a, a=a)
self.plot.y_range.start=y_min
self.plot.y_range.end=y_max
@bokeh_app.route("/bokeh/hack/")
@object_page("sin")
def make_hack():
app = HackApp.create()
return app
对每次选择的重绘速度不满意,因此我更新了它以更改线条的 alpha 属性。它需要命名和选择在 _list_attr_splat
对象中检索到的字形。这是完整的代码。更改在创建和 checkbox_handler
方法中。
import numpy as np
import pandas as pd
from collections import OrderedDict
from bokeh.plotting import figure
from bokeh.models import Plot, ColumnDataSource
from bokeh.properties import Instance
from bokeh.server.app import bokeh_app
from bokeh.server.utils.plugins import object_page
from bokeh.models.renderers import GlyphRenderer
from bokeh.models.widgets import HBox,Slider,TextInput, VBoxForm, CheckboxGroup
def get_stockdata(ticker):
MyStock = pd.read_csv(
"http://ichart.yahoo.com/table.csv?s="+ticker+"&a=0&b=1&c=2000&d=0&e=1&f=2015",
parse_dates=['Date'])
xyvalues = OrderedDict(AdjClose=MyStock['Adj Close'],Date=MyStock['Date'])
for x in xyvalues.keys():
xyvalues[x] =xyvalues[x][::-1]
return xyvalues
def movingaverage(values,window):
weigths = np.repeat(1.0, window)/window
smas = np.convolve(values, weigths, 'valid')
return smas # as a numpy array
class HackApp(HBox):
extra_generated_classes = [["HackApp", "HackApp", "HBox"]]
inputs = Instance(VBoxForm)
text = Instance(TextInput)
toggle = Instance(CheckboxGroup)
MVA_1 = Instance(Slider)
MVA_2 = Instance(Slider)
plot = Instance(Plot)
source = Instance(ColumnDataSource)
source2 = Instance(ColumnDataSource)
source3 = Instance(ColumnDataSource)
@classmethod
def create(cls):
obj = cls()
obj.source = ColumnDataSource(data=dict(x_y=[], y=[]))
obj.source2 = ColumnDataSource(data=dict(x_z=[], z=[]))
obj.source3 = ColumnDataSource(data=dict(x_a=[], a=[]))
obj.text = TextInput(
title="title", name='title', value='MSFT'
)
obj.toggle = CheckboxGroup( labels=["Closes","MVA_1","MVA_2"],active=[0,1,2])
obj.MVA_1 = Slider(
title="MVA_1", name='MVA_1',
value=100, start=-0.0, end=500.0, step=10
)
obj.MVA_2 = Slider(
title="MVA_2", name='MVA_2',
value=200, start=-0.0, end=500.0, step=10
)
toolset = "crosshair,pan,reset,resize,save,wheel_zoom"
plot = figure(title_text_font_size="12pt",
plot_height=400,
plot_width=400,
tools=toolset,
title=obj.text.value,
x_axis_type = "datetime"
)
plot.line('x_y', 'y', source=obj.source,
line_width=3,
line_alpha=0.6,
line_color="red",
name='closes'
)
plot.line('x_z', 'z', source=obj.source2,
line_width=3,
line_alpha=0.6,
line_color="blue",
name='av1'
)
plot.line('x_a', 'a', source=obj.source3,
line_width=3,
line_alpha=0.6,
line_color="green",
name='av2'
)
obj.plot = plot
obj.update_data()
obj.inputs = VBoxForm(
children=[
obj.text,
obj.toggle,
obj.MVA_1,
obj.MVA_2,
]
)
obj.children.append(obj.inputs)
obj.children.append(obj.plot)
return obj
def checkbox_handler(self,active):
for n,nm in enumerate(['closes','av1','av2']):
sel=self.plot.select(dict(name=nm))
sel[0].glyph.line_alpha= 1 if n in self.toggle.active else 0
def setup_events(self):
super(HackApp, self).setup_events()
if not self.text:
return
self.text.on_change('value', self, 'input_change')
for w in ["MVA_1", "MVA_2"]:
getattr(self, w).on_change('value', self, 'input_change')
self.toggle.on_click(self.checkbox_handler)
def input_change(self, obj, attrname, old, new):
self.update_data()
self.plot.title = self.text.value
def update_data(self,hide=False):
N = 200
a=1
b = self.MVA_1.value
b2 = self.MVA_2.value
print(self.toggle.active,"self.toggle")
ticker = self.text.value
xyvalues=get_stockdata(ticker)
y_min = min(xyvalues['AdjClose'] )*0.9
y_max = max(xyvalues['AdjClose'])*1.1
MA1 = b
MA2 = b2
Av1 = movingaverage(xyvalues['AdjClose'], MA1)
Av2 = movingaverage(xyvalues['AdjClose'], MA2)
SP1 = len(xyvalues['Date'][MA1-1:])
SP2 = len(xyvalues['Date'][MA2-1:])
Av1=Av1[-SP1:]
Av2=Av2[-SP2:]
avgdate1=xyvalues['Date'] [-SP1:]
avgdate2=xyvalues['Date'] [-SP2:]
x_y = []
y = []
x_z = []
z = []
x_a = []
a = []
for p in self.toggle.active:
if p ==0:
x_y = xyvalues['Date']
y = xyvalues['AdjClose']
if p ==1:
x_z = avgdate1
z = Av1
if p ==2:
x_a = avgdate2
a = Av2
self.source.data = dict(x_y=x_y, y=y)
self.source2.data = dict(x_z=x_z, z=z)
self.source3.data = dict(x_a=x_a, a=a)
self.plot.y_range.start=y_min
self.plot.y_range.end=y_max
@bokeh_app.route("/bokeh/hack/")
@object_page("sin")
def make_hack():
app = HackApp.create()
return app