Problem using Date picker range

I am trying to build a web app for practice with Dash where it takes input as a start_date & end_date from a Dataframe of SPY, and shows cumulative returns in a form of line-graph & gauge.

it shows error as TypeError: Invalid comparison between dtype=datetime64[ns] and str.

I would appreciate any help,PS: I still need to code for gauge output, but its showing me error with graph output as well.

Here’s my code:

import pandas as pd
import plotly.express as px
import seaborn as sns
import matplotlib.pyplot as plt
import datetime as dt
import yfinance as yf

spy = yf.download("SPY", start= "2000-01-01", end = "2023-12-05")
spy = spy.reset_index()


from dash import Dash, html, dcc
import dash_daq as daq
from dash.dependencies import Output, Input
from dash.exceptions import PreventUpdate
import dash_bootstrap_components as dbc
from dash_bootstrap_templates import load_figure_template

load_figure_template("SLATE")

app = Dash(__name__,external_stylesheets=[dbc.themes.SLATE])

app.layout = html.Div([
        dbc.Row([html.H1("SPY Returns during dates selected", style = {'text-align': 'center'})]),
        
        #html.Br,
    
        dbc.Row([
                dbc.Col([
                    dcc.DatePickerRange(
                        id = "date_picker",
                        min_date_allowed = spy["Date"].min(),
                        max_date_allowed = spy["Date"].max(),
                        initial_visible_month = spy["Date"].min(),
                        start_date = spy["Date"].min(),
                        end_date = spy["Date"].max())
                ]), 
                dbc.Col([
                    html.Div([
                        html.H3("Total Returns"),
                        daq.Gauge(
                            id = "Our Gauge",
                            label = "Returns",
                            value = 100,
                            color={"gradient":True,"ranges":{"green":[0,6],"yellow":[6,8],"red":[8,10]}},
                            labelPosition = "bottom")
                        
                        
                        
                    ])
                ]),
            dbc.Row([
                html.Div([
                    html.H3("Graph showing the returns"),
#                     html.Br,
                    dcc.Graph(id = 'Graph'),
                ])
            ])
                            
        ])
    
])

@app.callback(
        [Output("Our Gauge","Gauge")], 
        [Output("Graph", "figure")],
        [Input("date_picker", "start_date"),Input("date_picker", "end_date")]
         )
def plot_graph(start_date, end_date):
    
    df = spy[spy["Date"].between("start_date","end_date")]
    df["returns"] = df["Adj Close"].pct_change(1)
    df["cum_returns"] = (1 + df["returns"].cumprod())*100
                 
    figure = px.line(df,
                     x = df["Date"],
                     y = df["cum_returns"])
    return figure               



if __name__ == "__main__":
    app.run(debug = True, port = 2022)

Hey @puns,

Welcome to the community!

Seems like you need to change the data type of your Date column from str to datetimeobject. SinceI do not know the format of your Date column, I can’t help you directly, but it is something can be found on Google easily!

Cheers!

Also, may I ask you to reformat your code snippet by simply selecting all of the code and press control/command + e. It would increase the readability of your code so that not only your chance of getting instant help would increase but also others who may have same issue get help from your post easily :slight_smile:

1 Like

Thanks for your reply, it does show as datetime64[ns] type for the date column

As you have said I will try to format code before posting, I am new to all of this ! lol

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6019 entries, 0 to 6018
Data columns (total 7 columns):
Column     Non-Null Count  Dtype         
---  ------     --------------  -----         
 0   Date       6019 non-null   datetime64[ns]
 1   Open       6019 non-null   float64       
 2   High       6019 non-null   float64       
 3   Low        6019 non-null   float64       
 4   Close      6019 non-null   float64       
 5   Adj Close  6019 non-null   float64       
 6   Volume     6019 non-null   int64

dtypes: datetime64ns, float64(5), int64(1)

Could you please reformat your code in your question so that I can help you. As you can tell it is way complicated as it is…

I just reformatted the code, thanks

There is a small typo here! Could you please change "between("start_date", "end_date") with "between(start_date, end_date)

I corrected the typo, but now I get this error :weary:


SchemaTypeValidationError: Schema: [<Output `Our Gauge.Gauge`>, <Output `Graph.figure`>]
                Path: ()
                Expected type: (<class 'tuple'>, <class 'list'>)
                Received value of type <class 'plotly.graph_objs._figure.Figure'>:

I guess you need to do something in the line of below, but for sure need to change coding little bit.Because, I am not sure what is your main goal with it. Nevertheless, it is a good example how to utilize it, I believe…

@app.callback(
        [Output("Our Gauge","Gauge")], 
        [Output("Graph", "figure")],
        [Input("date_picker", "start_date"),Input("date_picker", "end_date")]
         )
def plot_graph(start_date, end_date):
    
    df = spy[spy["Date"].between(start_date,end_date)]
    #pct_change = (df['Close'].iloc[-1]-df['Close'].iloc[0])/df['Close'].iloc[0]*100
    df["returns"] = df["Adj Close"].pct_change(1)
    df["cum_returns"] = (1 + df["returns"].cumprod())*100
    pct_return = df["cum_returns"].iloc[-1]-df["cum_returns"].iloc[0]

                 
    figure = px.line(df,
                     x = df["Date"],
                     y = df["cum_returns"])
    
    return  pct_return, figure      

Thank you very much for your help. I was just trying to practice to some idea I had lol