Search code examples
python-3.xplotly

Remove dt_breaks from a plotly graph


I would like to plot a ohlc graph removing the gaps (rangebreaks) with no data at different intervals. Program works well when using daily intervals but I am unable to remove the gaps when using other intervals (1h,30min), process is more or less the same, but only shows the first day.

First I thought it was a datetime format issue but removing "rangebreaks" allows to plot all series.

Any suggestion?

Thanks in advance

import warnings
import pandas as pd
from datetime import datetime
from dateutil.relativedelta import relativedelta
import numpy as np
import plotly.io as pio
from plotly.subplots import make_subplots
import plotly
import plotly.graph_objects as go
import yfinance as yf
#pio.renderers.default = "browser"
warnings.filterwarnings('ignore')

t_var = ['META']
end = datetime.now()
start = end - relativedelta(days=59)
df_y = yf.download(t_var, start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d'), interval= "30m")
d = df_y.index[0]
b = df_y.index[-1]

dt_all = pd.date_range(start=d,end=b,freq='30min')
dt_breaks = [d for d in dt_all if not d in df_y.index]
fig = make_subplots(rows=1, cols=1)
fig.add_ohlc(x=df_y.index, open=df_y['Open'], high=df_y['High'], low=df_y['Low'], close=df_y['Close'],name='stock',decreasing_line_color='#21201f', increasing_line_color='#21201f', row=1, col=1)
fig.update_xaxes(showgrid=False, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=False,rangebreaks=[dict(values=dt_breaks)], rangeslider_visible=False)
#fig.update_xaxes(showgrid=False, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=False,rangeslider_visible=False)
fig.show()

Solution

  • Market holidays that cannot be handled by rangebreak functionality alone can be handled by adding the target period to rangebreak, but the specification did not work. rangebreak=[dict(bounds=['sat','mon']),dict(bounds=[16,9], pattern='hour'),dict(value=['2023-06-17','2023-06-19'])] Another approach is to add the current index to the index of 30-minute intervals from the start date to the end date, and extract only the non-overlapping indexes. That extraction is then given to rangebreak. At this time, the base value of dvalue for rangebreak is 86400000msec (1000msec*60sec*60min *24h), so we set it to 1800000 (1000msec*60sec*30min).

    t_var = ['META']
    end = datetime.now()
    start = end - relativedelta(days=59)
    df_y = yf.download(t_var, start=start.strftime('%Y-%m-%d'), end=end.strftime('%Y-%m-%d'), interval= "30m")
    
    d = df_y.index[0]
    b = df_y.index[-1]
    
    dt_all = pd.date_range(start=d,end=b,freq='30min')
    
    marged_index = dt_all.append(df_y.index)
    timegap = marged_index[~marged_index.duplicated(keep = False)]
    
    fig = make_subplots(rows=1, cols=1)
    fig.add_ohlc(x=df_y.index,
                 open=df_y['Open'],
                 high=df_y['High'],
                 low=df_y['Low'],
                 close=df_y['Close'],
                 name='stock',
                 decreasing_line_color='#21201f',
                 increasing_line_color='#21201f',
                 row=1, col=1)
    fig.update_xaxes(showgrid=False,
                     zeroline=False,
                     showticklabels=True,
                     showspikes=True,
                     spikemode='across',
                     spikesnap='cursor',
                     showline=False,
                     rangebreaks=[
                         dict(values=timegap, dvalue=1800000), # 30min:1000msec*60sec*30min
                     ],
                     rangeslider_visible=False)
    fig.show()
    

    enter image description here