InNoobWeTrust commited on
Commit
4b6a96c
β€’
1 Parent(s): c5f202a

fix: asset price issue with latest yfinance

Browse files
Files changed (4) hide show
  1. .gitignore +4 -1
  2. df.py +32 -20
  3. requirements.txt +1 -1
  4. streamlit_app.py +67 -54
.gitignore CHANGED
@@ -161,4 +161,7 @@ cython_debug/
161
  # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162
  # and can be added to the global gitignore or merged into this file. For a more nuclear
163
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164
- #.idea/
 
 
 
 
161
  # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
162
  # and can be added to the global gitignore or merged into this file. For a more nuclear
163
  # option (not recommended) you can uncomment the following to ignore the entire idea folder.
164
+ #.idea/
165
+
166
+
167
+ .DS_Store
df.py CHANGED
@@ -1,7 +1,6 @@
1
  import pandas as pd
2
  import pytz
3
  import yfinance as yf
4
- import streamlit as st
5
 
6
  from typing import List
7
  from types import SimpleNamespace
@@ -47,7 +46,9 @@ def extract_date_index(df):
47
  def fetch_btc_etf():
48
  # Get Bitcoin spot ETF history
49
  btc_etf_flow = pd.read_html(
50
- "https://farside.co.uk/?p=1321", attrs={"class": "etf"}, skiprows=[1]
 
 
51
  )[0]
52
  # Remove summary lines
53
  btc_etf_flow = btc_etf_flow.iloc[:-4]
@@ -57,11 +58,12 @@ def fetch_btc_etf():
57
  btc_etf_flow, btc_etf_flow_original = clean_etf_data(btc_etf_flow)
58
 
59
  return SimpleNamespace(
60
- flow = btc_etf_flow,
61
- orig = btc_etf_flow_original,
62
- funds = btc_etf_funds,
63
  )
64
 
 
65
  def fetch_eth_etf():
66
  # Get Ethereum spot ETF history
