Exemple #1
0
def lstx(no_group, no_annotations, minimal):
    """List all transactions that have been derived from events and annotated."""
    events = get_events(loaders.all)
    transactions = get_transactions(events,
                                    XDG_CONFIG_HOME + "/mistbat/tx_match.yaml")
    if not no_annotations:
        transactions = annotate_transactions(
            transactions, XDG_CONFIG_HOME + "/mistbat/tx_annotations.yaml")
    transactions = fmv_transactions(transactions,
                                    XDG_DATA_HOME + "/mistbat/tx_fmv.yaml")
    transactions = imply_fees(transactions)

    if no_group:
        transactions = [
            tx for tx in transactions if getattr(tx, "groups", None) is None
        ]

    # Print transactions
    for tx in transactions:
        if minimal:
            print(tx)
        else:
            print(tx.description())

    print("--------------------")
    print("{} total transactions".format(len(transactions)))
    print_usd_exposure()
Exemple #2
0
def fees():
    events = get_events(loaders.all)
    transactions = get_transactions(events,
                                    XDG_CONFIG_HOME + "/mistbat/tx_match.yaml")
    transactions = fmv_transactions(transactions,
                                    XDG_DATA_HOME + "/mistbat/tx_fmv.yaml")
    transactions = imply_fees(transactions)

    print("\nFees Incurred")
    print("-------------")
    fees = {}
    for tx in transactions:
        fees[tx.__class__.__name__] = fees.get(tx.__class__.__name__,
                                               0) + tx.fee_usd
    for k, v in fees.items():
        print(f"{k}: USD {v:0.2f}")
    print("TOTAL: USD {:0.2f}\n".format(sum(fees.values())))

    print("\nFees Incurred (negative values ignored)")
    print("-----------------------------------------")
    fees = {}
    for tx in transactions:
        fees[tx.__class__.__name__] = fees.get(tx.__class__.__name__, 0) + max(
            tx.fee_usd, 0)
    for k, v in fees.items():
        print(f"{k}: USD {v:0.2f}")
    print("TOTAL: USD {:0.2f}\n".format(sum(fees.values())))
Exemple #3
0
def currentbasis(harvest):
    """See available basis by coin"""
    events = get_events(loaders.all)
    transactions = get_transactions(events,
                                    XDG_CONFIG_HOME + "/mistbat/tx_match.yaml")
    transactions = annotate_transactions(
        transactions, XDG_CONFIG_HOME + "/mistbat/tx_annotations.yaml")
    transactions = fmv_transactions(transactions,
                                    XDG_DATA_HOME + "/mistbat/tx_fmv.yaml")
    transactions = imply_fees(transactions)

    form_8949 = Form8949(transactions)
    print("\nAVAILABLE BASIS REPORT")
    print(
        "Note: Coin totals will slighly deviate from 'holdings' since SENDRECV fees do not impact basis.\n"
    )
    table_headings = [
        "Coin",
        "Date Acquired",
        "Amount",
        "Basis per Coin",
        "Total Basis",
    ]
    if harvest:
        table_headings.append("Cum. G/L at Spot Price")
        spot_prices = get_coin_spot_prices(
            set(form_8949.current_available_basis().keys()))
    table = PrettyTable(table_headings)

    for coin, available_basis in form_8949.current_available_basis().items():
        coin_usd_total = 0.00
        coin_amount_total = 0.00
        cumulative_gain_or_loss = 0.00
        for basis in available_basis:
            time = basis[0].strftime("%Y-%m-%d %H:%M:%S")
            amount = round(basis[1], 8)
            fmv = round(basis[2], 2)
            total = round(amount * fmv, 2)
            row = [coin, time, amount, fmv, total]
            if harvest:
                cumulative_gain_or_loss += (spot_prices[coin] *
                                            amount) - (fmv * amount)
                row.append(round(cumulative_gain_or_loss, 2))
            table.add_row(row)
            coin_usd_total += total
            coin_amount_total += amount
        row = [
            "", "TOTAL",
            round(coin_amount_total, 8), "",
            round(coin_usd_total, 2)
        ]
        if harvest:
            row.append("")
        table.add_row(row)
        table.add_row([" "] * len(table.field_names))
    print(table)
