import dash_bootstrap_components as dbc from dash import Dash, dcc, html, Input, Output from dash_ag_grid import AgGrid from dash_bootstrap_templates import load_figure_template from datetime import datetime from flask_caching import Cache from pandas import DataFrame, Series from plotting import CandlestickChart, figure_with_subplots from daily_data import get_daily_data from signals import calculate_signals from stylesheets import grid_stylesheet, theme_stylesheet app = Dash(__name__, external_stylesheets = [theme_stylesheet, grid_stylesheet]) app.title = 'Swing Trading Dashboard' cache = Cache(app.server, config = { 'CACHE_TYPE': 'SimpleCache', 'CACHE_DEFAULT_TIMEOUT': 60 # Seconds. }) load_figure_template('lux_dark') def load_chart(data: DataFrame) -> dict: chart_data = data.tail(180) candlestick_chart = CandlestickChart( x = chart_data['Date'], opens = chart_data['Open'], highs = chart_data['High'], lows = chart_data['Low'], closes = chart_data['Close'] ) return figure_with_subplots([[candlestick_chart]]) @cache.cached(timeout = 60, key_prefix = 'get_daily_data') def get_cached_data(): return get_daily_data('SPY') @cache.cached(timeout = 60, key_prefix = 'calculate_signals') def get_cached_signals(): data = get_cached_data() return calculate_signals(data) @cache.cached(timeout = 60, key_prefix = 'load_chart') def get_cached_chart(): data = get_cached_data() return load_chart(data) app.layout = dbc.Container( [ dcc.Interval( id = 'refresh-interval', interval = 60 * 1000, # Milliseconds. n_intervals = 0 ), dcc.Graph( id = 'candlestick-chart', config = {'displayModeBar': False}, figure = figure_with_subplots([[CandlestickChart( x = Series(datetime.today()), opens = Series(), highs = Series(), lows = Series(), closes = Series(), title = '' )]]) ), html.Div( AgGrid( id = 'signal-table', columnDefs = [{'field': 'Strategy', 'flex': 3}], rowData = [], defaultColDef = {'flex': 1, 'sortable': False, 'resizable': False}, dashGridOptions = { 'domLayout': 'autoHeight', 'pagination': True, 'paginationPageSizeSelector': False, 'paginationPageSize': 10, }, style = {'height': None} ), className = 'dbc dbc-ag-grid' ) ], style = {'maxWidth': '1200px', 'margin': '0 auto'}, fluid = True ) @app.callback( [ Output('candlestick-chart', 'figure'), Output('signal-table', 'columnDefs'), Output('signal-table', 'rowData') ], Input('refresh-interval', 'n_intervals') ) def update_dashboard(_): signal_data = get_cached_signals() chart_figure = get_cached_chart() column_defs = [ {'field': col, 'flex': 3} if col == 'Strategy' else {'field': col, 'flex': 1, 'cellRenderer': 'SignalRenderer'} for col in signal_data.columns ] return chart_figure, column_defs, signal_data.to_dict(orient = 'records') if __name__ == '__main__': app.run_server(debug = False)