cryptoTester / aggrid_viewer.py
SamHastings1088's picture
first commit
642c876
import streamlit as st
import plotly.express as px
from datetime import date, timedelta
from data_creator import create_market_cap_dict, gen_rebased_df, ids2names_dict, names2ids_dict, create_assets, gen_symbols, create_histories_df, create_unix_dates, create_returns_df, create_rebased_df, date_range
from plot_creator import get_pre_selected_idx, write_coins, write_coins_custom, write_bespoke_coins, create_comparison_df, load_images, gen_performance_ag_df, add_drawdown
from port_creator import gen_all_returns, markowitz_weights_dict, uniform_weights_dict, ids_with_histories, uniform, create_port_rtns, markowitz_weights, create_weights_df
from risk_metrics import max_drawdown
from st_aggrid import AgGrid, GridOptionsBuilder
from persist import persist, load_widget_state
load_widget_state()
st.markdown(
"""
<style>
.css-1xsoh1l {
font-size: 0px;
}
.css-1xsoh1l{
color: rgb(120 190 33);
}
.css-jhf39w {
color: rgba(120, 190, 33, 1);
}
.css-jv3mmh {
background-color: rgb(120, 190, 33);
}
</style>
""",
unsafe_allow_html = True
)
# load start and end dates for investment analysis
lookback_years = 5 # max date range for backtest will be: lookback_years - 1
start_date = date.today() - timedelta(365)
end_date = date.today()
if 'start_date' not in st.session_state:
st.session_state.start_date = start_date
st.session_state.end_date = end_date
if 'max_coins' not in st.session_state:
st.session_state.max_coins = 10
if 'start_id' not in st.session_state:
st.session_state.start_id = 1
# Pull down histories from coincap, and create dataframes for historic prices,
# returns and rebased cumulative price; histories_df, returns_df, and
# rebased_df, respectively.
assets_json = create_assets(total_coins=50)
symbols, names, coin_ids = gen_symbols(assets_json)
ids2symbols = ids2names_dict(coin_ids, symbols)
ids2names_dict=ids2names_dict(coin_ids, names)
names2ids_dict = names2ids_dict(names, coin_ids)
market_cap_dict = create_market_cap_dict(assets_json)
start_unix, end_unix = create_unix_dates(today=date.today(), lookback_years=lookback_years)
histories_df = create_histories_df(coin_ids, start_unix, end_unix)
# Create list of coin ids with full hisoties over the backtest period
ids_with_histories = ids_with_histories(histories_df,
st.session_state.start_date, st.session_state.end_date)
names_with_histories = list(map(ids2names_dict.get, ids_with_histories))
def change_date_range():
st.session_state.start_date = st.session_state.myslider[0]
st.session_state.end_date = st.session_state.myslider[1]
# calculate weghts for the uniform and markowitz pfs
uniform_weights_dict = uniform_weights_dict(ids_with_histories[:st.session_state.max_coins])
#markowitz_weights_dict = markowitz_weights_dict(histories_df,
# st.session_state.start_date ,ids_with_histories[:max_coins], analysis_days=365)
strategy_dict = {'Uniform': uniform_weights_dict}#, 'Markowitz':markowitz_weights_dict}
if "strategy_dict" not in st.session_state:
st.session_state.strategy_dict=strategy_dict
if 'selected_assets' not in st.session_state:
st.session_state.selected_assets = ["Uniform"]
with st.sidebar:
st.subheader("Portfolio weights viewer")
portfolio_type = st.selectbox(
'Select portfolio strategy',
['Create your own'] + (list(st.session_state.strategy_dict.keys())),
index = st.session_state.start_id
)
if st.checkbox("Explain this"):
st.subheader("What's this all about then, eh?")
st.write('''
The app allows you to construct your own portfolios of crypto currencies and view their
historic performance alongside the performance of individual crypto
currencies over an investment period of your choosing.
To view the assets and weights comprising a particular portfolio select the
portfolio of interest in the 'Select portfolio strategy' dropdown (a uniform
portfolio for the top ten largest coins has been automatically created for you
to start with).
To create your own portfolio:
1. Select 'Create your own' in the 'select portfolio strategy' dropdown;
2. Select the maximum number of coins in your portfolio;
3. Select the relative weights for each of these assets;
4. Choose a name for your portfolio and click add portfolio;
5. Click update viewer;
You can sort and filter the performance metrics table on each of the columns.
To add an asset to the performance chart, select the corresponding select box.
''')
# Add select slider to allow
date_list = date_range(end_date,lookback_years-1)
start_port_date, end_port_date = st.select_slider(
'Select backtest date range',
key="myslider",
options=date_list,
#value=(date.today() - timedelta(365), date.today()),
value = (st.session_state.start_date, st.session_state.end_date),
on_change=change_date_range
)
# Move the definition of strategy_dict to about the potfolio_type selectbox
# This will require that you define max_coins in session state,a dn the
# have the max_coins number_input update the max coins session state.
# = 10 and let it be
# calculate returns for the portfolios and add to it the rebased df for assets
# with hisories. This is the new returns_df
rebased_df = gen_rebased_df(histories_df, ids_with_histories,
st.session_state.start_date, st.session_state.end_date)
all_returns_df = gen_all_returns(rebased_df, ids_with_histories,st.session_state.strategy_dict)
def write_something():
st.write("")
def rerun_aggrid():
st.session_state.selected_indexes = selected_indexes
st.session_state.performance_ag_df = gen_performance_ag_df(all_returns_df, market_cap_dict,
st.session_state.strategy_dict)
st.header('ran')
if portfolio_type == 'Create your own':
with st.sidebar:
st.session_state.max_coins = st.number_input(
"Maximum number of coins in portfolio",
min_value=1,
max_value=20,
value=10,
help='''
Coins will be added to your "investment set" in order of largest market cap.
The "investment set" is the group of assets from which your portfolio is
constructed. Depending on the portfolio strategy you choose, not all of the
assets in your investment set will be included in your portfolio.
'''
)
st.markdown("Bespoke portfolio weights (relative):" , unsafe_allow_html=False)
bespoke_weights = write_coins_custom(names_with_histories[:st.session_state.max_coins])
#bespoke_weights = write_bespoke_coins(names_with_histories[:st.session_state.max_coins])
bespoke_cols = st.columns(2)
bespoke_cols[0].write(" ")
bespoke_cols[0].write(" ")
add_bespoke = bespoke_cols[0].button("Add portfolio", key='bespoke_button')
bespoke_name = bespoke_cols[1].text_input("Choose portfolio name")
if add_bespoke:
if bespoke_name=="" or bespoke_name in all_returns_df.columns:
st.warning("Please give your portfolio a unique name")
else:
beskpoke_weights_dict={}
for i, wt in enumerate(bespoke_weights):
beskpoke_weights_dict[coin_ids[i]] = wt
st.session_state.strategy_dict[bespoke_name] = beskpoke_weights_dict
st.session_state.start_id = len(st.session_state.strategy_dict)
#st.session_state.selected_assets.append(bespoke_name)
st.success("Porfolio added, update viewer to see results")
#st.button('Update viewer', on_click = change_date_range)
st.button('Update viewer', on_click = rerun_aggrid)
#st.button('Update viewer', on_click = st.experimental_rerun())
#st.write(st.session_state.strategy_dict)
else:
non_zero_coins = [key for key in st.session_state.strategy_dict[portfolio_type].keys() if st.session_state.strategy_dict[portfolio_type][key]>0]
with st.sidebar:
st.markdown(portfolio_type + " portfolio weights (%):" , unsafe_allow_html=False)
write_coins(non_zero_coins, st.session_state.strategy_dict[portfolio_type], ids2names_dict)
st.session_state.performance_ag_df = gen_performance_ag_df(all_returns_df, market_cap_dict,
st.session_state.strategy_dict)
if 'selected_assets' not in st.session_state:
st.session_state.selected_assets = ["Uniform"]
selected_indexes = []
for asset in st.session_state.selected_assets:
try:
selected_indexes.append(list(st.session_state.performance_ag_df['Asset']).index(asset))
except:
pass
if 'selected_indexes' not in st.session_state:
st.session_state.selected_indexes = selected_indexes
gb = GridOptionsBuilder.from_dataframe(st.session_state.performance_ag_df)
gb.configure_selection('multiple', use_checkbox=True,
pre_selected_rows = st.session_state.selected_indexes)
gridOptions = gb.build()
st.subheader("Performance metrics")
grid_response = AgGrid(st.session_state.performance_ag_df, gridOptions=gridOptions,
data_return_mode = 'FILTERED', allow_unsafe_jscode=True, height = 200,
update_mode='MODEL_CHANGED', key = persist("aggrid")) # MANUAL SELECTION_CHANGED MODEL_CHANGED, VALUE_CHANGED
selected_assets = []
for row in grid_response['selected_rows']:
selected_assets.append(row['Asset'])
st.session_state.selected_assets = selected_assets
#selected_indexes = []
#for asset in st.session_state.selected_assets:
# selected_indexes.append(list(performance_ag_df['Asset']).index(asset))
chart_df = create_comparison_df(all_returns_df, st.session_state.selected_assets)
fig = px.line(chart_df, x=chart_df.index, y='Value (USD)', color='Asset')
st.subheader("Performance chart")
st.write(fig)