Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,18 @@ If you want to use the cutting-edge version, use this command instead:
<!-- runcmd code:console uv run --python 3.13 pytr help --for-readme -->
```console
usage: pytr [-h] [-V] [-v {warning,info,debug}] [--debug-logfile DEBUG_LOGFILE] [--debug-log-filter DEBUG_LOG_FILTER]
{help,login,portfolio,details,dl_docs,export_transactions,get_price_alarms,set_price_alarms,get_savings_plans,completion} ...
{help,login,portfolio,rates,details,dl_docs,export_transactions,get_price_alarms,set_price_alarms,get_savings_plans,completion} ...

Use "pytr command_name --help" to get detailed help to a specific command

Commands:
{help,login,portfolio,details,dl_docs,export_transactions,get_price_alarms,set_price_alarms,get_savings_plans,completion}
{help,login,portfolio,rates,details,dl_docs,export_transactions,get_price_alarms,set_price_alarms,get_savings_plans,completion}
Desired action to perform
help Print this help message
login Check if credentials file exists. If not create it and ask for input. Try to
login. Ask for device reset if needed
portfolio Show current portfolio
rates Fetch current prices for a list of ISINs given as direct list or CSV input
details Get details for an ISIN
dl_docs Download all pdf documents from the timeline and sort them into folders. Also
export account transactions (account_transactions.csv) and JSON files with all
Expand Down
80 changes: 76 additions & 4 deletions pytr/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import argparse
import asyncio
import re
import shutil
import signal
import sys
Expand All @@ -17,6 +18,7 @@
from pytr.dl import DL
from pytr.event import Event
from pytr.portfolio import PORTFOLIO_COLUMNS, Portfolio
from pytr.rates import RATE_COLUMNS, Rates, parse_isin_input
from pytr.savings_plans import SavingsPlans
from pytr.timeline import Timeline
from pytr.transactions import SUPPORTED_LANGUAGES, TransactionExporter
Expand Down Expand Up @@ -155,13 +157,19 @@ def formatter(prog):
default=False,
help="Include watchlist.",
)
parser_portfolio.add_argument(
"--ignore",
default=None,
metavar="ISINS",
help="Semicolon or comma separated list of ISINs to exclude from the portfolio, e.g. --ignore US30303M1027;DE0005140008",
)
parser_portfolio.add_argument("-o", "--output", help="Output path of CSV file", type=Path)
parser_portfolio.add_argument(
"--sort-by-column",
type=str.lower,
choices=[col.lower() for col in PORTFOLIO_COLUMNS],
default=None,
help="Sort results by column.",
type=str,
choices=list(PORTFOLIO_COLUMNS),
default="netValue",
help="Sort results by column (default: netValue).",
)
parser_portfolio.add_argument(
"--sort-ascending",
Expand All @@ -170,6 +178,50 @@ def formatter(prog):
help="Whether to sort in ascending order.",
)

# rates
info = "Fetch current prices for a list of ISINs given as direct list or CSV input"
parser_rates = parser_cmd.add_parser(
"rates",
formatter_class=formatter,
parents=[parser_login_args, parser_lang, parser_decimal_localization],
help=info,
description=info,
)
parser_rates.add_argument(
"input",
nargs="*",
help="ISINs to fetch prices for; comma, semicolon or space separated, e.g. DE0005140008,US0378331005",
default=[],
)
parser_rates.add_argument(
"-i",
"--inputfile",
help="Input file containing ISINs — comma, semicolon, whitespace or newline separated. Used when no ISINs given as positional args. Use '-' for stdin.",
type=argparse.FileType("r", encoding="utf-8"),
default=None,
nargs="?",
)
parser_rates.add_argument(
"-o",
"--output",
help="Output path for CSV file (default: stdout).",
type=Path,
default=None,
)
parser_rates.add_argument(
"--sort-by-column",
type=str,
choices=list(RATE_COLUMNS),
default="Name",
help="Sort results by column (default: Name).",
)
parser_rates.add_argument(
"--sort-ascending",
action=argparse.BooleanOptionalAction,
default=True,
help="Whether to sort in ascending order.",
)

# details
info = "Get details for an ISIN"
parser_details = parser_cmd.add_parser(
Expand Down Expand Up @@ -473,12 +525,32 @@ def main():
waf_token=args.waf_token,
),
args.include_watchlist,
instruments_to_ignore=re.split(r"[,;]", args.ignore) if args.ignore else [],
lang=args.lang,
decimal_localization=args.decimal_localization,
output=args.output,
sort_by_column=args.sort_by_column,
sort_descending=not args.sort_ascending,
).get()
elif args.command == "rates":
isins = parse_isin_input(args.input, args.inputfile)
if not isins:
print("No valid ISINs found in input.")
return -1
Rates(
login(
phone_no=args.phone_no,
pin=args.pin,
store_credentials=args.store_credentials,
waf_token=args.waf_token,
),
isins,
output=args.output,
decimal_localization=args.decimal_localization,
lang=args.lang,
sort_by_column=args.sort_by_column,
sort_descending=not args.sort_ascending,
).get()
elif args.command == "details":
Details(
login(
Expand Down
Loading