Search code examples
pythonpython-3.xplotly

How to avoid collapse of plotly-candle graphs


I used make_subplots of plotly for generating multiple candle graphs, but graphs were collapsed by x-range slider. I would like to know:

  1. How to get rid of ALL x-range slider. My implementation still yields x-range slide although fig.update_layout(xaxis_rangeslider_visible=False) is in it.
  2. How to make not-collapsed graphs with x-range slider. If you comment out fig.update_layout(xaxis_rangeslider_visible=False), you can find x-range slider destroy a graph above.

Please execute test_candle(graph_type="candle") for reprodicing collapsed graph. test_candle(graph_type="line") will show you not-collapsed example(and not-candle type).

def test_candle(graph_type="candle"):
    import pandas as pd
    import plotly.offline as offline
    import plotly.graph_objs as go
    from plotly.subplots import make_subplots
    
    col_N = 3 # max columns
    N = 7 # a number of graphs
    
    # sample data
    df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
    
    # calculate a (row, col) coordinate of the x-th graph.
    func = lambda x : ((x + (col_N-1)) // col_N, (x - 1) % col_N + 1)
    fig = make_subplots(
        rows=N // col_N + N % col_N, 
        cols=col_N,
        subplot_titles=[f"graph {i}" for i in range(1, N+1)]
    )
    row0, col0 = func(N)
    fig.update_layout(width = 1000*col_N)
    fig.update_layout(height = 1000*row0)
    fig.update_layout(xaxis_rangeslider_visible=False)
    for i in range(1, N+1):
        if graph_type == "candle":
            graph = go.Candlestick(
                x=df["Date"],
                open=df["AAPL.Open"],
                high=df["AAPL.High"],
                low=df["AAPL.Low"],
                close=df["AAPL.Close"]
            )
        elif graph_type == "line":
            graph = go.Line(x=df["Date"],y=df["AAPL.Close"])
        else:
            raise ValueError("Invalid graph type : {}".format(graph_type))
        row1, col1 = func(i)
        fig.add_trace(graph, row=row1, col=col1)
    offline.plot(fig, filename = 'sample-candle.html', auto_open=True)

Solution

  • The x-range sliders are destroying the graph because they overlap with the subplots.

    1. Remove all x-range sliders - Using fig.update_layout(xaxis_rangeslider_visible=False) will only apply to the 1st subplot, the rest of the subplots will still have the x-range sliders. To disable for all, use fig.update_xaxes(rangeslider_visible=False).
    2. Readable graph with x-range slider - Reducing the thickness of the slider will make it fit between the vertical space of the graphs: fig.update_xaxes(rangeslider_thickness = 0.04). To increase the thickness, we have to increase the vertical spacing between graphs, done with vertical_spacing in make_subplots().
    def test_candle(graph_type="candle"):
        import pandas as pd
        import plotly.offline as offline
        import plotly.graph_objs as go
        from plotly.subplots import make_subplots
        
        col_N = 3 # max columns
        N = 7 # a number of graphs
        
        # sample data
        df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv')
        
        # calculate a (row, col) coordinate of the x-th graph.
        func = lambda x : ((x + (col_N-1)) // col_N, (x - 1) % col_N + 1)
        fig = make_subplots(
            rows=N // col_N + N % col_N, 
            cols=col_N,
            subplot_titles=[f"graph {i}" for i in range(1, N+1)],
            # Adjust this along with rangeslider_thickness to get a nice graph *with* x-range sliders
            vertical_spacing = 0.15
        )
        row0, col0 = func(N)
        fig.update_layout(width = 1000*col_N)
        fig.update_layout(height = 1000*row0)
        
        # Disable x-range sliders by uncommenting the next line!
        # fig.update_xaxes(rangeslider_visible=False)
        # Adjust this along with vertical_spacing to get a nice graph *with* x-range sliders
        fig.update_xaxes(rangeslider_thickness = 0.04)
        
        for i in range(1, N+1):
            if graph_type == "candle":
                graph = go.Candlestick(
                    x=df["Date"],
                    open=df["AAPL.Open"],
                    high=df["AAPL.High"],
                    low=df["AAPL.Low"],
                    close=df["AAPL.Close"]
                )
            elif graph_type == "line":
                graph = go.Line(x=df["Date"],y=df["AAPL.Close"])
            else:
                raise ValueError("Invalid graph type : {}".format(graph_type))
            row1, col1 = func(i)
            fig.add_trace(graph, row=row1, col=col1)
        offline.plot(fig, filename = 'sample-candle.html', auto_open=True)