diff options
| -rw-r--r-- | bla.py | 61 | 
1 files changed, 47 insertions, 14 deletions
@@ -1,31 +1,62 @@  import csv  from collections import defaultdict, deque +from datetime import datetime  class FIFOQueue:      def __init__(self):          self.queue = deque() -    def add(self, amount, cost): -        self.queue.append((amount, cost)) +    def add(self, amount, cost, date): +        self.queue.append((amount, cost, date))      def remove(self, amount):          remaining = amount          cost_basis = 0 +        date_acquired = None +        entries = []          while remaining > 0:              if not self.queue:                  raise ValueError(f"Insufficient assets in queue to process sale of {amount}.") -            quantity, cost = self.queue[0] +            quantity, cost, date = self.queue[0]              if quantity > remaining:                  cost_basis += remaining * cost -                self.queue[0] = (quantity - remaining, cost) +                self.queue[0] = (quantity - remaining, cost, date) +                entries.append((remaining, cost, date))                  remaining = 0              else:                  cost_basis += quantity * cost                  remaining -= quantity +                entries.append((quantity, cost, date))                  self.queue.popleft() -        return cost_basis +        return cost_basis, entries + +def generate_report(sale_entries, proceeds, crypto_asset, date_sold): +    report = [] +    sell_date = datetime.strptime(date_sold, "%Y-%m-%d").strftime("%d.%m.%Y") + +    for amount, cost, buy_date in sale_entries: +        buy_date_formatted = datetime.strptime(buy_date, "%Y-%m-%d").strftime("%d.%m.%Y") +        holding_period = (datetime.strptime(date_sold, "%Y-%m-%d") - datetime.strptime(buy_date, "%Y-%m-%d")).days +        short_or_long = "Short" if holding_period < 365 else "Long" +        cost_basis = amount * cost +        gain_or_loss = proceeds - cost_basis + +        report.append({ +            "Amount": f"{amount:.8f}", +            "Currency": crypto_asset, +            "Date Sold": sell_date, +            "Date Acquired": buy_date_formatted, +            "Short/Long": short_or_long, +            "Buy/Input at": "Kraken", +            "Sell/Output at": "Kraken", +            "Proceeds": f"{proceeds:.2f}", +            "Cost Basis": f"{cost_basis:.2f}", +            "Gain/Loss": f"{gain_or_loss:.2f}", +        }) + +    return report  def process_ledger(file_path):      fifo_queues = {}  # Separate FIFO queue per cryptocurrency @@ -45,7 +76,8 @@ def process_ledger(file_path):                  fifo_queues.setdefault(currency, FIFOQueue())                  amount = float(row["amount"])                  price = 0  # Deposits typically have no associated cost basis -                fifo_queues[currency].add(amount, price) +                date = row["time"].split(" ")[0] +                fifo_queues[currency].add(amount, price, date)          # Process grouped trades          for refid, trades in trades_by_refid.items(): @@ -61,15 +93,16 @@ def process_ledger(file_path):                      crypto_fee = float(crypto_trade["fee"])                      fifo_queues.setdefault(crypto_asset, FIFOQueue()) +                    date_sold = eur_trade["time"].split(" ")[0] +                      if eur_amount < 0:  # Purchase of cryptocurrency                          stake_amount = -eur_amount - eur_fee  # Account for EUR fees                          crypto_amount -= crypto_fee  # Adjust for crypto fees -                        fifo_queues[crypto_asset].add(crypto_amount, stake_amount) +                        fifo_queues[crypto_asset].add(crypto_amount, stake_amount, date_sold)                      elif eur_amount > 0:  # Sale of cryptocurrency -                        sale_proceeds = eur_amount - eur_fee  # Account for EUR fees -                        cost_basis = fifo_queues[crypto_asset].remove(crypto_amount) -                        profit_or_loss = sale_proceeds - cost_basis -                        report.append((eur_trade["time"], crypto_asset, profit_or_loss)) +                        proceeds = eur_amount - eur_fee  # Account for EUR fees +                        cost_basis, sale_entries = fifo_queues[crypto_asset].remove(crypto_amount) +                        report.extend(generate_report(sale_entries, proceeds, crypto_asset, date_sold))                  else:                      raise ValueError(f"Unexpected trade grouping for refid {refid}")              else: @@ -79,6 +112,6 @@ def process_ledger(file_path):  # Usage  ledger_path = "kraken_ledger.csv"  # Replace with your file path -profit_and_loss_report = process_ledger(ledger_path) -for entry in profit_and_loss_report: -    print(entry) +tax_report = process_ledger(ledger_path) +for entry in tax_report: +    print(",".join(f"{key}={value}" for key, value in entry.items()))  | 
