Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Plotly: How to style a plotly figure so that it doesn't display gaps for missing dates?

I have a plotly graph of the EUR/JPY exchange rate across a few months in 15 minute time intervals, so as a result, there is no data from friday evenings to sunday evenings.

Here is a portion of the data, note the skip in the index (type: DatetimeIndex) over the weekend: enter image description here

Plotting this data in plotly results in a gap over the missing dates Using the dataframe above:

import plotly.graph_objs as go
candlesticks = go.Candlestick(x=data.index, open=data['Open'], high=data['High'],
                   low=data['Low'], close=data['Close'])
fig = go.Figure(layout=cf_layout)
fig.add_trace(trace=candlesticks)
fig.show()

Ouput:

enter image description here

As you can see, there are gaps where the missing dates are. One solution I've found online is to change the index to text using:

data.index = data.index.strftime("%d-%m-%Y %H:%M:%S")

and plotting it again, which admittedly does work, but has it's own problem. The x-axis labels look atrocious:

enter image description here

I would like to produce a graph that plots a graph like in the second plot where there are no gaps, but the x-axis is displayed like as it is on the first graph. Or at least displayed in a much more concise and responsive format, as close to the first graph as possible.

Thank you in advance for any help!

like image 701
Adnan Siddiquei Avatar asked Apr 21 '20 14:04

Adnan Siddiquei


2 Answers

Just in case someone here wants to remove gaps for outside trading hours and weekends, As shown below, using rangebreaks is the way to do it.

    fig = go.Figure(data=[go.Candlestick(x=df['date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'])])
    fig.update_xaxes(
        rangeslider_visible=True,
        rangebreaks=[
            # NOTE: Below values are bound (not single values), ie. hide x to y
            dict(bounds=["sat", "mon"]),  # hide weekends, eg. hide sat to before mon
            dict(bounds=[16, 9.5], pattern="hour"),  # hide hours outside of 9.30am-4pm
            # dict(values=["2020-12-25", "2021-01-01"])  # hide holidays (Christmas and New Year's, etc)
        ]
    )
    fig.update_layout(
        title='Stock Analysis',
        yaxis_title=f'{symbol} Stock'
    )

    fig.show()

here's Plotly's doc.

like image 60
Mega J Avatar answered Oct 21 '22 22:10

Mega J


Even if some dates are missing in your dataset, plotly interprets your dates as date values, and shows even missing dates on your timeline. One solution is to grab the first and last dates, build a complete timeline, find out which dates are missing in your original dataset, and include those dates in:

fig.update_xaxes(rangebreaks=[dict(values=dt_breaks)])

This will turn this figure:

enter image description here

Into this:

enter image description here

Complete code:

import plotly.graph_objects as go
from datetime import datetime
import pandas as pd
import numpy as np

# sample data
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')

# remove some dates to build a similar case as in the question
df = df.drop(df.index[75:110])
df = df.drop(df.index[210:250])
df = df.drop(df.index[460:480])

# build complete timepline from start date to end date
dt_all = pd.date_range(start=df['Date'].iloc[0],end=df['Date'].iloc[-1])

# retrieve the dates that ARE in the original datset
dt_obs = [d.strftime("%Y-%m-%d") for d in pd.to_datetime(df['Date'])]

# define dates with missing values
dt_breaks = [d for d in dt_all.strftime("%Y-%m-%d").tolist() if not d in dt_obs]

# make fiuge
fig = go.Figure(data=[go.Candlestick(x=df['Date'],
                open=df['AAPL.Open'], high=df['AAPL.High'],
                low=df['AAPL.Low'], close=df['AAPL.Close'])
                      ])

# hide dates with no values
fig.update_xaxes(rangebreaks=[dict(values=dt_breaks)])

fig.update_layout(yaxis_title='AAPL Stock')

fig.show()
like image 38
vestland Avatar answered Oct 21 '22 20:10

vestland