67
  eth_etf_flow = pd.read_html(
@@ -90,28 +92,34 @@ def fetch_eth_etf():
90
  eth_etf_flow, eth_etf_flow_original = clean_etf_data(eth_etf_flow)
91
 
92
  return SimpleNamespace(
93
- flow = eth_etf_flow,
94
- orig = eth_etf_flow_original,
95
- funds = eth_etf_funds,
96
  )
97
 
 
98
  def fetch_etf_volumes(funds: List[str], start_time=None):
99
  etf_volumes = pd.DataFrame()
100
  for fund in funds:
101
  etf_volumes[fund] = yf.download(
102
- str(fund), interval = '1d', period = 'max', start = start_time,
103
- ).Volume
 
 
 
104
  etf_volumes = extract_date_index(etf_volumes)
105
 
106
  return etf_volumes
107
 
 
108
  def fetch_asset_price(ticker: str, start_time=None):
109
- price = yf.download(ticker, interval = '1d', period = 'max', start = start_time).Close
110
  price = extract_date_index(price)
 
111
 
112
  return price
113
 
114
- @st.cache_data(ttl='30m')
115
  def fetch(asset):
116
  if asset == "BTC":
117
  df = fetch_btc_etf()
@@ -119,21 +127,25 @@ def fetch(asset):
119
  df = fetch_eth_etf()
120
 
121
  etf_flow, etf_funds = df.flow, df.funds
122
- tz = pytz.timezone('America/New_York')
 
 
 
123
  start_time = tz.localize(etf_flow.Date[0])
124
- etf_volumes = fetch_etf_volumes(etf_funds, start_time = start_time)
125
- price = fetch_asset_price(f'{asset}-USD', start_time = start_time)
126
- price.rename(columns={'Close': 'Price'}, inplace=True)
127
 
128
  etf_flow_individual = etf_flow.drop(columns="Total")
129
  etf_flow_total = etf_flow[["Date", "Total"]]
130
 
131
  cum_flow_individual = etf_flow_individual.drop(columns="Date").cumsum()
132
  cum_flow_individual["Date"] = etf_flow_individual.Date
133
- cum_flow_total = pd.DataFrame({
134
- "Date": etf_flow_total.Date,
135
- "Total": etf_flow_total.Total.cumsum(),
136
- })
 
 
137
 
138
  return SimpleNamespace(
139
  etf_flow=etf_flow,
 
1
  import pandas as pd
2
  import pytz
3
  import yfinance as yf
 
4
 
5
  from typing import List
6
  from types import SimpleNamespace
 
46
  def fetch_btc_etf():
47
  # Get Bitcoin spot ETF history
48
  btc_etf_flow = pd.read_html(
49
+ "https://farside.co.uk/bitcoin-etf-flow-all-data/",
50
+ attrs={"class": "etf"},
51
+ skiprows=[1],
52
  )[0]
53
  # Remove summary lines
54
  btc_etf_flow = btc_etf_flow.iloc[:-4]
 
58
  btc_etf_flow, btc_etf_flow_original = clean_etf_data(btc_etf_flow)
59
 
60
  return SimpleNamespace(
61
+ flow=btc_etf_flow,
62
+ orig=btc_etf_flow_original,
63
+ funds=btc_etf_funds,
64
  )
65
 
66
+
67
  def fetch_eth_etf():
68
  # Get Ethereum spot ETF history
69
  eth_etf_flow = pd.read_html(
 
92
  eth_etf_flow, eth_etf_flow_original = clean_etf_data(eth_etf_flow)
93
 
94
  return SimpleNamespace(
95
+ flow=eth_etf_flow,
96
+ orig=eth_etf_flow_original,
97
+ funds=eth_etf_funds,
98
  )
99
 
100
+
101
  def fetch_etf_volumes(funds: List[str], start_time=None):
102
  etf_volumes = pd.DataFrame()
103
  for fund in funds:
104
  etf_volumes[fund] = yf.download(
105
+ str(fund),
106
+ interval="1d",
107
+ period="max",
108
+ start=start_time,
109
+ )["Volume"]
110
  etf_volumes = extract_date_index(etf_volumes)
111
 
112
  return etf_volumes
113
 
114
+
115
  def fetch_asset_price(ticker: str, start_time=None):
116
+ price = yf.download(ticker, interval="1d", period="max", start=start_time)["Close"]
117
  price = extract_date_index(price)
118
+ price.rename(columns={"Close": "Price"}, inplace=True)
119
 
120
  return price
121
 
122
+
123
  def fetch(asset):
124
  if asset == "BTC":
125
  df = fetch_btc_etf()
 
127
  df = fetch_eth_etf()
128
 
129
  etf_flow, etf_funds = df.flow, df.funds
130
+ tz = pytz.timezone("America/New_York")
131
+
132
+ etf_flow, etf_funds = df.flow, df.funds
133
+ tz = pytz.timezone("America/New_York")
134
  start_time = tz.localize(etf_flow.Date[0])
135
+ etf_volumes = fetch_etf_volumes(etf_funds, start_time=start_time)
136
+ price = fetch_asset_price(f"{asset}-USD", start_time=start_time)
 
137
 
138
  etf_flow_individual = etf_flow.drop(columns="Total")
139
  etf_flow_total = etf_flow[["Date", "Total"]]
140
 
141
  cum_flow_individual = etf_flow_individual.drop(columns="Date").cumsum()
142
  cum_flow_individual["Date"] = etf_flow_individual.Date
143
+ cum_flow_total = pd.DataFrame(
144
+ {
145
+ "Date": etf_flow_total.Date,
146
+ "Total": etf_flow_total.Total.cumsum(),
147
+ }
148
+ )
149
 
150
  return SimpleNamespace(
151
  etf_flow=etf_flow,
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
  streamlit
2
  pandas
3
- yfinance
4
  altair
5
  vega
6
  workalendar
 
1
  streamlit
2
  pandas
3
+ yfinance[nospam,repair]==0.2.47
4
  altair
5
  vega
6
  workalendar
streamlit_app.py CHANGED
@@ -2,17 +2,23 @@ import pandas as pd
2
 
3
  import streamlit as st
4
  import altair as alt
5
- alt.renderers.set_embed_options(theme="dark")
6
  from pygwalker.api.streamlit import StreamlitRenderer, init_streamlit_comm
7
 
8
  from types import SimpleNamespace
9
 
10
  from df import fetch
11
 
 
 
 
 
 
 
12
 
13
  def gen_charts(asset, chart_size={"width": 560, "height": 300}):
14
  # Gen data
15
- data = fetch(asset)
16
  etf_volumes = data.etf_volumes
17
  price = data.price
18
  etf_flow_individual = data.etf_flow_individual
@@ -32,8 +38,8 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
32
  color="Funds:N",
33
  )
34
  ).properties(
35
- width=chart_size['width'],
36
- height=chart_size['height'] / 2,
37
  )
38
  trading_vol_total_fig = (
39
  alt.Chart(etf_volumes)
@@ -42,13 +48,13 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
42
  )
43
  .mark_rule()
44
  .encode(
45
- x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title='', labels=False)),
46
  y=alt.Y("sum(Volume):Q", title="Total Volume"),
47
  color=alt.value("teal"),
48
  )
