mirror of
https://github.com/d0zingcat/deploy.git
synced 2026-05-13 23:16:53 +00:00
155 lines
6.2 KiB
Python
155 lines
6.2 KiB
Python
from frontend.st_utils import initialize_st_page, get_backend_api_client
|
|
import streamlit as st
|
|
import pandas as pd
|
|
import plotly.graph_objects as go
|
|
import plotly.express as px
|
|
|
|
initialize_st_page(title="Portfolio", icon="💰")
|
|
|
|
# Page content
|
|
client = get_backend_api_client()
|
|
NUM_COLUMNS = 4
|
|
|
|
|
|
# Convert balances to a DataFrame for easier manipulation
|
|
def account_state_to_df(account_state):
|
|
data = []
|
|
for account, exchanges in account_state.items():
|
|
for exchange, tokens_info in exchanges.items():
|
|
for info in tokens_info:
|
|
data.append({
|
|
"account": account,
|
|
"exchange": exchange,
|
|
"token": info["token"],
|
|
"price": info["price"],
|
|
"units": info["units"],
|
|
"value": info["value"],
|
|
"available_units": info["available_units"],
|
|
})
|
|
return pd.DataFrame(data)
|
|
|
|
|
|
# Convert historical account states to a DataFrame
|
|
def account_history_to_df(history):
|
|
data = []
|
|
for record in history:
|
|
timestamp = record["timestamp"]
|
|
for account, exchanges in record["state"].items():
|
|
for exchange, tokens_info in exchanges.items():
|
|
for info in tokens_info:
|
|
data.append({
|
|
"timestamp": timestamp,
|
|
"account": account,
|
|
"exchange": exchange,
|
|
"token": info["token"],
|
|
"price": info["price"],
|
|
"units": info["units"],
|
|
"value": info["value"],
|
|
"available_units": info["available_units"],
|
|
})
|
|
return pd.DataFrame(data)
|
|
|
|
|
|
# Fetch account state from the backend
|
|
account_state = client.get_accounts_state()
|
|
account_history = client.get_account_state_history()
|
|
if len(account_state) == 0:
|
|
st.warning("No accounts found.")
|
|
st.stop()
|
|
|
|
# Display the accounts available
|
|
accounts = st.multiselect("Select Accounts", list(account_state.keys()), list(account_state.keys()))
|
|
if len(accounts) == 0:
|
|
st.warning("Please select an account.")
|
|
st.stop()
|
|
|
|
# Display the exchanges available
|
|
exchanges_available = []
|
|
for account in accounts:
|
|
exchanges_available += account_state[account].keys()
|
|
|
|
if len(exchanges_available) == 0:
|
|
st.warning("No exchanges found.")
|
|
st.stop()
|
|
exchanges = st.multiselect("Select Exchanges", exchanges_available, exchanges_available)
|
|
|
|
# Display the tokens available
|
|
tokens_available = []
|
|
for account in accounts:
|
|
for exchange in exchanges:
|
|
if exchange in account_state[account]:
|
|
tokens_available += [info["token"] for info in account_state[account][exchange]]
|
|
|
|
token_options = set(tokens_available)
|
|
tokens_available = st.multiselect("Select Tokens", token_options, token_options)
|
|
|
|
|
|
st.write("---")
|
|
|
|
filtered_account_state = {}
|
|
for account in accounts:
|
|
filtered_account_state[account] = {}
|
|
for exchange in exchanges:
|
|
if exchange in account_state[account]:
|
|
filtered_account_state[account][exchange] = [token_info for token_info in account_state[account][exchange] if token_info["token"] in tokens_available]
|
|
|
|
filtered_account_history = []
|
|
for record in account_history:
|
|
filtered_record = {"timestamp": record["timestamp"], "state": {}}
|
|
for account in accounts:
|
|
if account in record["state"]:
|
|
filtered_record["state"][account] = {}
|
|
for exchange in exchanges:
|
|
if exchange in record["state"][account]:
|
|
filtered_record["state"][account][exchange] = [token_info for token_info in record["state"][account][exchange] if token_info["token"] in tokens_available]
|
|
filtered_account_history.append(filtered_record)
|
|
|
|
if len(filtered_account_state) > 0:
|
|
account_state_df = account_state_to_df(filtered_account_state)
|
|
total_balance_usd = round(account_state_df["value"].sum(), 2)
|
|
c1, c2 = st.columns([1, 5])
|
|
with c1:
|
|
st.metric("Total Balance (USD)", total_balance_usd)
|
|
with c2:
|
|
account_state_df['% Allocation'] = (account_state_df['value'] / total_balance_usd) * 100
|
|
account_state_df['label'] = account_state_df['token'] + ' ($' + account_state_df['value'].apply(
|
|
lambda x: f'{x:,.2f}') + ')'
|
|
|
|
# Create a sunburst chart with Plotly Express
|
|
fig = px.sunburst(account_state_df,
|
|
path=['account', 'exchange', 'label'],
|
|
values='value',
|
|
hover_data={'% Allocation': ':.2f'},
|
|
title='% Allocation by Account, Exchange, and Token',
|
|
color='account',
|
|
color_discrete_sequence=px.colors.qualitative.Vivid)
|
|
|
|
fig.update_traces(textinfo='label+percent entry')
|
|
|
|
fig.update_layout(margin=dict(t=0, l=0, r=0, b=0), height=800, title_x=0.01, title_y=1,)
|
|
|
|
st.plotly_chart(fig, use_container_width=True)
|
|
|
|
st.dataframe(account_state_df[['exchange', 'token', 'units', 'price', 'value', 'available_units']], width=1800,
|
|
height=600)
|
|
|
|
# Plot the evolution of the portfolio over time
|
|
if len(filtered_account_history) > 0:
|
|
account_history_df = account_history_to_df(filtered_account_history)
|
|
account_history_df['timestamp'] = pd.to_datetime(account_history_df['timestamp'])
|
|
|
|
# Aggregate the value of the portfolio over time
|
|
portfolio_evolution_df = account_history_df.groupby('timestamp')['value'].sum().reset_index()
|
|
|
|
fig = px.line(portfolio_evolution_df, x='timestamp', y='value', title='Portfolio Evolution Over Time')
|
|
fig.update_layout(xaxis_title='Time', yaxis_title='Total Value (USD)', height=600)
|
|
st.plotly_chart(fig, use_container_width=True)
|
|
|
|
# Plot the evolution of each token's value over time
|
|
token_evolution_df = account_history_df.groupby(['timestamp', 'token'])['value'].sum().reset_index()
|
|
|
|
fig = px.area(token_evolution_df, x='timestamp', y='value', color='token', title='Token Value Evolution Over Time',
|
|
color_discrete_sequence=px.colors.qualitative.Vivid)
|
|
fig.update_layout(xaxis_title='Time', yaxis_title='Value (USD)', height=600)
|
|
st.plotly_chart(fig, use_container_width=True)
|