diff --git a/src/pricehist/cli.py b/src/pricehist/cli.py index 53b7f92..8909a5b 100644 --- a/src/pricehist/cli.py +++ b/src/pricehist/cli.py @@ -1,5 +1,4 @@ import argparse -import sys from datetime import datetime, timedelta from pricehist import outputs, sources @@ -37,7 +36,6 @@ def cmd_source(args): def cmd_fetch(args): source = sources.by_id[args.source]() - start = args.start or args.after output = outputs.by_type[args.output]() prices = source.fetch(args.pair, args.start, args.end) print(output.format(prices)) @@ -66,7 +64,7 @@ def build_parser(): subparsers = parser.add_subparsers(title="commands", dest="command") - sources_parser = subparsers.add_parser("sources", help="list sources") + subparsers.add_parser("sources", help="list sources") source_parser = subparsers.add_parser("source", help="show source details") source_parser.add_argument( diff --git a/src/pricehist/outputs/beancount.py b/src/pricehist/outputs/beancount.py index 9ef9c93..f8c5c9f 100644 --- a/src/pricehist/outputs/beancount.py +++ b/src/pricehist/outputs/beancount.py @@ -2,7 +2,6 @@ class Beancount: def format(self, prices): lines = [] for price in prices: - date = str(price.date).translate(str.maketrans("-", "/")) lines.append( f"{price.date} price {price.base} {price.amount} {price.quote}" ) diff --git a/src/pricehist/outputs/csv.py b/src/pricehist/outputs/csv.py index 0dec50d..9b457d8 100644 --- a/src/pricehist/outputs/csv.py +++ b/src/pricehist/outputs/csv.py @@ -2,7 +2,6 @@ class CSV: def format(self, prices): lines = ["date,base,quote,amount"] for price in prices: - date = str(price.date).translate(str.maketrans("-", "/")) line = ",".join([price.date, price.base, price.quote, str(price.amount)]) lines.append(line) return "\n".join(lines) diff --git a/src/pricehist/outputs/gnucashsql.py b/src/pricehist/outputs/gnucashsql.py index 450b22c..9d838c5 100644 --- a/src/pricehist/outputs/gnucashsql.py +++ b/src/pricehist/outputs/gnucashsql.py @@ -21,7 +21,18 @@ class GnuCashSQL: guid = m.hexdigest()[0:32] value_num = str(price.amount).replace(".", "") value_denom = 10 ** len(f"{price.amount}.".split(".")[1]) - v = f"('{guid}', '{date}', '{price.base}', '{price.quote}', '{source}', '{typ}', {value_num}, {value_denom})" + v = ( + "(" + f"'{guid}', " + f"'{date}', " + f"'{price.base}', " + f"'{price.quote}', " + f"'{source}', " + f"'{typ}', " + f"{value_num}, " + f"{value_denom}" + ")" + ) values.append(v) comma_newline = ",\n" diff --git a/src/pricehist/sources/coindesk.py b/src/pricehist/sources/coindesk.py index 42ada10..8af5884 100644 --- a/src/pricehist/sources/coindesk.py +++ b/src/pricehist/sources/coindesk.py @@ -17,7 +17,10 @@ class CoinDesk: @staticmethod def description(): - return "An average of bitcoin prices across leading global exchanges. Powered by CoinDesk, https://www.coindesk.com/price/bitcoin" + return ( + "An average of bitcoin prices across leading global exchanges. " + "Powered by CoinDesk, https://www.coindesk.com/price/bitcoin" + ) @staticmethod def source_url(): @@ -45,11 +48,17 @@ class CoinDesk: min_start = "2010-07-17" if start < min_start: exit( - f"start {start} too early. The CoinDesk BPI only covers data from {min_start} onwards." + f"start {start} too early. The CoinDesk BPI only covers data" + f"from {min_start} onwards." ) - url = f"https://api.coindesk.com/v1/bpi/historical/close.json?currency={quote}&start={start}&end={end}" - response = requests.get(url) + url = "https://api.coindesk.com/v1/bpi/historical/close.json" + params = { + "currency": quote, + "start": start, + "end": end, + } + response = requests.get(url, params=params) data = json.loads(response.content) prices = [] for (d, v) in data["bpi"].items(): diff --git a/src/pricehist/sources/coinmarketcap.py b/src/pricehist/sources/coinmarketcap.py index cee4482..118799a 100644 --- a/src/pricehist/sources/coinmarketcap.py +++ b/src/pricehist/sources/coinmarketcap.py @@ -1,7 +1,6 @@ import json -from datetime import datetime, timedelta +from datetime import datetime from decimal import Decimal -from xml.etree import ElementTree import requests @@ -25,9 +24,10 @@ class CoinMarketCap: def source_url(): return "https://coinmarketcap.com/" - # # currency metadata - these may max out at 5k items (crypto data is currently 4720 items) - # curl 'https://web-api.coinmarketcap.com/v1/fiat/map?include_metals=true' | jq . | tee fiat-map.json - # curl 'https://web-api.coinmarketcap.com/v1/cryptocurrency/map' | jq . | tee cryptocurrency-map.json + # # currency metadata - these may max out at 5k items + # # (crypto data is currently 4720 items) + # curl '.../v1/fiat/map?include_metals=true' | jq . | tee fiat-map.json + # curl '.../v1/cryptocurrency/map' | jq . | tee cryptocurrency-map.json @staticmethod def bases(): @@ -40,13 +40,14 @@ class CoinMarketCap: def fetch(self, pair, start, end): base, quote = pair.split("/") - url = f"https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical" + url = "https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical" params = { "symbol": base, "convert": quote, "time_start": int(datetime.strptime(start, "%Y-%m-%d").timestamp()), - "time_end": int(datetime.strptime(end, "%Y-%m-%d").timestamp()) - + 24 * 60 * 60, # round up to include the last day + "time_end": ( + int(datetime.strptime(end, "%Y-%m-%d").timestamp()) + 24 * 60 * 60 + ), # round up to include the last day } response = requests.get(url, params=params) diff --git a/src/pricehist/sources/ecb.py b/src/pricehist/sources/ecb.py index 3fb0355..1efe952 100644 --- a/src/pricehist/sources/ecb.py +++ b/src/pricehist/sources/ecb.py @@ -1,4 +1,3 @@ -import json from datetime import datetime, timedelta from decimal import Decimal from xml.etree import ElementTree @@ -78,10 +77,11 @@ class ECB: exit(f"start {start} too early. Minimum is {min_start}") almost_90_days_ago = str(datetime.now().date() - timedelta(days=85)) + url_base = "https://www.ecb.europa.eu/stats/eurofxref" if start > almost_90_days_ago: - source_url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist-90d.xml" # last 90 days + source_url = f"{url_base}/eurofxref-hist-90d.xml" # last 90 days else: - source_url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-hist.xml" # since 1999 + source_url = f"{url_base}/eurofxref-hist.xml" # since 1999 response = requests.get(source_url) data = response.content @@ -96,7 +96,8 @@ class ECB: for day in root.find("default:Cube", namespaces): date = day.attrib["time"] rate_xpath = f"./*[@currency='{quote}']" - # TODO what if it's not found for that day? (some quotes aren't in the earliest data) + # TODO what if it's not found for that day? + # (some quotes aren't in the earliest data) rate = Decimal(day.find(rate_xpath).attrib["rate"]) all_rows.insert(0, (date, rate)) selected = [