You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在已显示的Bokeh图表中添加新的Candle实例?

在Bokeh中显示图表后添加第四个Candle实例的解决方案

你说得没错——直接调用show(plot)生成的静态HTML确实没法动态添加新数据,因为这个静态文件已经把所有初始数据和渲染逻辑都固化了,没有后端或前端的动态更新机制。不过有两种靠谱的方法能实现你要的功能,下面详细说:

方法一:使用Bokeh Server(推荐用于实时/动态场景)

Bokeh Server是Bokeh专门用来做交互式动态可视化的工具,它能让Python代码直接和前端页面交互,随时更新图表数据。步骤如下:

  1. 先把你的Candle实例转换成Bokeh能识别的ColumnDataSource格式(这是Bokeh管理数据的核心对象);
  2. 创建蜡烛图的渲染元素(高低线+实体柱);
  3. 写一个更新函数,用来把新的Candle数据追加到数据源;
  4. 用Bokeh Server启动应用,就能在页面上触发更新了。

举个完整的代码例子:

from bokeh.models import ColumnDataSource, Button
from bokeh.plotting import figure, curdoc
from bokeh.layouts import column

# 假设你的Candle类定义如下
class Candle:
    def __init__(self, time, highest, lowest, open, close):
        self.time = time
        self.highest = highest
        self.lowest = lowest
        self.open = open
        self.close = close

# 初始化三个蜡烛实例
candle1 = Candle("2024-01-01", 100, 90, 95, 98)
candle2 = Candle("2024-01-02", 105, 97, 98, 102)
candle3 = Candle("2024-01-03", 110, 100, 102, 108)

# 转换为ColumnDataSource所需的字典格式
source = ColumnDataSource(data={
    'time': [c.time for c in [candle1, candle2, candle3]],
    'high': [c.highest for c in [candle1, candle2, candle3]],
    'low': [c.lowest for c in [candle1, candle2, candle3]],
    'open': [c.open for c in [candle1, candle2, candle3]],
    'close': [c.close for c in [candle1, candle2, candle3]]
})

# 创建蜡烛图
p = figure(x_axis_type='categorical', title="实时股票蜡烛图", x_axis_label="日期", y_axis_label="价格")
# 绘制高低影线
p.segment(x0='time', y0='high', x1='time', y1='low', source=source, color='black')
# 绘制蜡烛实体(上涨绿,下跌红)
p.vbar(x='time', width=0.6, top='open', bottom='close', source=source, fill_color='#2ecc71', line_color='black')
p.vbar(x='time', width=0.6, top='close', bottom='open', source=source, fill_color='#e74c3c', line_color='black')

# 定义添加新蜡烛的函数
def add_fourth_candle():
    # 创建第四个Candle实例
    candle4 = Candle("2024-01-04", 115, 105, 108, 112)
    # 用stream方法追加新数据(比update更高效,适合实时场景)
    source.stream({
        'time': [candle4.time],
        'high': [candle4.highest],
        'low': [candle4.lowest],
        'open': [candle4.open],
        'close': [candle4.close]
    })

# 添加一个按钮触发更新
add_button = Button(label="添加第四个蜡烛", button_type="success")
add_button.on_click(add_fourth_candle)

# 把图表和按钮加入文档
curdoc().add_root(column(p, add_button))

运行方式:保存成stock_candles.py,然后在终端执行bokeh serve --show stock_candles.py,浏览器会打开一个页面,点击按钮就能看到第四个蜡烛被添加进去了。

方法二:使用CustomJS在静态页面更新(无需后端)

如果不想搭Bokeh Server,也可以在生成静态HTML的时候,给页面加一个前端回调逻辑,用JavaScript来更新数据。这种方法适合不需要后端计算的简单场景:

from bokeh.models import ColumnDataSource, CustomJS, Button
from bokeh.plotting import figure, show
from bokeh.layouts import column

# 同样的初始Candle实例和数据源
class Candle:
    def __init__(self, time, highest, lowest, open, close):
        self.time = time
        self.highest = highest
        self.lowest = lowest
        self.open = open
        self.close = close

candle1 = Candle("2024-01-01", 100, 90, 95, 98)
candle2 = Candle("2024-01-02", 105, 97, 98, 102)
candle3 = Candle("2024-01-03", 110, 100, 102, 108)

source = ColumnDataSource(data={
    'time': [c.time for c in [candle1, candle2, candle3]],
    'high': [c.highest for c in [candle1, candle2, candle3]],
    'low': [c.lowest for c in [candle1, candle2, candle3]],
    'open': [c.open for c in [candle1, candle2, candle3]],
    'close': [c.close for c in [candle1, candle2, candle3]]
})

p = figure(x_axis_type='categorical', title="静态页面蜡烛图", x_axis_label="日期", y_axis_label="价格")
p.segment(x0='time', y0='high', x1='time', y1='low', source=source, color='black')
p.vbar(x='time', width=0.6, top='open', bottom='close', source=source, fill_color='#2ecc71', line_color='black')
p.vbar(x='time', width=0.6, top='close', bottom='open', source=source, fill_color='#e74c3c', line_color='black')

# 编写前端JavaScript回调
update_callback = CustomJS(args=dict(source=source), code="""
    // 定义第四个蜡烛的数据(这里可以根据需要修改)
    const newCandle = {
        time: ["2024-01-04"],
        high: [115],
        low: [105],
        open: [108],
        close: [112]
    };
    // 追加数据到数据源
    source.stream(newCandle);
""")

# 创建按钮绑定回调
add_button = Button(label="添加第四个蜡烛", button_type="success")
add_button.js_on_click(update_callback)

# 布局并生成静态HTML
layout = column(p, add_button)
show(layout)

运行这个代码后,会生成一个静态HTML文件,打开后点击按钮就能在前端直接添加新蜡烛,不需要任何后端服务。

为什么直接用show(plot)不行?

当你调用show(plot)时,Bokeh会把所有数据和渲染逻辑打包成静态HTML/JavaScript文件,Python进程执行完就结束了,页面里的内容是固定的——没有任何机制能让你从外部(不管是Python还是前端)修改已渲染的图表数据。所以必须用上面两种方法中的一种,给页面加上动态更新的逻辑。

内容的提问来源于stack exchange,提问作者Javier Guzmán

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:16:42