Search code examples
pythoncolorsplotly

plotly (python) linechart with changing color


I am looking for a solution to create a plotly linechart, build with go.Scattter like this example:

enter image description here

what i already tried:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import yfinance as yf

df = yf.download("AAPL MSFT", start="2022-01-01", end="2022-07-01", group_by='ticker')
df.reset_index(inplace=True)

title = 'Price over time'

fig = make_subplots(rows=1, cols=1,
                    vertical_spacing=0.05,
                    shared_xaxes=True,
                    subplot_titles=(title, ""))

# AAPL
fig.add_trace(go.Scatter(x=df['Date'],
                         y=df[('AAPL', 'Close')],

                         marker_color=df[('AAPL', 'Close')].apply(
                             lambda x: 'green'
                             if 120 <= x <= 150 else 'red'
                             if 151 <= x <= 170 else 'yellow'
                             if 171 <= x <= 190 else 'blue'),

                         mode='lines+markers',
                         showlegend=True,
                         name="AAPL",
                         stackgroup='one'),
              row=1,
              col=1,
              secondary_y=False)

fig.show()

I expect a solution with go.Scatter. The code provided is only a part of the solution, and I would like to add subplots. The colors used should depend on the value of the y-axis (e.g. 'Close' in this case). Two colors are possible; for example, the higher the price, the more green the color. It may be necessary to create an additional column with color codes first.


Solution

  • As a requirement, the graph cannot be created in a batch because of the color coding by price on the y-axis and y-axis. Draw markers and lines for each period and use the fill function.

    Code summary:

    • Only the closing price is used to obtain stock prices.
    • Adding a new column of color names in the condition of color-coding by category value.
    • Extraction of market holidays (difference from time series list created with period minimum and maximum values)

    Change the color of the outer circle because the markers are the same color. Change to subtitle and name title.

    import pandas as pd
    import plotly.graph_objects as go
    from plotly.subplots import make_subplots
    import yfinance as yf
    
    df = yf.download("AAPL MSFT", start="2022-01-01", end="2022-07-01", group_by='column')['Close']
    df.index = pd.to_datetime(df.index)
    df.index = df.index.tz_localize(None)
    df.reset_index(inplace=True)
    
    # color column add
    df['MSFT_color'] = df['MSFT'].apply(lambda x: 'green'
                     if 240 <= x <= 270 else 'red'
                     if 271 <= x <= 300 else 'yellow'
                     if 301 <= x <= 330 else 'blue')
    
    df['AAPL_color'] = df['AAPL'].apply(lambda x: 'green'
                     if 120 <= x <= 150 else 'red'
                     if 151 <= x <= 170 else 'yellow'
                     if 171 <= x <= 190 else 'blue')
    
    date_diff = set(pd.date_range(df['Date'].min(), df['Date'].max(), freq='1d').date.tolist()) ^ set(df['Date'].dt.date)
    
    title = 'Price over time'
    
    fig = make_subplots(rows=2, cols=1,
                        vertical_spacing=0.10,
                        shared_xaxes=True,
                        subplot_titles=('AAPL', 'MSFT'))
    
    for i in range(len(df)-1):
        fig.add_trace(go.Scatter(x=[df.loc[i,'Date'], df.loc[i+1,'Date']],
                                 y=[df.loc[i,'AAPL'], df.loc[i+1,'AAPL']],
                                 name='AAPL',
                                 mode='lines+markers',
                                 marker=dict(size=4,line=dict(width=1, color='DarkSlateGrey')),
                                 line_color=df.loc[i,'AAPL_color'],
                                 fill='tozeroy',
                                 fillcolor=df.loc[i,'AAPL_color'],
                                 showlegend=False
                            ), row=1, col=1, secondary_y=False)
        
        fig.add_trace(go.Scatter(x=[df.loc[i,'Date'], df.loc[i+1,'Date']],
                                 y=[df.loc[i,'MSFT'], df.loc[i+1,'MSFT']],
                                 name='MSFT',
                                 mode='lines+markers',
                                 marker=dict(size=4,line=dict(width=1, color='DarkSlateGrey')),
                                 line_color=df.loc[i,'MSFT_color'],
                                 fill='tozeroy',
                                 fillcolor=df.loc[i,'MSFT_color'],
                                 showlegend=False
                            ), row=2, col=1, secondary_y=False)
        
        
        
    fig.update_xaxes(
        rangebreaks=[
            dict(values=list(date_diff))
        ]
    )
    fig.update_layout(title=title)
    fig.show()
    

    enter image description here