问题描述
我正在尝试通过扩展接收新数据但它不起作用来从实时数据流中绘制烛台。目前通过检查 chrome 的 DevTool 控制台,它显示以下错误 -
Error: attribute type must be an array of length equal to indices array length
下面是我的代码。它使用 dash 扩展库来接收数据而不是使用间隔,因为同时实际程序也会更新一个滴答流。
我推测它要么与绘图烛台数据格式有关,要么只是 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,args=(app,),kwargs={'port':5000}).start()
解决方法
您收到的错误告诉您,您返回的字典中的键“类型”与长度等于字典中其他数组长度的数组的值不对应。基本上,解决方案是删除字典中的关键“类型”,您的回调应该可以工作。这是正确的代码,我在其中插入了解决方案的注释:
@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]