Example #1
0
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)
Example #2
0
def balances(keyword, minimum_balance, fetch, total, external):
    "Show balances across all accounts"

    buchfink_db = BuchfinkDB()
    assets_sum = {}
    assets_usd_sum = {}
    liabilities_sum = {}
    liabilities_usd_sum = {}

    if external:
        accounts = [account_from_string(ext, buchfink_db) for ext in external]
    else:
        accounts = buchfink_db.get_all_accounts()

    for account in accounts:
        if keyword is not None and keyword not in account.name:
            continue

        if fetch:
            buchfink_db.perform_assets_updates()
            buchfink_db.fetch_balances(account)

        sheet = buchfink_db.get_balances(account)

        for asset, balance in sheet.assets.items():
            amount = balance.amount
            assets_sum[asset] = assets_sum.get(asset, FVal(0)) + amount
            assets_usd_sum[asset] = assets_usd_sum.get(asset, FVal(0)) + balance.usd_value

        for liability, balance in sheet.liabilities.items():
            amount = balance.amount
            liabilities_sum[liability] = liabilities_sum.get(liability, FVal(0)) + amount
            liabilities_usd_sum[liability] = liabilities_usd_sum.get(liability, FVal(0)) \
                    + balance.usd_value

    currency = buchfink_db.get_main_currency()
    currency_in_usd = FVal(buchfink_db.inquirer.find_usd_price(currency))

    table = []
    assets = [obj[0] for obj in sorted(assets_usd_sum.items(), key=itemgetter(1), reverse=True)]
    balance_in_currency_sum = 0
    small_balances_sum = 0

    for asset in assets:
        balance = assets_sum[asset]
        balance_in_currency = FVal(assets_usd_sum.get(asset, 0)) / currency_in_usd
        if balance > ZERO:
            if balance_in_currency > FVal(minimum_balance):
                table.append([
                    asset.name,
                    balance,
                    asset.symbol,
                    round(float(balance_in_currency), 2)
                ])
            else:
                small_balances_sum += balance_in_currency
            balance_in_currency_sum += balance_in_currency

    if total:
        print(f'Total assets: {round(float(balance_in_currency_sum), 2)} {currency.symbol}')

    else:
        if small_balances_sum > 0:
            table.append(['Others', None, None, round(float(small_balances_sum), 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
        ]))

    if liabilities_sum:
        table = []
        balance_in_currency_sum = 0
        assets = [
                obj[0]
                for obj
                in sorted(liabilities_usd_sum.items(), key=itemgetter(1), reverse=True)
        ]
        for asset in assets:
            balance = liabilities_sum[asset]
            balance_in_currency = liabilities_usd_sum.get(asset, FVal(0)) / currency_in_usd
            if balance > ZERO and balance_in_currency >= FVal(minimum_balance):
                balance_in_currency_sum += balance_in_currency
                table.append([
                    asset.name,
                    balance,
                    asset.symbol,
                    round(float(balance_in_currency), 2)
                ])
        table.append(['Total', None, None, round(float(balance_in_currency_sum), 2)])

        if total:
            print(
                f'Total liabilities: '
                f'{round(float(balance_in_currency_sum), 2)} {currency.symbol}'
            )

        else:
            print()
            print(tabulate(table, headers=[
                'Liability',
                'Amount',
                'Symbol',
                'Fiat Value (%s)' % currency.symbol
            ]))