Compare commits
No commits in common. "master" and "file-styles-new-graph" have entirely different histories.
master
...
file-style
@ -645,7 +645,7 @@ a {
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tab-1, #tab-2, #tab-3{
|
#tab-1, #tab-2{
|
||||||
background-color: #1E1E1E;
|
background-color: #1E1E1E;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-left: none;
|
border-left: none;
|
||||||
@ -655,10 +655,4 @@ a {
|
|||||||
|
|
||||||
.tab--selected{
|
.tab--selected{
|
||||||
background-color: #111111 !important;
|
background-color: #111111 !important;
|
||||||
}
|
|
||||||
|
|
||||||
#company-desritpion{
|
|
||||||
padding: 3rem 1rem;
|
|
||||||
margin: 0;
|
|
||||||
background-color: #111111;
|
|
||||||
}
|
}
|
166
finance.py
166
finance.py
@ -10,9 +10,6 @@ import numpy as np
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
import datetime
|
import datetime
|
||||||
import time
|
import time
|
||||||
from pandas_datareader import data
|
|
||||||
import requests
|
|
||||||
from bs4 import BeautifulSoup
|
|
||||||
|
|
||||||
# Load data
|
# Load data
|
||||||
stock_list = ['MMM', 'ABT', 'ABBV', 'ABMD', 'ACN', 'ATVI', 'ADBE', 'AMD', 'AAP', 'AES', 'AFL', 'A', 'APD', 'AKAM',
|
stock_list = ['MMM', 'ABT', 'ABBV', 'ABMD', 'ACN', 'ATVI', 'ADBE', 'AMD', 'AAP', 'AES', 'AFL', 'A', 'APD', 'AKAM',
|
||||||
@ -53,7 +50,6 @@ stock_list = ['MMM', 'ABT', 'ABBV', 'ABMD', 'ACN', 'ATVI', 'ADBE', 'AMD', 'AAP',
|
|||||||
stock_list = ['WHR', 'WMB', 'WLTW', 'WYNN', 'XEL', 'XLNX', 'XYL', 'YUM', 'ZBRA', 'ZBH', 'ZION', 'ZTS']
|
stock_list = ['WHR', 'WMB', 'WLTW', 'WYNN', 'XEL', 'XLNX', 'XYL', 'YUM', 'ZBRA', 'ZBH', 'ZION', 'ZTS']
|
||||||
|
|
||||||
tickerData = yf.Tickers(stock_list)
|
tickerData = yf.Tickers(stock_list)
|
||||||
market_cap = data.get_quote_yahoo(stock_list)['marketCap']
|
|
||||||
fullTableDf = tickerData.history(period='1d', start='2019-1-1', end='2020-1-25')
|
fullTableDf = tickerData.history(period='1d', start='2019-1-1', end='2020-1-25')
|
||||||
closePrices = fullTableDf['Close']
|
closePrices = fullTableDf['Close']
|
||||||
selected_stocks_in_graph = [stock_list[0]]
|
selected_stocks_in_graph = [stock_list[0]]
|
||||||
@ -65,13 +61,7 @@ to_time = None
|
|||||||
# Initialize the app
|
# Initialize the app
|
||||||
app = dash.Dash(__name__)
|
app = dash.Dash(__name__)
|
||||||
app.config.suppress_callback_exceptions = True
|
app.config.suppress_callback_exceptions = True
|
||||||
stock_info_in_time_period_df = pd.DataFrame(index=stock_list, columns=["tracker", "średnia", "cena"])
|
stock_info_in_time_period_df = pd.DataFrame(columns=stock_list, index=["średnia", "cena", "dywidenda", "wolatylność"])
|
||||||
stock_info_in_time_period_df['tracker'] = stock_info_in_time_period_df.index
|
|
||||||
|
|
||||||
mean_prices_and_dividends = fullTableDf[['Close', 'Dividends']].mean(axis=0).unstack(level=0)
|
|
||||||
mean_prices_and_dividends_and_market_cap = pd.concat([mean_prices_and_dividends, market_cap], axis=1)
|
|
||||||
mean_prices_and_dividends_figure = px.scatter(mean_prices_and_dividends_and_market_cap.reset_index(), size="marketCap",
|
|
||||||
x='Dividends', y='Close', text="index", template='plotly_dark')
|
|
||||||
|
|
||||||
|
|
||||||
def make_gauge(title, min_v, value, max_v):
|
def make_gauge(title, min_v, value, max_v):
|
||||||
@ -121,14 +111,14 @@ app.layout = html.Div(
|
|||||||
html.Div(
|
html.Div(
|
||||||
className='div-for-dropdown',
|
className='div-for-dropdown',
|
||||||
children=[
|
children=[
|
||||||
dcc.Dropdown(id='table_selector',
|
dcc.Dropdown(id='table_selector',
|
||||||
options=get_options(stock_list),
|
options=get_options(stock_list),
|
||||||
multi=False, value=selected_stock_in_table,
|
multi=False, value=selected_stock_in_table,
|
||||||
style={'backgroundColor': '#1E1E1E'},
|
style={'backgroundColor': '#1E1E1E'},
|
||||||
className='stockselector'
|
className='stockselector'
|
||||||
),
|
),
|
||||||
html.Button("Pobierz dane", id="btn_data", style={'margin-top': '3rem'}),
|
html.Button("Pobierz dane", id="btn_data",style={'margin-top': '3rem'}),
|
||||||
dcc.Download(id="download-data")
|
dcc.Download(id="download-data")
|
||||||
|
|
||||||
],
|
],
|
||||||
style={'color': '#1E1E1E'}),
|
style={'color': '#1E1E1E'}),
|
||||||
@ -141,45 +131,22 @@ app.layout = html.Div(
|
|||||||
]),
|
]),
|
||||||
dash_table.DataTable(
|
dash_table.DataTable(
|
||||||
id='info_in_time_period',
|
id='info_in_time_period',
|
||||||
columns=[{"name": i, "id": i} for i in stock_info_in_time_period_df.columns],
|
|
||||||
style_header={'backgroundColor': 'rgb(30, 30, 30)'},
|
style_header={'backgroundColor': 'rgb(30, 30, 30)'},
|
||||||
style_cell={
|
style_cell={
|
||||||
'backgroundColor': 'rgb(50, 50, 50)',
|
'backgroundColor': 'rgb(50, 50, 50)',
|
||||||
'color': 'white'
|
'color': 'white'
|
||||||
},
|
},
|
||||||
style_data_conditional=[
|
|
||||||
{
|
|
||||||
'if': {
|
|
||||||
'filter_query': '{cena} > {średnia}',
|
|
||||||
'column_id': 'tracker'
|
|
||||||
},
|
|
||||||
'backgroundColor': 'green',
|
|
||||||
'color': 'black'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'if': {
|
|
||||||
'filter_query': '{cena} <= {średnia}',
|
|
||||||
'column_id': 'tracker'
|
|
||||||
},
|
|
||||||
'backgroundColor': 'red',
|
|
||||||
'color': 'black'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
html.Div(className='eight columns div-for-charts bg-grey',
|
html.Div(className='eight columns div-for-charts bg-grey',
|
||||||
children=[
|
children=[
|
||||||
dcc.Tabs(id='tabs', value='tab-1', children=[
|
dcc.Tabs(id='tabs', value='tab-1', children=[
|
||||||
dcc.Tab(id='tab-1', label='Chart 1', value='tab-1', children=[
|
dcc.Tab(id='tab-1', label='Chart 1', value='tab-1', children=[
|
||||||
dcc.Graph(id='timeseries', config={'displayModeBar': False}, animate=True),
|
dcc.Graph(id='timeseries', config={'displayModeBar': False}, animate=True),
|
||||||
]),
|
]),
|
||||||
dcc.Tab(id='tab-2', label='Chart 2', value='tab-2', children=[
|
dcc.Tab(id='tab-2', label='Chart 2', value='tab-2',children=[
|
||||||
dcc.Graph(id='price-dividends', figure=mean_prices_and_dividends_figure,
|
dcc.Graph(id='price-dividends', config={'displayModeBar': False}, animate=True),
|
||||||
config={'displayModeBar': False}, animate=True),
|
]),
|
||||||
]),
|
|
||||||
dcc.Tab(id='tab-3', label='Copmany description', value='tab-3', children=[
|
|
||||||
html.Div(id="company-desritpion"),
|
|
||||||
]),
|
|
||||||
]),
|
]),
|
||||||
dash_table.DataTable(
|
dash_table.DataTable(
|
||||||
id='stock_price_table',
|
id='stock_price_table',
|
||||||
@ -194,24 +161,6 @@ app.layout = html.Div(
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# Callback for scraping company description
|
|
||||||
@app.callback(Output('company-desritpion', 'children'), [Input('table_selector', 'value')])
|
|
||||||
def update_graph(selected_dropdown_value):
|
|
||||||
url = 'https://finance.yahoo.com/quote/{company}/profile?p={company}'.format(company=selected_dropdown_value)
|
|
||||||
page = requests.get(url)
|
|
||||||
soup = BeautifulSoup(page.content, 'html.parser')
|
|
||||||
comp_name = soup.find(id="Main").h3.text
|
|
||||||
description = soup.find_all('section', class_='quote-sub-section')[0].p.text
|
|
||||||
|
|
||||||
return dcc.Markdown('''
|
|
||||||
|
|
||||||
# [{comp_name}]({url})
|
|
||||||
|
|
||||||
{description}
|
|
||||||
'''.format(comp_name=comp_name, description=description, url=url))
|
|
||||||
|
|
||||||
|
|
||||||
# Callback for downloading file
|
# Callback for downloading file
|
||||||
@app.callback(
|
@app.callback(
|
||||||
Output("download-data", "data"),
|
Output("download-data", "data"),
|
||||||
@ -221,8 +170,7 @@ def update_graph(selected_dropdown_value):
|
|||||||
)
|
)
|
||||||
def create_download_file(n_clicks, selected_table):
|
def create_download_file(n_clicks, selected_table):
|
||||||
global selected_stock_in_table_df
|
global selected_stock_in_table_df
|
||||||
return dcc.send_data_frame(selected_stock_in_table_df.to_csv, "data-{table}.csv".format(table=selected_table))
|
return dcc.send_data_frame(selected_stock_in_table_df.to_csv, "data-{table}.csv".format(table = selected_table))
|
||||||
|
|
||||||
|
|
||||||
# Callback for timeseries price
|
# Callback for timeseries price
|
||||||
@app.callback(Output('timeseries', 'figure'), [Input('stockselector', 'value')])
|
@app.callback(Output('timeseries', 'figure'), [Input('stockselector', 'value')])
|
||||||
@ -236,52 +184,16 @@ def update_graph(selected_dropdown_value):
|
|||||||
return figure
|
return figure
|
||||||
|
|
||||||
|
|
||||||
@app.callback([Output("stock_price_table", "data"),
|
@app.callback([Output("stock_price_table", "data"), Output('stock_price_table', 'columns')],
|
||||||
Output('stock_price_table', 'columns'),
|
[Input('table_selector', 'value')])
|
||||||
Output('average_gauge', 'figure'),
|
def update_table(selected_dropdown_value):
|
||||||
Output('volatility_gauge', 'figure'),
|
|
||||||
Output('info_in_time_period', 'data')],
|
|
||||||
[Input('timeseries', 'relayoutData'),
|
|
||||||
Input('table_selector', 'value')])
|
|
||||||
def common_table_callback(callback_data_time_period, callback_data_table_selector):
|
|
||||||
global selected_stock_in_table
|
global selected_stock_in_table
|
||||||
global selected_stock_in_table_df
|
global selected_stock_in_table_df
|
||||||
global from_time
|
selected_stock_in_table = selected_dropdown_value
|
||||||
global to_time
|
selected_stock_in_table_df = fullTableDf.xs(selected_stock_in_table, axis=1, level=1)
|
||||||
global average_gauge
|
data = selected_stock_in_table_df.to_dict('records')
|
||||||
global volatility_gauge
|
columns = [{"name": i, "id": i} for i in selected_stock_in_table_df.columns]
|
||||||
global stock_info_in_time_period_df
|
return data, columns
|
||||||
selected_stock_in_table_changed = False
|
|
||||||
change_time_period = False
|
|
||||||
for trigger in dash.callback_context.triggered:
|
|
||||||
if trigger['prop_id'] == 'table_selector.value':
|
|
||||||
selected_stock_in_table_changed = True
|
|
||||||
if trigger['prop_id'] == 'timeseries.relayoutData':
|
|
||||||
change_time_period = True
|
|
||||||
if selected_stock_in_table_changed:
|
|
||||||
selected_stock_in_table = callback_data_table_selector
|
|
||||||
selected_stock_in_table_df = fullTableDf.xs(selected_stock_in_table, axis=1, level=1)
|
|
||||||
if change_time_period:
|
|
||||||
if "xaxis.range[0]" in callback_data_time_period and "xaxis.range[1]" in callback_data_time_period:
|
|
||||||
from_time = callback_data_time_period["xaxis.range[0]"]
|
|
||||||
to_time = callback_data_time_period["xaxis.range[1]"]
|
|
||||||
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)
|
|
||||||
if change_time_period or selected_stock_in_table_changed:
|
|
||||||
stock_info_in_time_period_df['średnia'] = fullTableDf['Close'].loc[from_time:to_time].mean(axis=0)
|
|
||||||
stock_info_in_time_period_df['cena'] = fullTableDf['Close'].loc[fullTableDf.index.max()]
|
|
||||||
time_period = selected_stock_in_table_df['Close'].loc[from_time:to_time]
|
|
||||||
mean = time_period.mean(axis=0)
|
|
||||||
std = time_period.std(axis=0)
|
|
||||||
average_gauge = make_gauge('średnia', 0, mean, 400)
|
|
||||||
volatility_gauge = make_gauge('wolatylność', 0, std, 400)
|
|
||||||
stock_price_table_data = selected_stock_in_table_df.to_dict('records')
|
|
||||||
stock_price_table_columns = [{"name": i, "id": i} for i in selected_stock_in_table_df.columns]
|
|
||||||
stock_info_in_time_period_data = stock_info_in_time_period_df.to_dict('records')
|
|
||||||
return stock_price_table_data, stock_price_table_columns, average_gauge, volatility_gauge, stock_info_in_time_period_data
|
|
||||||
|
|
||||||
|
|
||||||
average_gauge = make_gauge('średnia', 0, 0, 400)
|
average_gauge = make_gauge('średnia', 0, 0, 400)
|
||||||
@ -289,9 +201,9 @@ volatility_gauge = make_gauge('wolatylność', 0, 0, 400)
|
|||||||
|
|
||||||
|
|
||||||
def round_to_nearest_weekday(date):
|
def round_to_nearest_weekday(date):
|
||||||
if isinstance(date, pd.Timestamp):
|
if isinstance(date,pd.Timestamp):
|
||||||
if date.dayofweek > 5:
|
if date.dayofweek > 5:
|
||||||
date += datetime.timedelta(days=8 - date.dayofweek)
|
date += datetime.timedelta(days=8-date.dayofweek)
|
||||||
assert date.dayofweek <= 5
|
assert date.dayofweek <= 5
|
||||||
return date
|
return date
|
||||||
elif isinstance(date, str):
|
elif isinstance(date, str):
|
||||||
@ -302,10 +214,44 @@ def round_to_nearest_weekday(date):
|
|||||||
else:
|
else:
|
||||||
date = datetime.datetime.strptime(date, "%Y-%m-%d")
|
date = datetime.datetime.strptime(date, "%Y-%m-%d")
|
||||||
if date.isoweekday() > 5:
|
if date.isoweekday() > 5:
|
||||||
date += datetime.timedelta(days=8 - date.isoweekday())
|
date += datetime.timedelta(days=8-date.isoweekday())
|
||||||
assert date.isoweekday() <= 5
|
assert date.isoweekday() <= 5
|
||||||
return date
|
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 "xaxis.range[0]" in selectedData and "xaxis.range[1]" in selectedData:
|
||||||
|
from_time = selectedData["xaxis.range[0]"]
|
||||||
|
to_time = selectedData["xaxis.range[1]"]
|
||||||
|
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')
|
||||||
|
|
||||||
|
@app.callback(Output('price-dividends', 'figure'),
|
||||||
|
[Input('table_selector', 'value')])
|
||||||
|
def update_point_chart(selected_dropdown_value):
|
||||||
|
selected_stock_in_table_df = fullTableDf.xs(selected_dropdown_value, axis=1, level=1)
|
||||||
|
figure = px.scatter(selected_stock_in_table_df, x='Dividends', y='Close', template='plotly_dark')
|
||||||
|
return figure
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run_server(debug=True)
|
app.run_server(debug=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user