Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- pages/home.py +48 -0
- pages/stock_by_exchange.py +219 -0
- pages/stock_by_index.py +221 -0
pages/home.py
ADDED
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import dash
|
2 |
+
from dash import html, dcc
|
3 |
+
|
4 |
+
dash.register_page(__name__, path='/')
|
5 |
+
|
6 |
+
layout = html.Div(children=[
|
7 |
+
html.Br(),
|
8 |
+
html.Br(),
|
9 |
+
html.Br(),
|
10 |
+
dcc.Markdown('''
|
11 |
+
**ExchangeTree** is an interactive web application that enables one to explore the most relevant stock indexes and exchanges.
|
12 |
+
|
13 |
+
The app is still under development and should be considered alpha quality.
|
14 |
+
|
15 |
+
The tool is provided "as is" and we are not to be hold responsible for any inaccuracies.
|
16 |
+
|
17 |
+
The current version represents the very first working prototype and it is glitchy and very minimalistic.
|
18 |
+
|
19 |
+
Bugs can be reported and additional functionality requested via [GitHub](https://github.com/mirix/stocktree).
|
20 |
+
|
21 |
+
The design is currently non-responsive. It has been developed in Linux and optimised for Firefox with a 1080p desktop display.
|
22 |
+
|
23 |
+
Microsoft browsers and operating systems are unable to display unicode emoji flags, whereas Google Chrome can be patched by installing an [extension](https://chrome.google.com/webstore/detail/country-flag-fixer/jhcpefjbhmbkgjgipkhndplfbhdecijh).
|
24 |
+
|
25 |
+
**ExchangeTree** is build in Python by leveraging [Plotly/Dash](https://github.com/plotly/dash) technologies.
|
26 |
+
|
27 |
+
Finantial information is gathered in real time by using the [StockSymbol](https://github.com/yongghongg/stock-symbol) and [yfinance](https://github.com/ranaroussi/yfinance) APIs.
|
28 |
+
|
29 |
+
However, these sources may be replaced in the future.
|
30 |
+
|
31 |
+
**ExchangeTree** has two exploration modes: index mode and exchange mode, respectively.
|
32 |
+
|
33 |
+
Indexes are far from exhaustive as only the main ones are currently considered, whereas exchange mode can be a bit laggy.
|
34 |
+
|
35 |
+
This app differs from existing tools in which it aims at providing a hierarchical overview whereas other apps tend to be more targeted.
|
36 |
+
|
37 |
+
The current layout is intended to be explored counterclockwise from top to bottom:
|
38 |
+
|
39 |
+
First one chooses a country, then a exchange or index and finally a specific stock.
|
40 |
+
|
41 |
+
Graphs are on the top row and tables on the bottom row (you may need to scroll down to see them).
|
42 |
+
|
43 |
+
Graphs are somehow interactive and tables can be filtered by entering the first letters of the desired item.
|
44 |
+
|
45 |
+
''', link_target="_blank",
|
46 |
+
style={'fontFamily': 'Arial, Helvetica, sans-serif', 'color': 'grey', 'fontSize': 14, 'linkColor': 'darkorange'}),
|
47 |
+
|
48 |
+
])
|
pages/stock_by_exchange.py
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import flag
|
2 |
+
import pandas as pd
|
3 |
+
import numpy as np
|
4 |
+
from countryinfo import CountryInfo
|
5 |
+
from stocksymbol import StockSymbol
|
6 |
+
import yfinance as yf
|
7 |
+
import plotly.graph_objects as go
|
8 |
+
from dash import Dash, dcc, html, Input, Output, dash_table, callback
|
9 |
+
import dash
|
10 |
+
from dash.dependencies import Input, Output
|
11 |
+
from dash.exceptions import PreventUpdate
|
12 |
+
|
13 |
+
dash.register_page(__name__)
|
14 |
+
|
15 |
+
api_key = '724b3358-1685-4659-92ea-1e445f283e30'
|
16 |
+
ss = StockSymbol(api_key)
|
17 |
+
|
18 |
+
market_list = ss.market_list
|
19 |
+
|
20 |
+
df = pd.DataFrame.from_dict(market_list)
|
21 |
+
|
22 |
+
df = pd.DataFrame.from_dict(market_list)
|
23 |
+
df = df[['abbreviation', 'market']].copy()
|
24 |
+
|
25 |
+
df['country'] = df['abbreviation'].apply(lambda x: CountryInfo(x).name().title() if x != 'eu' else 'Europe')
|
26 |
+
df['iso3'] = df['abbreviation'].apply(lambda x: CountryInfo(x).iso(3) if x != 'eu' else 'EUR')
|
27 |
+
df['iso2'] = df['abbreviation'].apply(lambda x: CountryInfo(x).iso(2) if x != 'eu' else 'EU')
|
28 |
+
df['flags'] = df['iso2'].apply(lambda x: flag.flag(x))
|
29 |
+
df['lat'] = df['abbreviation'].apply(lambda x: CountryInfo(x).capital_latlng()[0] if x != 'eu' else 49.845556)
|
30 |
+
df['long'] = df['abbreviation'].apply(lambda x:CountryInfo(x).capital_latlng()[1] if x != 'eu' else 9.906111)
|
31 |
+
|
32 |
+
df.loc[df['iso3'] == 'HKG', 'lat'] = 22.278333
|
33 |
+
df.loc[df['iso3'] == 'HKG', 'long'] = 114.174444
|
34 |
+
|
35 |
+
customdata = [df['country'], df['flags']]
|
36 |
+
hovertemplate = ('<br>' + customdata[0] + ' ' + customdata[1] + '<br>' + '<extra></extra>')
|
37 |
+
|
38 |
+
fig = go.Figure(data=go.Scattergeo(
|
39 |
+
lon = df['long'],
|
40 |
+
lat = df['lat'],
|
41 |
+
text = df['flags'] + '<br>' + '<b>' + df['iso3'] + '</b>',
|
42 |
+
mode = 'text+markers',
|
43 |
+
marker = dict(size=40, color='darkorange', opacity=0.8)
|
44 |
+
))
|
45 |
+
|
46 |
+
fig.update_traces(textfont_size=13, customdata=customdata, hovertemplate=hovertemplate)
|
47 |
+
fig.update_geos(projection=dict(type = 'orthographic'), visible=False, resolution=110, showcountries=True, countrycolor='darkorange')
|
48 |
+
fig.update_layout(title=dict(text='EXPLORE LISTED COMPANIES BY EXCHANGE', font=dict(color='darkorange')), title_x=0.5, font=dict(color='White'), clickmode='event+select', height=900)
|
49 |
+
|
50 |
+
country = 'ch'
|
51 |
+
symbol_list = ss.get_symbol_list(market=country)
|
52 |
+
df2 = pd.DataFrame.from_dict(symbol_list)
|
53 |
+
df3 = pd.DataFrame(df2['exchange'].value_counts().reset_index().values, columns=['exchange', 'number_of_companies'])
|
54 |
+
df3['country'] = df.loc[df['abbreviation'] == country]['iso3'].values[0] + ' ' + df.loc[df['abbreviation'] == country]['flags'].values[0]
|
55 |
+
df3 = df3[['country', 'exchange' , 'number_of_companies']]
|
56 |
+
df3 = df3.sort_values(['exchange'], ascending = [True])
|
57 |
+
|
58 |
+
ticker = 'SQN.SW'
|
59 |
+
index = 'EBS'
|
60 |
+
comp = yf.Ticker(ticker)
|
61 |
+
hist = comp.history(period='1y')
|
62 |
+
df_inx = df2.loc[df2['exchange'] == index].copy()
|
63 |
+
df_inx.drop(['shortName', 'market'], axis=1, inplace=True, errors='ignore')
|
64 |
+
df_inx = df_inx.sort_values(['longName', 'symbol'], ascending = [True, True])
|
65 |
+
df_inx = df_inx.reset_index(drop=True)
|
66 |
+
df_inx['id'] = df_inx.index
|
67 |
+
|
68 |
+
@callback([Output(component_id='table-index-exchange', component_property='data'),
|
69 |
+
Output(component_id='table-index-exchange', component_property='columns')],
|
70 |
+
[Output('table-company-exchange', 'data'), Output('table-company-exchange', 'columns')], [Output('company-evolution-exchange', 'figure')],
|
71 |
+
[Input('map-flags', 'selectedData')], [Input('table-index-exchange', 'selected_rows')], [Input('table-company-exchange', 'selected_row_ids')])
|
72 |
+
def display_selected_data(selectedData, selected_rows, selected_row_ids):
|
73 |
+
global df
|
74 |
+
global df3
|
75 |
+
global df_inx
|
76 |
+
if selectedData:
|
77 |
+
index = selectedData['points'][0]['pointIndex']
|
78 |
+
country = df.iloc[index]['abbreviation']
|
79 |
+
else:
|
80 |
+
country = 'ch'
|
81 |
+
symbol_list = ss.get_symbol_list(market=country)
|
82 |
+
df2 = pd.DataFrame.from_dict(symbol_list)
|
83 |
+
df3 = pd.DataFrame(df2['exchange'].value_counts().reset_index().values, columns=['exchange', 'number_of_companies'])
|
84 |
+
df3['country'] = df.loc[df['abbreviation'] == country]['iso3'].values[0] + ' ' + df.loc[df['abbreviation'] == country]['flags'].values[0]
|
85 |
+
df3 = df3[['country', 'exchange' , 'number_of_companies']]
|
86 |
+
df3 = df3.sort_values(['exchange'], ascending = [True])
|
87 |
+
columns = [{'name': col, 'id': col} for col in df3.columns]
|
88 |
+
data = df3.to_dict(orient='records')
|
89 |
+
|
90 |
+
if selected_rows:
|
91 |
+
#index = selected_rows
|
92 |
+
if selected_rows[0] > len(df3)-1:
|
93 |
+
selected_rows = [0]
|
94 |
+
index = df3['exchange'].iloc[selected_rows[0]]
|
95 |
+
|
96 |
+
else:
|
97 |
+
index = 'EBS'
|
98 |
+
df_inx = df2.loc[df2['exchange'] == index].copy()
|
99 |
+
|
100 |
+
df_inx.drop(['shortName', 'market'], axis=1, inplace=True, errors='ignore')
|
101 |
+
df_inx = df_inx.sort_values(['longName', 'symbol'], ascending = [False, False])
|
102 |
+
df_inx = df_inx.reset_index(drop=True)
|
103 |
+
df_inx['id'] = df_inx.index
|
104 |
+
columns2 = [{'name': col, 'id': col} for col in df_inx.columns[:-1]]
|
105 |
+
data2 = df_inx.to_dict(orient='records')
|
106 |
+
|
107 |
+
if selected_row_ids:
|
108 |
+
if selected_row_ids[0] > len(df_inx)-1:
|
109 |
+
selected_row_ids = [0]
|
110 |
+
ticker = df_inx['symbol'].iloc[selected_row_ids[0]]
|
111 |
+
comp_name = df_inx['longName'].iloc[selected_row_ids[0]]
|
112 |
+
else:
|
113 |
+
ticker = 'SQN.SW'
|
114 |
+
comp_name = 'Swissquote Group Holding Ltd'
|
115 |
+
comp = yf.Ticker(ticker)
|
116 |
+
hist = comp.history(period='1y')
|
117 |
+
fig2 = go.Figure(data=go.Scatter(
|
118 |
+
x = hist.index,
|
119 |
+
y = hist['Close'],
|
120 |
+
mode = 'lines',
|
121 |
+
line = dict(color='firebrick', width=3)
|
122 |
+
))
|
123 |
+
|
124 |
+
fig2.update_layout(
|
125 |
+
xaxis=dict(
|
126 |
+
showline=False,
|
127 |
+
showgrid=True,
|
128 |
+
showticklabels=True,
|
129 |
+
gridcolor='WhiteSmoke',
|
130 |
+
tickfont=dict(
|
131 |
+
size=12,
|
132 |
+
color='darkorange',
|
133 |
+
),
|
134 |
+
),
|
135 |
+
yaxis=dict(
|
136 |
+
showline=False,
|
137 |
+
showgrid=True,
|
138 |
+
showticklabels=True,
|
139 |
+
gridcolor='WhiteSmoke',
|
140 |
+
tickfont=dict(
|
141 |
+
size=12,
|
142 |
+
color='darkorange',
|
143 |
+
),
|
144 |
+
),
|
145 |
+
showlegend=False,
|
146 |
+
plot_bgcolor='white',
|
147 |
+
title=comp_name,
|
148 |
+
font=dict(
|
149 |
+
size=12,
|
150 |
+
color='darkorange'
|
151 |
+
)
|
152 |
+
)
|
153 |
+
|
154 |
+
return data, columns, data2, columns2, fig2
|
155 |
+
|
156 |
+
layout = html.Div([
|
157 |
+
html.Div([
|
158 |
+
dcc.Graph(id='map-flags',
|
159 |
+
figure=fig, style={'width': '900px', 'height': '900px'})], style={'display': 'inline-block'}),
|
160 |
+
html.Div([
|
161 |
+
dcc.Graph(id='company-evolution-exchange',
|
162 |
+
figure=fig, style={'width': '900px', 'height': '600px'})], style={'display': 'inline-block'}),
|
163 |
+
html.Div([
|
164 |
+
html.Label('EXCHANGES', style={'fontWeight': 'bold', 'color': 'darkorange', 'fontSize': 12, 'fontFamily': 'Arial, Helvetica, sans-serif'}),
|
165 |
+
dash_table.DataTable(id='table-index-exchange',
|
166 |
+
style_header={'backgroundColor': 'darkorange',
|
167 |
+
'color': 'white',
|
168 |
+
'fontWeight': 'bold', 'fontFamily': 'Arial, Helvetica, sans-serif', 'fontSize': 12
|
169 |
+
},
|
170 |
+
style_data={'backgroundColor': 'white',
|
171 |
+
'color': 'grey'
|
172 |
+
},
|
173 |
+
fill_width=False,
|
174 |
+
editable=True,
|
175 |
+
filter_action='native',
|
176 |
+
filter_options={'case': 'insensitive'},
|
177 |
+
sort_action='native',
|
178 |
+
sort_mode='multi',
|
179 |
+
#column_selectable='single',
|
180 |
+
row_selectable='single',
|
181 |
+
#selected_columns=[],
|
182 |
+
selected_rows=[],
|
183 |
+
#selected_row_ids=[],
|
184 |
+
#fixed_rows={'headers':True, 'data':1},
|
185 |
+
page_action='none',
|
186 |
+
style_table={'height': '900px', 'width': '700px', 'overflowY': 'auto'}
|
187 |
+
#page_current=0,
|
188 |
+
#page_size=10
|
189 |
+
)], style={'display': 'inline-block'}),
|
190 |
+
html.Div([
|
191 |
+
html.Label('COMPANIES', style={'fontWeight': 'bold', 'color': 'darkorange', 'fontSize': 12, 'fontFamily': 'Arial, Helvetica, sans-serif'}),
|
192 |
+
dash_table.DataTable(id='table-company-exchange',
|
193 |
+
style_header={'backgroundColor': 'darkorange',
|
194 |
+
'color': 'white',
|
195 |
+
'fontWeight': 'bold', 'fontFamily': 'Arial, Helvetica, sans-serif', 'fontSize': 12
|
196 |
+
},
|
197 |
+
style_data={'backgroundColor': 'white',
|
198 |
+
'color': 'grey'
|
199 |
+
},
|
200 |
+
fill_width=False,
|
201 |
+
editable=True,
|
202 |
+
filter_action='native',
|
203 |
+
filter_options={'case': 'insensitive'},
|
204 |
+
sort_action='native',
|
205 |
+
sort_mode='multi',
|
206 |
+
#column_selectable='single',
|
207 |
+
row_selectable='single',
|
208 |
+
#selected_columns=[],
|
209 |
+
selected_rows=[],
|
210 |
+
selected_row_ids=[],
|
211 |
+
#fixed_rows={'headers': True},
|
212 |
+
page_action='none',
|
213 |
+
style_table={'height': '900px', 'width': '900px', 'overflowY': 'auto'}
|
214 |
+
#page_current=0,
|
215 |
+
#page_size=10
|
216 |
+
)], style={'display': 'inline-block'}),
|
217 |
+
])
|
218 |
+
|
219 |
+
|
pages/stock_by_index.py
ADDED
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import flag
|
2 |
+
import pandas as pd
|
3 |
+
import numpy as np
|
4 |
+
from countryinfo import CountryInfo
|
5 |
+
from stocksymbol import StockSymbol
|
6 |
+
import yfinance as yf
|
7 |
+
import plotly.graph_objects as go
|
8 |
+
from dash import Dash, dcc, html, Input, Output, dash_table, callback
|
9 |
+
import dash
|
10 |
+
from dash.dependencies import Input, Output
|
11 |
+
from dash.exceptions import PreventUpdate
|
12 |
+
|
13 |
+
dash.register_page(__name__)
|
14 |
+
|
15 |
+
api_key = '724b3358-1685-4659-92ea-1e445f283e30'
|
16 |
+
ss = StockSymbol(api_key)
|
17 |
+
|
18 |
+
market_list = ss.market_list
|
19 |
+
|
20 |
+
df = pd.DataFrame.from_dict(market_list)
|
21 |
+
df = df[['abbreviation', 'index']].copy()
|
22 |
+
df = df[df['index'].map(lambda x: len(x)) > 0]
|
23 |
+
|
24 |
+
df['country'] = df['abbreviation'].apply(lambda x: CountryInfo(x).name().title() if x != 'eu' else 'Europe')
|
25 |
+
df['iso3'] = df['abbreviation'].apply(lambda x: CountryInfo(x).iso(3) if x != 'eu' else 'EUR')
|
26 |
+
df['iso2'] = df['abbreviation'].apply(lambda x: CountryInfo(x).iso(2) if x != 'eu' else 'EU')
|
27 |
+
df['flags'] = df['iso2'].apply(lambda x: flag.flag(x))
|
28 |
+
df['lat'] = df['abbreviation'].apply(lambda x: CountryInfo(x).capital_latlng()[0] if x != 'eu' else 49.845556)
|
29 |
+
df['long'] = df['abbreviation'].apply(lambda x:CountryInfo(x).capital_latlng()[1] if x != 'eu' else 9.906111)
|
30 |
+
|
31 |
+
df.loc[df['iso3'] == 'HKG', 'lat'] = 22.278333
|
32 |
+
df.loc[df['iso3'] == 'HKG', 'long'] = 114.174444
|
33 |
+
|
34 |
+
customdata = [df['country'], df['flags']]
|
35 |
+
hovertemplate = ('<br>' + customdata[0] + ' ' + customdata[1] + '<br>' + '<extra></extra>')
|
36 |
+
|
37 |
+
fig = go.Figure(data=go.Scattergeo(
|
38 |
+
lon = df['long'],
|
39 |
+
lat = df['lat'],
|
40 |
+
text = df['flags'] + '<br>' + '<b>' + df['iso3'] + '</b>',
|
41 |
+
mode = 'text+markers',
|
42 |
+
marker = dict(size=40, color='darkorange', opacity=0.8)
|
43 |
+
))
|
44 |
+
|
45 |
+
fig.update_traces(textfont_size=13, customdata=customdata, hovertemplate=hovertemplate)
|
46 |
+
fig.update_geos(projection=dict(type = 'orthographic'), visible=False, resolution=110, showcountries=True, countrycolor='darkorange')
|
47 |
+
fig.update_layout(title=dict(text='EXPLORE LISTED COMPANIES BY INDEX', font=dict(color='darkorange')), title_x=0.5, font=dict(color='White'), clickmode='event+select', height=900)
|
48 |
+
|
49 |
+
country = 'us'
|
50 |
+
df2 = df.loc[df['abbreviation'] == country].copy()
|
51 |
+
df3 = pd.DataFrame.from_dict(df2['index'].values[0])
|
52 |
+
df3['country'] = df2['iso3'].iloc[0] + ' ' + df2['flags'].iloc[0]
|
53 |
+
df3 = df3.rename({'id': 'id_index'}, axis=1)
|
54 |
+
df3 = df3[['country', 'id_index' , 'name']]
|
55 |
+
df3 = df3.sort_values(['id_index', 'name'], ascending = [True, True])
|
56 |
+
|
57 |
+
ticker = 'MMM'
|
58 |
+
index = 'DJA'
|
59 |
+
comp = yf.Ticker(ticker)
|
60 |
+
hist = comp.history(period='1y')
|
61 |
+
symbol_list = ss.get_symbol_list(index=index)
|
62 |
+
df_inx = pd.DataFrame.from_dict(symbol_list)
|
63 |
+
df_inx.drop(['shortName', 'market'], axis=1, inplace=True, errors='ignore')
|
64 |
+
df_inx = df_inx.sort_values(['longName', 'symbol'], ascending = [True, True])
|
65 |
+
df_inx = df_inx.reset_index(drop=True)
|
66 |
+
df_inx['id'] = df_inx.index
|
67 |
+
|
68 |
+
@callback([Output(component_id='table-index', component_property='data'),
|
69 |
+
Output(component_id='table-index', component_property='columns')],
|
70 |
+
[Output('table-company', 'data'), Output('table-company', 'columns')], [Output('company-evolution', 'figure')],
|
71 |
+
[Input('map-flags', 'selectedData')], [Input('table-index', 'selected_rows')], [Input('table-company', 'selected_row_ids')])
|
72 |
+
def display_selected_data(selectedData, selected_rows, selected_row_ids):
|
73 |
+
global df
|
74 |
+
if selectedData:
|
75 |
+
index = selectedData['points'][0]['pointIndex']
|
76 |
+
country = df.iloc[index]['abbreviation']
|
77 |
+
else:
|
78 |
+
country = 'us'
|
79 |
+
df2 = df.loc[df['abbreviation'] == country].copy()
|
80 |
+
df3 = pd.DataFrame.from_dict(df2['index'].values[0])
|
81 |
+
df3['country'] = df2['iso3'].iloc[0] + ' ' + df2['flags'].iloc[0]
|
82 |
+
df3 = df3.rename({'id': 'id_index'}, axis=1)
|
83 |
+
df3 = df3[['country', 'id_index' , 'name']]
|
84 |
+
df3 = df3[df3['id_index'] != 'HSI:HSI']
|
85 |
+
df3 = df3.sort_values(['id_index', 'name'], ascending = [True, True])
|
86 |
+
columns = [{'name': col, 'id': col} for col in df3.columns]
|
87 |
+
data = df3.to_dict(orient='records')
|
88 |
+
|
89 |
+
if selected_rows:
|
90 |
+
#index = selected_rows
|
91 |
+
if selected_rows[0] > len(df3)-1:
|
92 |
+
selected_rows = [0]
|
93 |
+
index = df3['id_index'].iloc[selected_rows[0]].split(':')[1]
|
94 |
+
|
95 |
+
else:
|
96 |
+
index = df3['id_index'].iloc[0].split(':')[1]
|
97 |
+
symbol_list = ss.get_symbol_list(index=index)
|
98 |
+
df_inx = pd.DataFrame.from_dict(symbol_list)
|
99 |
+
if not df_inx.empty:
|
100 |
+
df_inx.drop(['shortName', 'market'], axis=1, inplace=True, errors='ignore')
|
101 |
+
df_inx = df_inx.sort_values(['longName', 'symbol'], ascending = [True, True])
|
102 |
+
df_inx = df_inx.reset_index(drop=True)
|
103 |
+
df_inx['id'] = df_inx.index
|
104 |
+
columns2 = [{'name': col, 'id': col} for col in df_inx.columns[:-1]]
|
105 |
+
data2 = df_inx.to_dict(orient='records')
|
106 |
+
|
107 |
+
if selected_row_ids:
|
108 |
+
if selected_row_ids[0] > len(df_inx)-1:
|
109 |
+
selected_row_ids = [0]
|
110 |
+
ticker = df_inx['symbol'].iloc[selected_row_ids[0]]
|
111 |
+
comp_name = df_inx['longName'].iloc[selected_row_ids[0]]
|
112 |
+
else:
|
113 |
+
ticker = df_inx['symbol'].iloc[0]
|
114 |
+
comp_name = df_inx['longName'].iloc[0]
|
115 |
+
|
116 |
+
comp = yf.Ticker(ticker)
|
117 |
+
hist = comp.history(period='1y')
|
118 |
+
fig2 = go.Figure(data=go.Scatter(
|
119 |
+
x = hist.index,
|
120 |
+
y = hist['Close'],
|
121 |
+
mode = 'lines',
|
122 |
+
line = dict(color='firebrick', width=3)
|
123 |
+
))
|
124 |
+
|
125 |
+
fig2.update_layout(
|
126 |
+
xaxis=dict(
|
127 |
+
showline=False,
|
128 |
+
showgrid=True,
|
129 |
+
showticklabels=True,
|
130 |
+
gridcolor='WhiteSmoke',
|
131 |
+
tickfont=dict(
|
132 |
+
size=12,
|
133 |
+
color='darkorange',
|
134 |
+
),
|
135 |
+
),
|
136 |
+
yaxis=dict(
|
137 |
+
showline=False,
|
138 |
+
showgrid=True,
|
139 |
+
showticklabels=True,
|
140 |
+
gridcolor='WhiteSmoke',
|
141 |
+
tickfont=dict(
|
142 |
+
size=12,
|
143 |
+
color='darkorange',
|
144 |
+
),
|
145 |
+
),
|
146 |
+
showlegend=False,
|
147 |
+
plot_bgcolor='white',
|
148 |
+
title=comp_name,
|
149 |
+
font=dict(
|
150 |
+
size=12,
|
151 |
+
color='darkorange'
|
152 |
+
)
|
153 |
+
)
|
154 |
+
else:
|
155 |
+
raise PreventUpdate
|
156 |
+
|
157 |
+
return data, columns, data2, columns2, fig2
|
158 |
+
|
159 |
+
layout = html.Div([
|
160 |
+
html.Div([
|
161 |
+
dcc.Graph(id='map-flags',
|
162 |
+
figure=fig, style={'width': '900px', 'height': '900px'})], style={'display': 'inline-block'}),
|
163 |
+
html.Div([
|
164 |
+
dcc.Graph(id='company-evolution',
|
165 |
+
figure=fig, style={'width': '900px', 'height': '600px'})], style={'display': 'inline-block'}),
|
166 |
+
html.Div([
|
167 |
+
html.Label('INDEXES', style={'fontWeight': 'bold', 'color': 'darkorange', 'fontSize': 12, 'fontFamily': 'Arial, Helvetica, sans-serif'}),
|
168 |
+
dash_table.DataTable(id='table-index',
|
169 |
+
style_header={'backgroundColor': 'darkorange',
|
170 |
+
'color': 'white',
|
171 |
+
'fontWeight': 'bold', 'fontFamily': 'Arial, Helvetica, sans-serif', 'fontSize': 12
|
172 |
+
},
|
173 |
+
style_data={'backgroundColor': 'white',
|
174 |
+
'color': 'grey'
|
175 |
+
},
|
176 |
+
fill_width=False,
|
177 |
+
editable=True,
|
178 |
+
filter_action='native',
|
179 |
+
filter_options={'case': 'insensitive'},
|
180 |
+
sort_action='native',
|
181 |
+
sort_mode='multi',
|
182 |
+
#column_selectable='single',
|
183 |
+
row_selectable='single',
|
184 |
+
#selected_columns=[],
|
185 |
+
selected_rows=[],
|
186 |
+
#selected_row_ids=[],
|
187 |
+
#fixed_rows={'headers':True, 'data':1},
|
188 |
+
page_action='none',
|
189 |
+
style_table={'height': '900px', 'width': '700px', 'overflowY': 'auto'}
|
190 |
+
#page_current=0,
|
191 |
+
#page_size=10
|
192 |
+
)], style={'display': 'inline-block'}),
|
193 |
+
html.Div([
|
194 |
+
html.Label('COMPANIES', style={'fontWeight': 'bold', 'color': 'darkorange', 'fontSize': 12, 'fontFamily': 'Arial, Helvetica, sans-serif'}),
|
195 |
+
dash_table.DataTable(id='table-company',
|
196 |
+
style_header={'backgroundColor': 'darkorange',
|
197 |
+
'color': 'white',
|
198 |
+
'fontWeight': 'bold', 'fontFamily': 'Arial, Helvetica, sans-serif', 'fontSize': 12
|
199 |
+
},
|
200 |
+
style_data={'backgroundColor': 'white',
|
201 |
+
'color': 'grey'
|
202 |
+
},
|
203 |
+
fill_width=False,
|
204 |
+
editable=True,
|
205 |
+
filter_action='native',
|
206 |
+
filter_options={'case': 'insensitive'},
|
207 |
+
sort_action='native',
|
208 |
+
sort_mode='multi',
|
209 |
+
#column_selectable='single',
|
210 |
+
row_selectable='single',
|
211 |
+
#selected_columns=[],
|
212 |
+
selected_rows=[],
|
213 |
+
selected_row_ids=[],
|
214 |
+
#fixed_rows={'headers': True},
|
215 |
+
page_action='none',
|
216 |
+
style_table={'height': '900px', 'width': '900px', 'overflowY': 'auto'}
|
217 |
+
#page_current=0,
|
218 |
+
#page_size=10
|
219 |
+
)], style={'display': 'inline-block'}),
|
220 |
+
])
|
221 |
+
|