from dash import Dash, dcc, html, Input, Output import plotly.graph_objects as go import json from datetime import datetime, timedelta from ema_algo import Ema_Algo from api import fetch_chart_data_yahoo import pytz app = Dash(__name__) # pull stock data from json files # timestamps_file = open('timestamps.json', 'r') # timestamps_file_data = timestamps_file.read() # timestamps_raw = json.loads(timestamps_file_data) # timestamps = [datetime.datetime.fromtimestamp(t) for t in timestamps_raw] # prices_file = open('close_prices.json', 'r') # prices = json.loads(prices_file.read()) # intersection_indices = find_intersections(ema_5, ema_13, offset=13) # offset so don't calculate the SMA days # interpolated_intersections = [interpolate_intersection(indices, timestamps, ema_5, ema_13) for indices in intersection_indices] # intersected_x = [] # intersected_y = [] # for x,y in interpolated_intersections: # intersected_x.append(x) # intersected_y.append(y) app.layout = html.Div([ html.H4('Backtesting using the EMA method (5 vs 13) [ALPHA VERSION 0.0.2]'), html.Div( [ html.Label("Ticker ", htmlFor="ticker"), dcc.Input(id="ticker", value="SPY", type="text"), html.Br(), html.Label("Period ", htmlFor="period_dropdown"), dcc.Dropdown( id="period_dropdown", options=["1d","5d","1mo","3mo","6mo","1y","2y","5y","10y","ytd","max"], value = "1y"), html.Br(), html.Label("Interval ", htmlFor="interval_dropdown"), dcc.Dropdown( id="interval_dropdown", options=["1m", "2m", "5m", "15m", "30m", "60m", "90m", "1h", "4h", "1d", "5d", "1wk", "1mo", "3mo"], value = "1d", ), html.P(id='error_message'), ], id='input_params' ), html.Hr(), dcc.Graph(id="graph"), html.P("If bought and sold on these signals, the percent gain/loss would be:"), html.P(id="percent_gain") ]) @app.callback( Output("graph", "figure"), Output("percent_gain", "children"), Output("input_params", "style"), Output("error_message", "children"), Input("ticker", "value"), Input("period_dropdown", "value"), Input("interval_dropdown", "value") ) def display_color(ticker, period, interval): fd = open('bt-recent.json', 'r') raw_data = fd.read() trial_data = json.loads(raw_data) fd.close() chart_data = trial_data['chart_data'] backtest_results = trial_data['backtest_results'] url_params = trial_data['url_params'] percent_gain = backtest_results['percent_gain'] error_style = {"color" : "red"} error_message = "False error" # Code to execute no matter what (optional) raw_timestamps = chart_data['timestamps'] timestamps = [datetime.fromtimestamp(t).astimezone(pytz.timezone('US/Eastern')) for t in raw_timestamps] prices = chart_data['prices'] # test to see if graphc works, TODO make it abstracted algoEMA = Ema_Algo() algo_graph_data = backtest_results['algo_graph_data'] algo_graphs = algoEMA.export_graph(algo_graph_data) buy_indices = backtest_results['buy_indices'] sell_indices = backtest_results['sell_indices'] buy_prices, buy_times = [], [] for i in buy_indices: buy_prices.append(prices[i]) buy_times.append(timestamps[i]) sell_prices, sell_times = [], [] for i in sell_indices: sell_prices.append(prices[i]) sell_times.append(timestamps[i]) buy_sell_scatters = [ go.Scatter(name='Buys', x=buy_times, y=buy_prices, line=dict(color='rgb(0, 0, 255)'), mode='markers', marker_size=10), go.Scatter(name='Sells', x=sell_times, y=sell_prices, line=dict(color='rgb(255, 255, 0)'), mode='markers', marker_size=10) ] data = fetch_chart_data_yahoo('XRP-USD', '1m') times = [datetime.fromtimestamp(t).astimezone(pytz.timezone('US/Eastern')) for t in data['timestamps']] comp_scatter = go.Scatter(name='Price (yahoo)', x=times, y=data['prices'], line=dict(color='rgb(255, 0, 0)'), mode='lines') fig = go.Figure( data = [ go.Scatter(name='Price', x=timestamps, y=prices, line=dict(color='rgb(0, 0, 0)'), mode='lines'), comp_scatter ] # + algo_graphs + buy_sell_scatters , layout = go.Layout( title=go.layout.Title(text='Chart for ' + chart_data['name']), xaxis=go.layout.XAxis(title='Date (dt=' + url_params['interval'] + ', range=' + url_params['period'] + ')'), yaxis=go.layout.YAxis(title='Price ($)') ) ) return fig, percent_gain, error_style, error_message app.run(debug=True)