-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathparse.py
More file actions
121 lines (104 loc) · 3.71 KB
/
parse.py
File metadata and controls
121 lines (104 loc) · 3.71 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/bin/python3
import glob
import csv
from typing import List, Dict
from dataclasses import dataclass
from argparse import ArgumentParser
from datetime import date, datetime
import matplotlib.pyplot as plt
### models ###
@dataclass
class StockItem:
name: str
isin: str
rate_ct: int
pieces_100: int
def total_ct(self):
return self.rate_ct * self.pieces_100 / 100
@dataclass
class Report:
date: date
items: List[StockItem]
def __str__(self):
# tiny bit of formatting
ret = "Report(date=" + self.date.isoformat() + ", items=[\n"
for p in self.items:
ret += "\t" + str(p) + ",\n"
ret += "])"
return ret
### helper functions ###
def parseReport(f) -> Report:
cr = csv.reader(f, delimiter=";", quotechar="\"")
row_list = [x for x in cr]
# line 4 (3 if counted from 0)
date = datetime.strptime(row_list[3][1], "%d.%m.%Y %H:%M")
# actual listing starts at 7 (6 if from 0)
items = []
for i in range(6, len(row_list)):
r = row_list[i]
items.append(StockItem(r[3], r[2], int(r[4].replace(",", "")),
int(r[0].replace(",", ""))))
return Report(date, items)
def create_time_series(p_fun) -> Dict:
# build a time series to make pyplot happy
named_data_series = {}
for r in list_of_reports:
for p in r.items:
if p.name in named_data_series:
named_data_series[p.name].append((r.date, p_fun(p)))
else:
named_data_series[p.name] = [(r.date, p_fun(p))]
return named_data_series
### main code ###
arg_parser = ArgumentParser(
description="Small parser/visualization tool for the DKB stock/portfolio CSV export")
arg_parser.add_argument("-f", help="path to the folder with the csv [f]iles",
required=True)
arg_parser.add_argument("-t", action='store_true', help="draw [t]otal values")
arg_parser.add_argument("-n", action='store_true', help="draw [n]umber of shares/...")
arg_parser.add_argument("-r", action='store_true', help="draw [r]ate of items")
arg_parser.add_argument("-d", action='store_true', help="[d]ump parsed data (for debugging)")
args = arg_parser.parse_args()
# find files, read and parse
csv_file_names = glob.glob(glob.escape(args.f) + "/*.csv")
list_of_reports = []
for fn in csv_file_names:
with open(fn, "r", encoding="ISO-8859-1") as f:
list_of_reports.append(parseReport(f))
# enforce some sorting
list_of_reports.sort(key=lambda r: r.date)
for r in list_of_reports:
r.items.sort(key=lambda r: r.isin)
if args.d:
for report in list_of_reports:
print(report)
list_of_time_series = []
names_of_plots = []
if args.t:
list_of_time_series.append(create_time_series(lambda p: p.total_ct()/100))
names_of_plots.append("Total Values")
if args.n:
list_of_time_series.append(create_time_series(lambda p: p.pieces_100/100))
names_of_plots.append("Numbers of Shares/...")
if args.r:
list_of_time_series.append(create_time_series(lambda p: p.rate_ct/100))
names_of_plots.append("Rates per Item")
lstyles = ["solid", "dashed", "dashdot", "dotted"]
fig, axs = plt.subplots(len(list_of_time_series), 1, sharex=True)
# edge case, if we only have one plot, it will not return an array, so let's make it into one
if len(list_of_time_series) == 1:
tmp = fig
fig = [tmp]
tmp = axs
axs = [tmp]
# actual drawing
for i in range(0, len(list_of_time_series)):
ts = list_of_time_series[i]
for n in ts:
axs[i].step([x[0] for x in ts[n]],
[x[1] for x in ts[n]],
label=n, marker="x", ls=lstyles[i])
axs[i].set_title(names_of_plots[i])
axs[i].grid(True)
axs[i].legend()
plt.show()