From 5ba20a25637b3d5999582a80faaa36e20ffae119 Mon Sep 17 00:00:00 2001 From: falsycat Date: Sat, 19 Jul 2025 19:59:17 +0900 Subject: [PATCH] add pretty-report program --- pretty-report/__main__.py | 137 ++++++++++++++++++++++++++++++++++++++ requirements.txt | 5 +- 2 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 pretty-report/__main__.py diff --git a/pretty-report/__main__.py b/pretty-report/__main__.py new file mode 100644 index 0000000..cb6c9d1 --- /dev/null +++ b/pretty-report/__main__.py @@ -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}
%{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) diff --git a/requirements.txt b/requirements.txt index aa094d9..b686c0e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -numpy -matplotlib +pandas +plotly +dash