diff --git a/finance.py b/finance.py index 4491ad2..357dec4 100755 --- a/finance.py +++ b/finance.py @@ -6,7 +6,11 @@ import plotly.express as px import yfinance as yf from dash.dependencies import Input, Output import plotly.graph_objects as go +import numpy as np import pandas as pd +import datetime +import time + # Load data stock_list = ['MMM', 'ABT', 'ABBV', 'ABMD', 'ACN', 'ATVI', 'ADBE', 'AMD', 'AAP', 'AES', 'AFL', 'A', 'APD', 'AKAM', 'ALK', 'ALB', 'ARE', 'ALXN', 'ALGN', 'ALLE', 'LNT', 'ALL', 'GOOGL', 'GOOG', 'MO', 'AMZN', 'AMCR', 'AEE', @@ -57,6 +61,7 @@ to_time = None # Initialize the app app = dash.Dash(__name__) app.config.suppress_callback_exceptions = True +stock_info_in_time_period_df = pd.DataFrame(columns=stock_list, index=["średnia", "cena", "dywidenda", "wolatylność"]) def make_gauge(title, min_v, value, max_v): @@ -116,7 +121,15 @@ app.layout = html.Div( style={'color': '#1E1E1E'}), html.P('Wybierz przedział czasu by policzyć średnie i wachania'), dcc.Graph(id='average_gauge'), - dcc.Graph(id='volatility_gauge') + dcc.Graph(id='volatility_gauge'), + dash_table.DataTable( + id='info_in_time_period', + style_header={'backgroundColor': 'rgb(30, 30, 30)'}, + style_cell={ + 'backgroundColor': 'rgb(50, 50, 50)', + 'color': 'white' + }, + ) ]), html.Div(className='eight columns div-for-charts bg-grey', children=[ @@ -159,21 +172,55 @@ def update_table(selected_dropdown_value): return data, columns -@app.callback([Output('average_gauge', 'figure'), Output('volatility_gauge', 'figure')], +average_gauge = make_gauge('średnia', 0, 0, 400) +volatility_gauge = make_gauge('wolatylność', 0, 0, 400) + + +def round_to_nearest_weekday(date): + if isinstance(date,pd.Timestamp): + if date.dayofweek > 5: + date += datetime.timedelta(days=8-date.dayofweek) + assert date.dayofweek <= 5 + return date + elif isinstance(date, str): + if '.' in date: + date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S.%f") + elif ':' in date: + date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S") + else: + date = datetime.datetime.strptime(date, "%Y-%m-%d") + if date.isoweekday() > 5: + date += datetime.timedelta(days=8-date.isoweekday()) + assert date.isoweekday() <= 5 + return date + + +@app.callback([Output('average_gauge', 'figure'), + Output('volatility_gauge', 'figure'), + Output('info_in_time_period', 'data')], Input('timeseries', 'relayoutData')) def change_time_period(selectedData): global from_time global to_time + global average_gauge + global volatility_gauge + global stock_info_in_time_period_df if selectedData is not None: - if selectedData.get('autosize'): - from_time = selected_stock_in_table_df.index.min() - to_time = selected_stock_in_table_df.index.max() - else: + if "xaxis.range[0]" in selectedData and "xaxis.range[1]" in selectedData: from_time = selectedData["xaxis.range[0]"] to_time = selectedData["xaxis.range[1]"] - average_gauge = make_gauge('średnia', 0, 290, 400) - volatility_gauge = make_gauge('wolatylność', 0, 133, 400) - return average_gauge, volatility_gauge + else: + from_time = selected_stock_in_table_df.index.min() + to_time = selected_stock_in_table_df.index.max() + from_time = round_to_nearest_weekday(from_time) + to_time = round_to_nearest_weekday(to_time) + time_period = selected_stock_in_table_df.loc[from_time:to_time] + mean = time_period.mean(axis=0) + std = time_period.std(axis=0) + # TODO: oblicz stock_info_in_time_period_df tutuaj !!! + average_gauge = make_gauge('średnia', 0, mean['Close'], 400) + volatility_gauge = make_gauge('wolatylność', 0, std['Close'], 400) + return average_gauge, volatility_gauge, stock_info_in_time_period_df.T.to_dict('records') if __name__ == '__main__':