Exemple #4
0
def tax(aggregated, year):
    """Generate the information needed for IRS Form 8949"""
    events = get_events(loaders.all)
    transactions = get_transactions(events,
                                    XDG_CONFIG_HOME + "/mistbat/tx_match.yaml")
    transactions = annotate_transactions(
        transactions, XDG_CONFIG_HOME + "/mistbat/tx_annotations.yaml")
    transactions = fmv_transactions(transactions,
                                    XDG_DATA_HOME + "/mistbat/tx_fmv.yaml")
    transactions = imply_fees(transactions)

    form_8949 = Form8949(transactions)

    print("SHORT-TERM CAPITAL GAINS")
    table = PrettyTable([
        "(a) Description",
        "(b) Date acquired",
        "(c) Date sold",
        "(d) Proceeds",
        "(e) Basis",
        "(h) Gain",
    ])
    total_gain = 0.00
    for line in form_8949.generate_form(term="short",
                                        aggregated=aggregated,
                                        year=year):
        table.add_row(line)
        if str(line[-1]).strip():
            total_gain += line[-1]
    print(table)
    print(f"TOTAL SHORT-TERM CAPITAL GAIN: USD {total_gain:0.2f}")

    print("\nLONG-TERM CAPITAL GAINS")
    table = PrettyTable([
        "(a) Description",
        "(b) Date acquired",
        "(c) Date sold",
        "(d) Proceeds",
        "(e) Basis",
        "(h) Gain",
    ])
    total_gain = 0.00
    for line in form_8949.generate_form(term="long",
                                        aggregated=aggregated,
                                        year=year):
        table.add_row(line)
        if str(line[-1]).strip():
            total_gain += line[-1]
    print(table)
    print(f"TOTAL LONG-TERM CAPITAL GAIN: USD {total_gain:0.2f}")
Exemple #5
0
def updatefmv(verbose):
    """Update the tx_fmv.yaml file for any missing figures"""
    # Load storage file and events and transactions
    try:
        fmv_raw = yaml.load(open(XDG_DATA_HOME + "/mistbat/tx_fmv.yaml"))
    except FileNotFoundError:
        fmv_raw = {}
    fmv_data = {}
    for id in fmv_raw:
        fmvs = fmv_raw[id].split(" -- ")
        comment = None
        if len(fmvs) == 2:  # If there is a comment
            comment = fmvs[1]
        fmvs = fmvs[0].split()
        fmvs = {fmv.split("@")[0]: fmv.split("@")[1] for fmv in fmvs}
        fmvs["comment"] = comment
        fmv_data[id] = fmvs

    events = get_events(loaders.all)
    transactions = get_transactions(events,
                                    XDG_CONFIG_HOME + "/mistbat/tx_match.yaml")

    # Identify missing transactions
    missing = [
        tx for tx in transactions if tx.missing_fmv and tx.id not in fmv_data
    ]

    # Error-check that stored transactions have necessary FMV info
    stored = [tx for tx in transactions if tx.id in fmv_data]
    for tx in stored:
        stored_coins = set(fmv_data[tx.id].keys())
        stored_coins.remove("comment")
        if set(tx.affected_coins) != stored_coins:
            raise RuntimeError(
                f"Transaction {tx.id} does not have correct fmv info")

    # Confirm that the tx_fmv file doesn't have any unknown tx ids
    diff = set(id for id in fmv_data) - set(tx.id for tx in transactions)
    diff = ", ".join(diff)
    if len(diff) != 0:
        raise RuntimeError(
            f"Unrecognized transaction ids in tx_fmv.yaml: {diff}. Tip: Dont inlude fiat transaction fmvs."
        )

    # Fill remaining missing transactions with public closing price
    print(f"{len(missing)} missing transactions") if verbose else None
    for tx in missing:
        print(f"{tx.id}")
        fmv_data[tx.id] = {"comment": "from crytpocompare daily close api"}
        for coin in tx.affected_coins:
            coin_fmv = get_historical_close(coin, int(tx.time.timestamp()))
            fmv_data[tx.id][coin] = coin_fmv
            print(f"{coin}@{coin_fmv}\n") if verbose else None
            time.sleep(0.1)

    # Convert fmv_data back into fmv_raw and dump to disk
    fmv_raw = {}
    for id, coins in fmv_data.items():
        comment = coins.pop("comment")
        fmv_raw[id] = " ".join(f"{coin}@{price}"
                               for coin, price in coins.items())
        if comment:
            fmv_raw[id] += " -- " + comment

    yaml.dump(
        fmv_raw,
        open(XDG_DATA_HOME + "/mistbat/tx_fmv.yaml", "w"),
        default_flow_style=False,
    )
Exemple #6
0
 def get(self):
     if self.current_user is None:
         self.redirect('/sign-in-form')
         return
     transactions_info = transactions.get_transactions(self.current_user)
     self.render('templates/self.html', transactions=transactions_info)