From bc5149fd3541687842570ba6e195c5deb7e0573a Mon Sep 17 00:00:00 2001 From: uvok Date: Sun, 13 Apr 2025 16:19:55 +0200 Subject: Tax report --- bla.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/bla.py b/bla.py index 91bbd78..a1d6578 100644 --- a/bla.py +++ b/bla.py @@ -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())) -- cgit v1.2.3