49
  ).properties(
50
- width=chart_size['width'],
51
- height=chart_size['height'] / 2,
52
  )
53
  # Combine trading volume and average trading volume
54
  trading_vol_fig = trading_vol_total_fig & trading_vol_fig
@@ -70,14 +76,14 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
70
  color="Funds:N",
71
  )
72
  ).properties(
73
- width=chart_size['width'],
74
- height=chart_size['height'] / 2,
75
  )
76
  net_flow_total_fig = (
77
  alt.Chart(etf_flow_total)
78
  .mark_rule()
79
  .encode(
80
- x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title='', labels=False)),
81
  y=alt.Y("Total:Q"),
82
  color=alt.condition(
83
  alt.datum.Total > 0,
@@ -86,11 +92,13 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
86
  ),
87
  )
88
  ).properties(
89
- width=chart_size['width'],
90
- height=chart_size['height'] / 2,
91
  )
92
  net_flow_individual_fig = net_flow_total_fig & net_flow_individual_fig
93
- net_flow_individual_fig = net_flow_individual_fig.resolve_scale(x='shared').properties(
 
 
94
  title=f"{asset} ETF net flow of individual funds",
95
  )
96
 
@@ -98,7 +106,7 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
98
  alt.Chart(etf_flow_total)
99
  .mark_rule()
100
  .encode(
101
- x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title='', labels=False)),
102
  y=alt.Y("Total:Q"),
103
  color=alt.condition(
104
  alt.datum.Total > 0,
@@ -107,8 +115,8 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
107
  ),
108
  )
109
  ).properties(
110
- width=chart_size['width'],
111
- height=chart_size['height'] / 2,
112
  )
113
  # Line chart of price
114
  price_fig = (
@@ -120,12 +128,12 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
120
  color=alt.value("crimson"),
121
  )
122
  ).properties(
123
- width=chart_size['width'],
124
- height=chart_size['height'] / 2,
125
  )
126
 
127
  net_flow_total_fig = net_flow_total_fig & price_fig
128
- net_flow_total_fig = net_flow_total_fig.resolve_scale(x='shared').properties(
129
  title=f"{asset} ETF net flow total vs asset price",
130
  )
131
 
@@ -138,16 +146,18 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
138
  )
139
  .mark_area()
140
  .encode(
141
- x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title='', labels=False)),
142
  y=alt.Y("Net Flow:Q"),
143
  color=alt.Color("Funds:N", scale=alt.Scale(scheme="tableau20")),
144
  )
145
  ).properties(
146
- width=chart_size['width'],
147
- height=chart_size['height'] / 2,
148
  )
149
  cum_flow_individual_net_fig = cum_flow_individual_net_fig & price_fig
150
- cum_flow_individual_net_fig = cum_flow_individual_net_fig.resolve_scale(x='shared').properties(
 
 
151
  title=f"{asset} ETF cumulative flow of individual funds vs asset price",
152
  )
153
 
@@ -159,18 +169,18 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
159
  )
160
  .mark_area()
161
  .encode(
162
- x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title='', labels=False)),
163
  y=alt.Y("Total:Q", impute={"value": 0}),
