Search code examples
pythonplotplotlycandlestick-chart

Candlestick chart not supported by plotly Streaming API (python)


Problem

I am trying to do a candlestick chart displaying real-time data, using plotly with python. I am therefore using plotly's Streaming API. As an example, I simply adapted the example provided at this link.

Working code

import plotly.plotly as py
import plotly.tools as tls
from plotly.graph_objs import *

import numpy as np  
import datetime
import time

stream_ids = tls.get_credentials_file()['stream_ids']

# Get stream id from stream id list
stream_id = stream_ids[0]

# Make instance of stream id object
stream = Stream(
    token=stream_id,  
    maxpoints=80      
)

# Initialize trace of streaming plot by embedding the unique stream_id
trace1 = Candlestick(
    open=[],
    high=[],
    low=[],
    close=[],
    x=[],
    stream=stream         
)

data = Data([trace1])

# Add title to layout object
layout = Layout(title='CANDLE STICK CHART')

# Make a figure object
fig = Figure(data=data, layout=layout)

# Send fig to Plotly, initialize streaming plot, open new tab
unique_url = py.plot(fig, filename='s7_first-stream')

# Make instance of the Stream link object,
s = py.Stream(stream_id)

# Open the stream
s.open()

i = 0    # a counter
k = 5    # some shape parameter
N = 200  # number of points to be plotted

# Delay start of stream by 5 sec (time to switch tabs)
time.sleep(5)

while i<N:
    i += 1   # add to counter

    # Current time on x-axis, dummy data for the candlestick chart
    x = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')
    low = np.cos(k*i/50.)*np.cos(i/50.)+np.random.randn(1)
    close = low+1
    open = low +2
    high = low+3

    # Write to Plotly stream
    s.write(dict(x=x,
                 low=low,
                 close=close,
                 open=open,
                 high=high))

    # Write numbers to stream to append current data on plot,
    # Write lists to overwrite existing data on plot 

    time.sleep(0.08)  

# Close the stream when done plotting
s.close()

Output

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/plotly/plotly/plotly.py", line 632, in write
    tools.validate(stream_object, stream_object['type'])
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/plotly/tools.py", line 1323, in validate
    cls(obj)  # this will raise on invalid keys/items
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/plotly/graph_objs/graph_objs.py", line 377, in __init__
    self.__setitem__(key, val, _raise=_raise)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/plotly/graph_objs/graph_objs.py", line 428, in __setitem__
    raise exceptions.PlotlyDictKeyError(self, path)
plotly.exceptions.PlotlyDictKeyError: 'open' is not allowed in 'scatter'

Path To Error: ['open']

Valid attributes for 'scatter' at path [] under parents []:

    ['cliponaxis', 'connectgaps', 'customdata', 'customdatasrc', 'dx',
    'dy', 'error_x', 'error_y', 'fill', 'fillcolor', 'hoverinfo',
    'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertext', 'hovertextsrc',
    'ids', 'idssrc', 'legendgroup', 'line', 'marker', 'mode', 'name',
    'opacity', 'r', 'rsrc', 'showlegend', 'stream', 't', 'text',
    'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'tsrc',
    'type', 'uid', 'visible', 'x', 'x0', 'xaxis', 'xcalendar', 'xsrc', 'y',
    'y0', 'yaxis', 'ycalendar', 'ysrc']

Run `<scatter-object>.help('attribute')` on any of the above.
'<scatter-object>' is the object at []

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/Louis/PycharmProjects/crypto_dashboard/Data_gathering/candlestick_stream_test.py", line 79, in <module>
    high=high))
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/site-packages/plotly/plotly/plotly.py", line 640, in write
    "invalid:\n\n{1}".format(stream_object['type'], err)
plotly.exceptions.PlotlyError: Part of the data object with type, 'scatter', is invalid. This will default to 'scatter' if you do not supply a 'type'. If you do not want to validate your data objects when streaming, you can set 'validate=False' in the call to 'your_stream.write()'. Here's why the object is invalid:

'open' is not allowed in 'scatter'

Path To Error: ['open']

Valid attributes for 'scatter' at path [] under parents []:

    ['cliponaxis', 'connectgaps', 'customdata', 'customdatasrc', 'dx',
    'dy', 'error_x', 'error_y', 'fill', 'fillcolor', 'hoverinfo',
    'hoverinfosrc', 'hoverlabel', 'hoveron', 'hovertext', 'hovertextsrc',
    'ids', 'idssrc', 'legendgroup', 'line', 'marker', 'mode', 'name',
    'opacity', 'r', 'rsrc', 'showlegend', 'stream', 't', 'text',
    'textfont', 'textposition', 'textpositionsrc', 'textsrc', 'tsrc',
    'type', 'uid', 'visible', 'x', 'x0', 'xaxis', 'xcalendar', 'xsrc', 'y',
    'y0', 'yaxis', 'ycalendar', 'ysrc']

Run `<scatter-object>.help('attribute')` on any of the above.
'<scatter-object>' is the object at []

It looks like my trace has been interpreted as a data object of type 'Scatter' instead of 'Candlestick'. That would explain why the 'open' attribute is not allowed.

Is the streaming API supported by Candlestick objects or I'm missing something?

Thank you!


Solution

  • In your while loop, you should add the key type='candlestick' to the dict passed to write:

    s.write(dict(type='candlestick',
        x=x,
        low=low,
        close=close,
        open=open,
        high=high))
    

    It works similarly for all the plotly.graph_objs traces accepting a stream attribute.