如何将破折号 plotly extenddata api 与 go.candlestick 绘图一起使用?

how to use the dash plotly extenddata api with go.candlestick plots?

我正在尝试通过在收到新数据时对其进行扩展来从实时数据流中绘制烛台,但它无法正常工作。目前通过检查 chrome 的 DevTool 控制台,它显示以下错误 -

Error: attribute type must be an array of length equal to indices array length

下面是我的代码。它使用破折号扩展库来接收数据而不是使用间隔,因为同时实际程序也会更新一个报价流。

我推测它要么与 plotly candlestick 数据格式有关,要么只是 go.candlestick 不支持扩展数据,知道如何解决它吗?

import json
import dash_html_components as html
import dash_core_components as dcc
import plotly.graph_objects as go
from gevent import sleep
from dash import Dash
from dash.dependencies import Input, Output, State
from dash_extensions import WebSocket
from dash_extensions.websockets import SocketPool, run_server

import threading, queue, time
from datetime import datetime
from pytz import timezone
x = 0
def genData(q):
    global x
    while True:
        values = {}
        values['high'] = 10
        values['low'] = 5 
        values['open'] = 6
        values['close'] = 9
        
        values['CHANGE'] = 0
        values['MARKET_STATE'] = 'edit'
        values['UPDATE_TIME'] = datetime.now(timezone('Europe/London')).time().strftime('%H:%M:%S')
        item = {}
        item['values'] = values
        q.put(item)
        x += 0.1
        sleep(1)

# This block runs asynchronously.
def ws_handler(ws, q):
    # for data in data_feed():
    #     ws.send(json.dumps(data))  # send data
    while True:
        while len(list(q.queue)) != 0:
            data = q.get()
            #print(data)
            sleep(0.1)  # delay between data events
            ws.send(json.dumps(data))
            q.task_done()


q = queue.Queue()
# Create example app.
app = Dash(prevent_initial_callbacks=True)
socket_pool = SocketPool(app, handler=lambda x: ws_handler(x, q))
app.layout = html.Div([
    dcc.Graph(id="graph", figure=go.Figure(go.Candlestick(x=[],open=[],close=[],high=[],low=[]))),#go.Scatter(x=[], y=[]))),
    WebSocket(id="ws")
])


@app.callback(Output("graph", "extendData"), [Input("ws", "message")], [State("graph", "figure")])
def update_graph(msg, figure):    
    data = json.loads(msg['data'])['values']
    return (
        dict(
            x = [[ datetime.strptime(data['UPDATE_TIME'],'%H:%M:%S') ]],
            open  = [[ data['open'] ]],
            close = [[ data['close']]],
            high  = [[ data['high']]],
            low   = [[ data['low']]],
            type='candlestick'
        ),
        [0],
        10 
    )

if __name__ == '__main__':
    threading.Thread(target=genData, daemon=True, args=(q,)).start()
    threading.Thread(target=run_server,daemon=True,args=(app,),kwargs={'port':5000}).start()
    

您收到的错误告诉您,您返回的字典中的键 'type' 不对应于一个长度等于数组中其他数组长度的值字典。基本上,解决方案是删除字典中的 'type' 键,您的回调应该会起作用。这是正确的代码,我在其中插入了解决方案的注释:

@app.callback(Output("graph", "extendData"), [Input("ws", "message")], [State("graph", "figure")])
def update_graph(msg, figure):    
    data = json.loads(msg['data'])['values']
    #removed 'type' key in dict below
    return (
        dict(
            x = [[ datetime.strptime(data['UPDATE_TIME'],'%H:%M:%S') ]],
            open  = [[ data['open'] ]],
            close = [[ data['close']]],
            high  = [[ data['high']]],
            low   = [[ data['low']]]
        ),
        [0],
        10 
    )

这是我成功使用的一个简单示例:

@app.callback(
    Output('indicators', 'extendData'),
    Input('live_interval', 'n_intervals')
)
def update_rates(n_intervals):
    #gather data into dict from dataframe
    new_data = candles[['time', 'high', 'low', 'open', 'close']].iloc[-1]
    new_data['time'] = new_data['time'] + delta*n_intervals
    new_data = new_data.to_dict()

    #data rename
    new_data['x'] = new_data['time']
    del new_data['time']

    #data reshape
    for k in new_data.keys():
        new_data[k] = [[new_data[k]]]

    return new_data, [1]