164
  color=alt.Color(
165
  "negative:N", title="Negative Flow", scale=alt.Scale(scheme="set2")
166
  ),
167
  )
168
  ).properties(
169
- width=chart_size['width'],
170
- height=chart_size['height'] / 2,
171
  )
172
  cum_flow_total_fig = cum_flow_total_fig & price_fig
173
- cum_flow_total_fig = cum_flow_total_fig.resolve_scale(x='shared').properties(
174
  title=f"{asset} ETF cumulative flow total vs asset price",
175
  )
176
 
@@ -182,7 +192,8 @@ def gen_charts(asset, chart_size={"width": 560, "height": 300}):
182
  cum_flow_total_fig=cum_flow_total_fig,
183
  )
184
 
185
- def asset_charts(asset: str, chart_size={"width": 'container', "height": 300}):
 
186
  charts = gen_charts(asset, chart_size)
187
  # Vertical concat the charts in each asset into single column of that asset
188
  all_charts = (
@@ -195,31 +206,33 @@ def asset_charts(asset: str, chart_size={"width": 'container', "height": 300}):
195
 
196
  return all_charts
197
 
 
198
  def compound_chart(chart_size={"width": 560, "height": 300}):
199
- all_charts_btc = asset_charts('BTC', chart_size)
200
- all_charts_eth = asset_charts('ETH', chart_size)
201
  # Horizontal concat the charts for btc and eth
202
  all_charts = (all_charts_btc | all_charts_eth).resolve_scale(color="independent")
203
 
204
  return all_charts
205
 
206
-
207
  if __name__ == "__main__":
208
  # Set page config
209
  st.set_page_config(layout="wide", page_icon="πŸ“ˆ")
210
  # Initialize pygwalker communication
211
  init_streamlit_comm()
212
 
213
- dashboard_tab, single_view, flow_tab, volume_tab, price_tab = st.tabs([
214
- 'Dashboard',
215
- 'View Single ETF',
216
- 'Explore ETF Flow',
217
- 'Explore ETF Volume',
218
- 'Explore ETF Asset Price',
219
- ])
 
 
220
 
221
- btc = fetch('BTC')
222
- eth = fetch('ETH')
223
 
224
  with dashboard_tab:
225
  chart = compound_chart(chart_size={"width": 560, "height": 300})
@@ -227,33 +240,33 @@ if __name__ == "__main__":
227
  st.altair_chart(chart, use_container_width=True)
228
  with single_view:
229
  asset = st.selectbox(
230
- 'Asset to view',
231
- ('BTC', 'ETH'),
232
  )
233
- charts = gen_charts(asset, chart_size={"width": 'container', "height": 600})
234
- st.altair_chart(charts.trading_vol_fig, use_container_width = True)
235
- st.altair_chart(charts.net_flow_individual_fig, use_container_width = True)
236
- st.altair_chart(charts.net_flow_total_fig, use_container_width = True)
237
- st.altair_chart(charts.cum_flow_individual_net_fig, use_container_width = True)
238
- st.altair_chart(charts.cum_flow_total_fig, use_container_width = True)
239
  with flow_tab:
240
  btc_flow, eth_flow = btc.etf_flow, eth.etf_flow
241
- btc_flow['Asset'] = 'BTC'
242
- eth_flow['Asset'] = 'ETH'
243
  df = pd.concat([btc_flow, eth_flow])
244
  df.Date = df.Date.astype(str)
245
  StreamlitRenderer(df).explorer()
246
  with volume_tab:
247
  btc_volume, eth_volume = btc.etf_volumes, eth.etf_volumes
248
- btc_volume['Asset'] = 'BTC'
249
- eth_volume['Asset'] = 'ETH'
250
  df = pd.concat([btc_volume, eth_volume])
251
  df.Date = df.Date.astype(str)
252
  StreamlitRenderer(df).explorer()
253
  with price_tab:
254
  btc_price, eth_price = btc.price, eth.price
255
- btc_price['Asset'] = 'BTC'
256
- eth_price['Asset'] = 'ETH'
257
  df = pd.concat([btc_price, eth_price])
258
  df.Date = df.Date.astype(str)
259
  StreamlitRenderer(df).explorer()
 
2
 
3
  import streamlit as st
4
  import altair as alt
5
+
6
  from pygwalker.api.streamlit import StreamlitRenderer, init_streamlit_comm
7
 
8
  from types import SimpleNamespace
9
 
10
  from df import fetch
11
 
12
+ alt.renderers.set_embed_options(theme="dark")
13
+
14
+
15
+ @st.cache_data(ttl="30m")
16
+ def fetch_asset(asset):
17
+ return fetch(asset)
18
 
19
  def gen_charts(asset, chart_size={"width": 560, "height": 300}):
20
  # Gen data
21
+ data = fetch_asset(asset)
22
  etf_volumes = data.etf_volumes
23
  price = data.price
24
  etf_flow_individual = data.etf_flow_individual
 
38
  color="Funds:N",
39
  )
