Skip to content

Commit dc3b72d

Browse files
tilidevmarzzzello
andauthored
Add option to save portfolio to csv (#54)
* Add option to save portfolio to csv - add portfolio_to_csv method to Portfolio class - extend argument parsing with path option for saving csv - portfolio_to_csv executes after get() method when path for saving csv is provided * use output_path only in csv function * rm whitespace --------- Co-authored-by: marzzzello <[email protected]>
1 parent 4e3f141 commit dc3b72d

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

pytr/main.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,16 @@ def formatter(prog):
9494
parser_dl_docs.add_argument('--universal', help='Platform independent file names', action='store_true')
9595
# portfolio
9696
info = 'Show current portfolio'
97-
parser_cmd.add_parser(
97+
parser_portfolio = parser_cmd.add_parser(
9898
'portfolio',
9999
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
100100
parents=[parser_login_args],
101101
help=info,
102102
description=info,
103103
)
104+
parser_portfolio.add_argument(
105+
'-o', '--output', help='Output path of CSV file', metavar='OUTPUT', type=Path
106+
)
104107
# details
105108
info = 'Get details for an ISIN'
106109
parser_details = parser_cmd.add_parser(
@@ -214,7 +217,10 @@ def main():
214217
elif args.command == 'details':
215218
Details(login(phone_no=args.phone_no, pin=args.pin, web=not args.applogin), args.isin).get()
216219
elif args.command == 'portfolio':
217-
Portfolio(login(phone_no=args.phone_no, pin=args.pin, web=not args.applogin)).get()
220+
p = Portfolio(login(phone_no=args.phone_no, pin=args.pin, web=not args.applogin), args.output)
221+
p.get()
222+
if args.output is not None:
223+
p.portfolio_to_csv()
218224
elif args.command == 'export_transactions':
219225
export_transactions(args.input, args.output, args.lang)
220226
elif args.version:

pytr/portfolio.py

+14
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,20 @@ async def portfolio_loop(self):
7676
else:
7777
print(f"unmatched subscription of type '{subscription['type']}':\n{preview(response)}")
7878

79+
def portfolio_to_csv(self, output_path):
80+
positions = self.portfolio['positions']
81+
csv_lines = []
82+
for pos in sorted(positions, key=lambda x: x['netSize'], reverse=True):
83+
csv_lines.append(
84+
f"{pos['name']};{pos['instrumentId']};{float(pos['averageBuyIn']):.2f};{float(pos['netValue']):.2f}"
85+
)
86+
87+
with open(output_path, 'w', encoding='utf-8') as f:
88+
f.write('Name;ISIN;avgCost;netValue\n')
89+
f.write('\n'.join(csv_lines))
90+
91+
print(f'Wrote {len(csv_lines) + 1} lines to {self.output_path}')
92+
7993
def overview(self):
8094
# for x in ['netValue', 'unrealisedProfit', 'unrealisedProfitPercent', 'unrealisedCost']:
8195
# print(f'{x:24}: {self.portfolio[x]:>10.2f}')

0 commit comments

Comments
 (0)