Excel output WIP
This commit is contained in:
parent
cd630de70b
commit
1661ab7dd2
|
@ -26,26 +26,13 @@ from fin_depo.data import *
|
||||||
import datetime
|
import datetime
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
|
import fin_data
|
||||||
|
|
||||||
|
from .data import TaxReport, BoughtAndSold, BoughtAndNotYetSold
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@dataclasses.dataclass
|
FIN_DB = fin_data.FinancialDatabase(enable_kucoin=True, enable_nationalbanken_dk=True)
|
||||||
class BoughtAndSold:
|
|
||||||
amount: AssetAmount
|
|
||||||
time_bought: datetime.datetime
|
|
||||||
time_sold: datetime.datetime
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
|
||||||
class BoughtAndNotYetSold:
|
|
||||||
amount: AssetAmount
|
|
||||||
time_bought: datetime.datetime
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
|
||||||
class TaxReport:
|
|
||||||
bought_and_sold_for: list[BoughtAndSold]
|
|
||||||
bought_and_spent_for: list[BoughtAndSold]
|
|
||||||
current_assets: dict[Asset, deque[BoughtAndNotYetSold]]
|
|
||||||
|
|
||||||
|
|
||||||
def compute_tax(transfers: list) -> TaxReport:
|
def compute_tax(transfers: list) -> TaxReport:
|
||||||
|
@ -117,8 +104,17 @@ def compute_tax(transfers: list) -> TaxReport:
|
||||||
spend(fee, transfer.executed_time)
|
spend(fee, transfer.executed_time)
|
||||||
del transfer, fee
|
del transfer, fee
|
||||||
|
|
||||||
|
def exchange_rate_at_time(a, b, t):
|
||||||
|
try:
|
||||||
|
sample = FIN_DB.get_exchange_rate_at_time(a, b, t)
|
||||||
|
return sample.average
|
||||||
|
except Exception:
|
||||||
|
logger.exception('Error when fetching exchange rate (%s,%s) at %s', a, b, t)
|
||||||
|
return None
|
||||||
|
|
||||||
return TaxReport(
|
return TaxReport(
|
||||||
bought_and_sold_for=bought_and_sold_for,
|
bought_and_sold_for=bought_and_sold_for,
|
||||||
bought_and_spent_for=bought_and_spent_for,
|
bought_and_spent_for=bought_and_spent_for,
|
||||||
current_assets=prices_bought_for,
|
current_assets=prices_bought_for,
|
||||||
|
exchange_rate_at_time=exchange_rate_at_time,
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,8 +9,9 @@ from fin_depo.data import *
|
||||||
import datetime
|
import datetime
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from . import compute_tax
|
from . import compute_tax, output_excel
|
||||||
|
|
||||||
KUCOIN_CLIENT = fin_depo.defi_kucoin.KucoinDepoFetcher(
|
KUCOIN_CLIENT = fin_depo.defi_kucoin.KucoinDepoFetcher(
|
||||||
secrets.KUCOIN_KEY,
|
secrets.KUCOIN_KEY,
|
||||||
|
@ -52,6 +53,10 @@ def main():
|
||||||
for bas in tax_report.bought_and_sold_for:
|
for bas in tax_report.bought_and_sold_for:
|
||||||
sys.stdout.write(f'{bas.amount} ({bas.time_bought} ----> {bas.time_sold})\n')
|
sys.stdout.write(f'{bas.amount} ({bas.time_bought} ----> {bas.time_sold})\n')
|
||||||
|
|
||||||
|
output_path = Path('./output/report.xlsx')
|
||||||
|
output_excel.produce_excel_report(tax_report, output_path)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
34
crypto_tax/data.py
Normal file
34
crypto_tax/data.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import sys
|
||||||
|
import requests
|
||||||
|
import fin_depo
|
||||||
|
from . import secrets
|
||||||
|
from fin_defs import CryptoCurrency, AssetAmount, MPC, Asset, USDT
|
||||||
|
from decimal import Decimal
|
||||||
|
from collections import deque
|
||||||
|
from collections.abc import Callable
|
||||||
|
from fin_depo.data import *
|
||||||
|
import datetime
|
||||||
|
import dataclasses
|
||||||
|
import logging
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class BoughtAndSold:
|
||||||
|
amount: AssetAmount
|
||||||
|
time_bought: datetime.datetime
|
||||||
|
time_sold: datetime.datetime
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class BoughtAndNotYetSold:
|
||||||
|
amount: AssetAmount
|
||||||
|
time_bought: datetime.datetime
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class TaxReport:
|
||||||
|
bought_and_sold_for: list[BoughtAndSold]
|
||||||
|
bought_and_spent_for: list[BoughtAndSold]
|
||||||
|
current_assets: dict[Asset, deque[BoughtAndNotYetSold]]
|
||||||
|
exchange_rate_at_time: Callable[[Asset,Asset, datetime.datetime ], Decimal]
|
||||||
|
|
||||||
|
|
||||||
|
|
93
crypto_tax/output_excel.py
Normal file
93
crypto_tax/output_excel.py
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import sys
|
||||||
|
import requests
|
||||||
|
import fin_depo
|
||||||
|
from . import secrets
|
||||||
|
import fin_defs
|
||||||
|
from decimal import Decimal
|
||||||
|
from collections import deque
|
||||||
|
from fin_depo.data import *
|
||||||
|
import datetime
|
||||||
|
import dataclasses
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from .data import TaxReport, BoughtAndSold, BoughtAndNotYetSold
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import openpyxl
|
||||||
|
|
||||||
|
TAX_TYPES: dict[fin_defs.Asset, str] = {
|
||||||
|
fin_defs.DKK: 'Fiat',
|
||||||
|
fin_defs.EUR: 'Fiat',
|
||||||
|
fin_defs.BTC: 'Krypto-valuta',
|
||||||
|
fin_defs.MPC: 'Krypto-valuta',
|
||||||
|
fin_defs.WELL_KNOWN_SYMBOLS['MATIC']: 'Krypto-valuta',
|
||||||
|
fin_defs.USDT: 'Stable Coin (Financiel Kontrakt)',
|
||||||
|
}
|
||||||
|
|
||||||
|
NOW = datetime.datetime.now(tz=datetime.UTC)
|
||||||
|
|
||||||
|
def mult_a(a, b):
|
||||||
|
if a is None or b is None:
|
||||||
|
return 'Unknown'
|
||||||
|
return a * b
|
||||||
|
|
||||||
|
def write_current_assets(sheet, tax_report: TaxReport):
|
||||||
|
column_headers = ['Værdipapir', 'Mængde', 'Estimeret værdi (DKK)',
|
||||||
|
'Beskatningstype']
|
||||||
|
sheet.append(column_headers)
|
||||||
|
for asset, positions in tax_report.current_assets.items():
|
||||||
|
total_amount: Decimal = sum((p.amount.amount for p in positions), start=Decimal(0))
|
||||||
|
exchange_rate_asset_to_dkk = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, NOW)
|
||||||
|
assert exchange_rate_asset_to_dkk is not None, asset
|
||||||
|
row = [
|
||||||
|
asset.raw_short_name(),
|
||||||
|
total_amount,
|
||||||
|
mult_a(total_amount, exchange_rate_asset_to_dkk),
|
||||||
|
TAX_TYPES[asset],
|
||||||
|
]
|
||||||
|
sheet.append(row)
|
||||||
|
del asset, positions, row, total_amount
|
||||||
|
|
||||||
|
|
||||||
|
def write_fifo_sheet(sheet, tax_report: TaxReport):
|
||||||
|
column_headers = [
|
||||||
|
'Værdipapir', 'Mængde', 'Anskaffelsesværdi (DKK)', 'Købsdato (UTC)',
|
||||||
|
'Salgsværdi (DKK)', 'Salgsdato (UTC)', 'Profit (DKK)', 'Tab (DKK)',
|
||||||
|
'Beskatningstype',
|
||||||
|
]
|
||||||
|
sheet.append(column_headers)
|
||||||
|
row_idx = 2
|
||||||
|
for fifo_entry in tax_report.bought_and_sold_for:
|
||||||
|
print(fifo_entry)
|
||||||
|
asset = fifo_entry.amount.asset
|
||||||
|
|
||||||
|
exchange_rate_dkk_bought = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, fifo_entry.time_bought)
|
||||||
|
#assert exchange_rate_dkk_bought is not None, asset
|
||||||
|
exchange_rate_dkk_sold = tax_report.exchange_rate_at_time(asset, fin_defs.DKK, fifo_entry.time_sold)
|
||||||
|
#assert exchange_rate_dkk_bought is not None, asset
|
||||||
|
|
||||||
|
row = [
|
||||||
|
asset.raw_short_name(),
|
||||||
|
fifo_entry.amount.amount,
|
||||||
|
mult_a(fifo_entry.amount.amount , exchange_rate_dkk_bought),
|
||||||
|
fifo_entry.time_bought.replace(tzinfo=None),
|
||||||
|
mult_a(fifo_entry.amount.amount , exchange_rate_dkk_sold),
|
||||||
|
fifo_entry.time_sold.replace(tzinfo=None),
|
||||||
|
f'=max(0, E{row_idx} - C{row_idx})',
|
||||||
|
f'=max(0, C{row_idx} - E{row_idx})',
|
||||||
|
TAX_TYPES[asset],
|
||||||
|
]
|
||||||
|
sheet.append(row)
|
||||||
|
row_idx+= 1
|
||||||
|
del fifo_entry, asset, row
|
||||||
|
|
||||||
|
def produce_excel_report(report: TaxReport, output_path: Path):
|
||||||
|
workbook = openpyxl.Workbook()
|
||||||
|
|
||||||
|
workbook.active.title = 'Current Assets'
|
||||||
|
write_current_assets(workbook.active, report)
|
||||||
|
|
||||||
|
sheet_buy_sales = workbook.create_sheet('FIFO')
|
||||||
|
write_fifo_sheet(sheet_buy_sales, report)
|
||||||
|
|
||||||
|
workbook.save(output_path)
|
Loading…
Reference in New Issue
Block a user