40
  ).properties(
41
+ width=chart_size["width"],
42
+ height=chart_size["height"] / 2,
43
  )
44
  trading_vol_total_fig = (
45
  alt.Chart(etf_volumes)
 
48
  )
49
  .mark_rule()
50
  .encode(
51
+ x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title="", labels=False)),
52
  y=alt.Y("sum(Volume):Q", title="Total Volume"),
53
  color=alt.value("teal"),
54
  )
55
  ).properties(
56
+ width=chart_size["width"],
57
+ height=chart_size["height"] / 2,
58
  )
59
  # Combine trading volume and average trading volume
60
  trading_vol_fig = trading_vol_total_fig & trading_vol_fig
 
76
  color="Funds:N",
77
  )
78
  ).properties(
79
+ width=chart_size["width"],
80
+ height=chart_size["height"] / 2,
81
  )
82
  net_flow_total_fig = (
83
  alt.Chart(etf_flow_total)
84
  .mark_rule()
85
  .encode(
86
+ x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title="", labels=False)),
87
  y=alt.Y("Total:Q"),
88
  color=alt.condition(
89
  alt.datum.Total > 0,
 
92
  ),
93
  )
94
  ).properties(
95
+ width=chart_size["width"],
96
+ height=chart_size["height"] / 2,
97
  )
98
  net_flow_individual_fig = net_flow_total_fig & net_flow_individual_fig
99
+ net_flow_individual_fig = net_flow_individual_fig.resolve_scale(
100
+ x="shared"
101
+ ).properties(
102
  title=f"{asset} ETF net flow of individual funds",
103
  )
104
 
 
106
  alt.Chart(etf_flow_total)
107
  .mark_rule()
108
  .encode(
109
+ x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title="", labels=False)),
110
  y=alt.Y("Total:Q"),
111
  color=alt.condition(
112
  alt.datum.Total > 0,
 
115
  ),
116
  )
117
  ).properties(
118
+ width=chart_size["width"],
119
+ height=chart_size["height"] / 2,
120
  )
121
  # Line chart of price
122
  price_fig = (
 
128
  color=alt.value("crimson"),
129
  )
130
  ).properties(
131
+ width=chart_size["width"],
132
+ height=chart_size["height"] / 2,
133
  )
134
 
135
  net_flow_total_fig = net_flow_total_fig & price_fig
136
+ net_flow_total_fig = net_flow_total_fig.resolve_scale(x="shared").properties(
137
  title=f"{asset} ETF net flow total vs asset price",
138
  )
139
 
 
146
  )
147
  .mark_area()
148
  .encode(
149
+ x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title="", labels=False)),
150
  y=alt.Y("Net Flow:Q"),
151
  color=alt.Color("Funds:N", scale=alt.Scale(scheme="tableau20")),
152
  )
153
  ).properties(
154
+ width=chart_size["width"],
155
+ height=chart_size["height"] / 2,
156
  )
157
  cum_flow_individual_net_fig = cum_flow_individual_net_fig & price_fig
158
+ cum_flow_individual_net_fig = cum_flow_individual_net_fig.resolve_scale(
159
+ x="shared"
160
+ ).properties(
161
  title=f"{asset} ETF cumulative flow of individual funds vs asset price",
162
  )
163
 
 
169
  )
170
  .mark_area()
