add pretty-report program
This commit is contained in:
parent
b8b3d40ece
commit
5ba20a2563
137
pretty-report/__main__.py
Normal file
137
pretty-report/__main__.py
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
|
import dash
|
||||||
|
from dash import dcc, html
|
||||||
|
import pandas as pd
|
||||||
|
import plotly.graph_objects as go
|
||||||
|
import plotly.express as px
|
||||||
|
|
||||||
|
def numerize(df, column):
|
||||||
|
if isinstance(column, list):
|
||||||
|
for item in column:
|
||||||
|
df = numerize(df, item)
|
||||||
|
else:
|
||||||
|
df[column] = pd.to_numeric(df[column], errors="coerce")
|
||||||
|
return df
|
||||||
|
|
||||||
|
data = []
|
||||||
|
with open("financials.txt", "r") as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line == "":
|
||||||
|
pass
|
||||||
|
elif line.startswith("#"):
|
||||||
|
data.append([])
|
||||||
|
else:
|
||||||
|
data[-1].append(line.split(","))
|
||||||
|
|
||||||
|
asset = numerize(pd.DataFrame(data[0], columns=["Name", "Amount"]), "Amount")
|
||||||
|
debt = numerize(pd.DataFrame(data[2], columns=["Name", "Amount"]), "Amount")
|
||||||
|
net = numerize(pd.DataFrame(data[3], columns=["Name", "Amount"]), "Amount")
|
||||||
|
|
||||||
|
expense = numerize(pd.DataFrame(data[4], columns=["Name", "Amount"]), "Amount")
|
||||||
|
revenue = numerize(pd.DataFrame(data[5], columns=["Name", "Amount"]), "Amount")
|
||||||
|
|
||||||
|
inv_asset = numerize(pd.DataFrame(data[1], columns=["Name", "Amount"]), "Amount")
|
||||||
|
inv_expense = numerize(pd.DataFrame(data[7], columns=["Name", "Amount"]), "Amount")
|
||||||
|
inv_revenue = numerize(pd.DataFrame(data[8], columns=["Name", "Amount"]), "Amount")
|
||||||
|
|
||||||
|
food_expense = numerize(pd.DataFrame(data[6], columns=["Name", "Amount"]), "Amount")
|
||||||
|
|
||||||
|
daily = numerize(pd.DataFrame(data[9], columns=["Date", "Asset", "RealNet", "Risked"]), ["Asset", "RealNet", "Risked"])
|
||||||
|
|
||||||
|
# ---- displaying ----
|
||||||
|
def PieAndTable(title, data):
|
||||||
|
total = sum(data["Amount"])
|
||||||
|
|
||||||
|
fig = px.pie(
|
||||||
|
data.sort_values(by="Amount", ascending=False),
|
||||||
|
names="Name",
|
||||||
|
values="Amount",
|
||||||
|
hole=0.5,
|
||||||
|
hover_name="Name",
|
||||||
|
title=title,
|
||||||
|
)
|
||||||
|
fig.update_traces(
|
||||||
|
hovertemplate="%{label}<br>%{value} (%{percent})",
|
||||||
|
textinfo="label",
|
||||||
|
)
|
||||||
|
fig.update_layout(
|
||||||
|
annotations=[
|
||||||
|
dict(
|
||||||
|
x=0.5, y=0.5,
|
||||||
|
text=f"{total:,}",
|
||||||
|
showarrow=False,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
showlegend=False,
|
||||||
|
)
|
||||||
|
return dcc.Graph(
|
||||||
|
style={"flex": "1", "height": "20rem"},
|
||||||
|
figure=fig,
|
||||||
|
)
|
||||||
|
def PlWaterfall(title, e, r):
|
||||||
|
merged = pd.merge(e, r, on="Name", suffixes=["E", "R"], how="outer")
|
||||||
|
merged["Amount"] = merged["AmountR"].fillna(0) - merged["AmountE"].fillna(0)
|
||||||
|
merged = merged.sort_values(by="Amount", ascending=False)
|
||||||
|
|
||||||
|
fig = go.Figure(go.Waterfall(
|
||||||
|
orientation="v",
|
||||||
|
x=merged["Name"],
|
||||||
|
y=merged["Amount"],
|
||||||
|
))
|
||||||
|
fig.update_layout(title=title)
|
||||||
|
return dcc.Graph(figure=fig)
|
||||||
|
|
||||||
|
def DailyLines(df):
|
||||||
|
fig = go.Figure()
|
||||||
|
fig.add_trace(go.Scatter(
|
||||||
|
x=df["Date"],
|
||||||
|
y=df["Asset"],
|
||||||
|
mode="lines",
|
||||||
|
name="Total"
|
||||||
|
))
|
||||||
|
fig.add_trace(go.Scatter(
|
||||||
|
x=df["Date"],
|
||||||
|
y=df["RealNet"],
|
||||||
|
mode="lines",
|
||||||
|
name="Realtime Net"
|
||||||
|
))
|
||||||
|
fig.add_trace(go.Scatter(
|
||||||
|
x=df["Date"],
|
||||||
|
y=df["Risked"],
|
||||||
|
mode="lines",
|
||||||
|
name="Risked"
|
||||||
|
))
|
||||||
|
fig.update_layout(hovermode="x unified")
|
||||||
|
return dcc.Graph(figure=fig)
|
||||||
|
|
||||||
|
app = dash.Dash(__name__)
|
||||||
|
app.layout = html.Div([
|
||||||
|
html.H2("WHOLE"),
|
||||||
|
html.Div(
|
||||||
|
style={"display": "flex", "gap": "1rem"},
|
||||||
|
children=[
|
||||||
|
PieAndTable("Asset", asset),
|
||||||
|
PieAndTable("Debt", debt),
|
||||||
|
PieAndTable("Net", net),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
PlWaterfall("P&L", expense, revenue),
|
||||||
|
|
||||||
|
html.H2("DAILY"),
|
||||||
|
html.Div(children=[
|
||||||
|
DailyLines(daily),
|
||||||
|
]),
|
||||||
|
|
||||||
|
html.H2("DETAILS"),
|
||||||
|
html.Div(
|
||||||
|
style={"display": "flex", "gap": "1rem"},
|
||||||
|
children=[
|
||||||
|
PieAndTable("Food Expenses", food_expense),
|
||||||
|
PieAndTable("RiskedAsset", inv_asset),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
PlWaterfall("Investment P&L", inv_expense, inv_revenue),
|
||||||
|
])
|
||||||
|
app.run(debug=True)
|
@ -1,2 +1,3 @@
|
|||||||
numpy
|
pandas
|
||||||
matplotlib
|
plotly
|
||||||
|
dash
|
||||||
|
Loading…
x
Reference in New Issue
Block a user