-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfinances.py
78 lines (63 loc) · 2.1 KB
/
finances.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import argparse
import json
from collections.abc import Sequence
from typing import TypedDict
import polars as pl
import seaborn.objects as so
__all__ = ("plot", "read_data")
class NamesDict(TypedDict):
assets: list[str]
liabilities: list[str]
def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--csv", default="balance-sheet.csv")
parser.add_argument("--names", default="names.json")
args = parser.parse_args(argv)
with open(args.names) as f:
names = json.load(f)
data = read_data(args.csv, names)
plot(data, names["assets"])
return 0
def plot(df: pl.DataFrame, asset_names: list[str]) -> None:
so.Plot(df, "Date", "Change").add(so.Line()).scale(
y=so.Continuous().label(like="${x:,g}")
).save("change")
so.Plot(df, "Date", "PctChange").add(so.Line()).scale(
y=so.Continuous().label(like="{x:.0%}")
).label(y="Percent change").save("pct-change")
(
so.Plot(
df.melt(
id_vars="Date",
value_vars=asset_names,
),
"Date",
"value",
color="variable",
)
.add(so.Area(alpha=0.9), so.Stack())
.scale(
y=so.Continuous().label(like="${x:,g}"),
)
.label(color="Asset class", y="Amount")
).save("stacked", bbox_inches="tight")
def read_data(csv: str, names: NamesDict) -> pl.DataFrame:
return (
pl.read_csv(csv)
.select(
pl.col("Date").str.to_date("%m/%d/%Y"),
pl.exclude("Date", "Total", "Change", "Notes")
.str.replace_all("[$,]", "")
.cast(pl.Float64), # str.to_decimal() messes up converting to pandas
)
.with_columns(
Total=pl.sum_horizontal(pl.exclude("Date", *names["liabilities"]))
- pl.sum_horizontal(pl.col(names["liabilities"]))
)
.with_columns(
PctChange=pl.col("Total").pct_change(),
Change=pl.col("Total").diff(),
)
)
if __name__ == "__main__":
raise SystemExit(main())