def fetch(keyword): "Fetch trades for configured accounts" buchfink_db = BuchfinkDB() for account in buchfink_db.get_all_accounts(): if keyword is not None and keyword not in account['name']: continue if 'exchange' not in account: continue click.echo('Fetching trades for ' + account['name']) exchange = buchfink_db.get_exchange(account['name']) api_key_is_valid, error = exchange.validate_api_key() if not api_key_is_valid: logger.critical( 'Skipping exchange %s because API key is not valid (%s)', account['name'], error) continue name = account.get('name') trades = exchange.query_online_trade_history(start_ts=epoch_start_ts, end_ts=epoch_end_ts) logger.info('Fetched %d trades from %s', len(trades), name) with open("trades/" + name + ".yaml", "w") as f: yaml.dump({"trades": serialize_trades(trades)}, stream=f)
def balances(keyword): "Show balances across all accounts" buchfink_db = BuchfinkDB() balances_sum = {} usd_value_sum = {} for account in buchfink_db.get_all_accounts(): if keyword is not None and keyword not in account['name']: continue if 'exchange' in account: exchange = buchfink_db.get_exchange(account['name']) api_key_is_valid, error = exchange.validate_api_key() if not api_key_is_valid: logger.critical( 'Skipping exchange %s because API key is not valid (%s)', account['name'], error) continue balances, error = exchange.query_balances() if not error: logger.info('Fetched balances for %d assets from %s', len(balances.keys()), account['name']) for asset, balance in balances.items(): amount = balance['amount'] balances_sum[asset] = balances_sum.get(asset, FVal(0)) + amount if 'usd_value' in balance: usd_value_sum[asset] = usd_value_sum.get( asset, FVal(0)) + balance['usd_value'] elif 'ethereum' in account: manager = buchfink_db.get_chain_manager(account) manager.query_balances() for eth_balance in manager.balances.eth.values(): for asset, balance in eth_balance.asset_balances.items(): amount = balance.amount balances_sum[asset] = balances_sum.get(asset, FVal(0)) + amount usd_value_sum[asset] = usd_value_sum.get( asset, FVal(0)) + balance.usd_value elif 'bitcoin' in account: manager = buchfink_db.get_chain_manager(account) manager.query_balances() asset = Asset('BTC') for balance in manager.balances.btc.values(): amount = balance.amount balances_sum[asset] = balances_sum.get(asset, FVal(0)) + amount usd_value_sum[asset] = usd_value_sum.get( asset, FVal(0)) + balance.usd_value elif 'file' in account: account = yaml.load(open(account['file'], 'r'), Loader=yaml.SafeLoader) if 'balances' in account: for balance in account['balances']: amount = FVal(balance['amount']) asset = Asset(balance['asset']) usd_value = amount * buchfink_db.inquirer.find_usd_price( asset) balances_sum[asset] = balances_sum.get(asset, FVal(0)) + amount usd_value_sum[asset] = usd_value_sum.get( asset, FVal(0)) + usd_value currency = buchfink_db.get_main_currency() currency_in_usd = buchfink_db.inquirer.find_usd_price(currency) table = [] assets = [ obj[0] for obj in sorted( usd_value_sum.items(), key=itemgetter(1), reverse=True) ] balance_in_currency_sum = 0 for asset in assets: balance = balances_sum[asset] balance_in_currency = usd_value_sum.get(asset, FVal(0)) / currency_in_usd balance_in_currency_sum += balance_in_currency table.append([ asset, balance, asset.symbol, round(float(balance_in_currency), 2) ]) table.append( ['Total', None, None, round(float(balance_in_currency_sum), 2)]) print( tabulate(table, headers=[ 'Asset', 'Amount', 'Symbol', 'Fiat Value (%s)' % currency.symbol ]))
def fetch_(keyword, account_type, fetch_actions, fetch_balances, fetch_trades, external): "Fetch trades for configured accounts" buchfink_db = BuchfinkDB() buchfink_db.perform_assets_updates() now = ts_now() fetch_limited = fetch_actions or fetch_balances or fetch_trades if external: accounts = [account_from_string(ext, buchfink_db) for ext in external] else: accounts = buchfink_db.get_all_accounts() # TODO: This should move to BuchfinkDB.get_accounts() if keyword is not None: if keyword.startswith('/') and keyword.endswith('/'): keyword_re = re.compile(keyword[1:-1]) accounts = [acc for acc in accounts if keyword_re.search(acc.name)] else: accounts = [acc for acc in accounts if keyword in acc.name] logger.info( 'Collected %d account(s): %s', len(accounts), ', '.join([acc.name for acc in accounts]) ) for account in accounts: if account_type is not None and account_type not in account.account_type: continue name = account.name trades = [] actions = [] if account.account_type == "ethereum": if not fetch_limited or fetch_actions: logger.info('Analyzing ethereum transactions for %s', name) manager = buchfink_db.get_chain_manager(account) txs = manager.ethereum.transactions.single_address_query_transactions( account.address, start_ts=0, end_ts=now, with_limit=False, only_cache=False ) for txn in txs: tx_hash = '0x' + txn.tx_hash.hex() receipt = buchfink_db.get_ethereum_transaction_receipt(tx_hash, manager) acc_actions = classify_tx(account, tx_hash, txn, receipt) if actions: for act in actions: logger.debug('Found action: %s', act) actions.extend(acc_actions) if not fetch_limited or fetch_trades: logger.info('Fetching uniswap trades for %s', name) manager = buchfink_db.get_chain_manager(account) trades = manager.eth_modules['uniswap'].get_trades( addresses=manager.accounts.eth, from_timestamp=int(epoch_start_ts), to_timestamp=int(epoch_end_ts), only_cache=False ) elif account.account_type == "exchange": if not fetch_limited or fetch_trades: logger.info('Fetching exhange trades for %s', name) exchange = buchfink_db.get_exchange(name) api_key_is_valid, error = exchange.validate_api_key() if not api_key_is_valid: logger.critical( 'Skipping exchange %s because API key is not valid (%s)', account.name, error ) else: trades = exchange.query_online_trade_history( start_ts=epoch_start_ts, end_ts=epoch_end_ts ) else: logger.debug('No way to retrieve trades for %s, yet', name) annotations_path = "annotations/" + name + ".yaml" if not fetch_limited or fetch_actions: if os.path.exists(annotations_path): annotated = buchfink_db.get_actions_from_file(annotations_path) else: annotated = [] logger.info('Fetched %d action(s) (%d annotated) from %s', len(actions) + len(annotated), len(annotated), name) actions.extend(annotated) if actions: with open("actions/" + name + ".yaml", "w") as yaml_file: yaml.dump({ "actions": serialize_ledger_actions(actions) }, stream=yaml_file, sort_keys=True) if not fetch_limited or fetch_trades: if os.path.exists(annotations_path): annotated = buchfink_db.get_trades_from_file(annotations_path) else: annotated = [] logger.info('Fetched %d trades(s) (%d annotated) from %s', len(trades) + len(annotated), len(annotated), name) trades.extend(annotated) with open("trades/" + name + ".yaml", "w") as yaml_file: yaml.dump({ "trades": serialize_trades(trades) }, stream=yaml_file, sort_keys=True) if not fetch_limited or fetch_balances: buchfink_db.fetch_balances(account) logger.info('Fetched balances from %s', name)