171
  .encode(
172
+ x=alt.X("Date:T", axis=alt.Axis(tickCount="day", title="", labels=False)),
173
  y=alt.Y("Total:Q", impute={"value": 0}),
174
  color=alt.Color(
175
  "negative:N", title="Negative Flow", scale=alt.Scale(scheme="set2")
176
  ),
177
  )
178
  ).properties(
179
+ width=chart_size["width"],
180
+ height=chart_size["height"] / 2,
181
  )
182
  cum_flow_total_fig = cum_flow_total_fig & price_fig
183
+ cum_flow_total_fig = cum_flow_total_fig.resolve_scale(x="shared").properties(
184
  title=f"{asset} ETF cumulative flow total vs asset price",
185
  )
186
 
 
192
  cum_flow_total_fig=cum_flow_total_fig,
193
  )
194
 
195
+
196
+ def asset_charts(asset: str, chart_size={"width": "container", "height": 300}):
197
  charts = gen_charts(asset, chart_size)
198
  # Vertical concat the charts in each asset into single column of that asset
199
  all_charts = (
 
206
 
207
  return all_charts
208
 
209
+
210
  def compound_chart(chart_size={"width": 560, "height": 300}):
211
+ all_charts_btc = asset_charts("BTC", chart_size)
212
+ all_charts_eth = asset_charts("ETH", chart_size)
213
  # Horizontal concat the charts for btc and eth
214
  all_charts = (all_charts_btc | all_charts_eth).resolve_scale(color="independent")
215
 
216
  return all_charts
217
 
 
218
  if __name__ == "__main__":
219
  # Set page config
220
  st.set_page_config(layout="wide", page_icon="πŸ“ˆ")
221
  # Initialize pygwalker communication
222
  init_streamlit_comm()
223
 
224
+ dashboard_tab, single_view, flow_tab, volume_tab, price_tab = st.tabs(
225
+ [
226
+ "Dashboard",
227
+ "View Single ETF",
228
+ "Explore ETF Flow",
229
+ "Explore ETF Volume",
230
+ "Explore ETF Asset Price",
231
+ ]
232
+ )
233
 
234
+ btc = fetch_asset("BTC")
235
+ eth = fetch_asset("ETH")
236
 
237
  with dashboard_tab:
238
  chart = compound_chart(chart_size={"width": 560, "height": 300})
 
240
  st.altair_chart(chart, use_container_width=True)
241
  with single_view:
242
  asset = st.selectbox(
243
+ "Asset to view",
244
+ ("BTC", "ETH"),
245
  )
246
+ charts = gen_charts(asset, chart_size={"width": "container", "height": 600})
247
+ st.altair_chart(charts.trading_vol_fig, use_container_width=True)
248
+ st.altair_chart(charts.net_flow_individual_fig, use_container_width=True)
249
+ st.altair_chart(charts.net_flow_total_fig, use_container_width=True)
250
+ st.altair_chart(charts.cum_flow_individual_net_fig, use_container_width=True)
251
+ st.altair_chart(charts.cum_flow_total_fig, use_container_width=True)
252
  with flow_tab:
253
  btc_flow, eth_flow = btc.etf_flow, eth.etf_flow
254
+ btc_flow["Asset"] = "BTC"
255
+ eth_flow["Asset"] = "ETH"
256
  df = pd.concat([btc_flow, eth_flow])
257
  df.Date = df.Date.astype(str)
258
  StreamlitRenderer(df).explorer()
259
  with volume_tab:
260
  btc_volume, eth_volume = btc.etf_volumes, eth.etf_volumes
261
+ btc_volume["Asset"] = "BTC"
262
+ eth_volume["Asset"] = "ETH"
263
  df = pd.concat([btc_volume, eth_volume])
264
  df.Date = df.Date.astype(str)
265
  StreamlitRenderer(df).explorer()
266
  with price_tab:
267
  btc_price, eth_price = btc.price, eth.price
268
+ btc_price["Asset"] = "BTC"
269
+ eth_price["Asset"] = "ETH"
270
  df = pd.concat([btc_price, eth_price])
271
  df.Date = df.Date.astype(str)
272
  StreamlitRenderer(df).explorer()