Handle transfers between own accounts
This commit is contained in:
parent
4e3ac4b693
commit
c40ce86f27
|
@ -24,6 +24,7 @@ from decimal import Decimal
|
||||||
from collections import deque
|
from collections import deque
|
||||||
from fin_depo.data import *
|
from fin_depo.data import *
|
||||||
import datetime
|
import datetime
|
||||||
|
import dataclassabc
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
import fin_data
|
import fin_data
|
||||||
|
@ -42,9 +43,49 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
FIN_DB = fin_data.FinancialDatabase(enable_kucoin=True, enable_nationalbanken_dk=True)
|
FIN_DB = fin_data.FinancialDatabase(enable_kucoin=True, enable_nationalbanken_dk=True)
|
||||||
|
|
||||||
|
@dataclassabc.dataclassabc(frozen=True)
|
||||||
|
class TransferDetails(fin_depo.data.DoubleRegister):
|
||||||
|
withdrawal: fin_depo.data.WithdrawalDetails
|
||||||
|
deposit: fin_depo.data.DepositDetails
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fee(self) -> AssetAmount | None:
|
||||||
|
return self.withdrawal.fee # TODO?
|
||||||
|
|
||||||
|
@property
|
||||||
|
def executed_time(self) -> datetime.datetime:
|
||||||
|
return self.withdrawal.executed_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def input(self) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def output(self) -> None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def collate_interaccount_transfers(transfers: list[fin_depo.data.DoubleRegister]) -> list[fin_depo.data.DoubleRegister]:
|
||||||
|
new_transfers = []
|
||||||
|
for t in transfers:
|
||||||
|
if isinstance(t, fin_depo.data.DepositDetails):
|
||||||
|
prev_transfer = new_transfers[-1] if len(new_transfers) > 0 else None
|
||||||
|
if isinstance(prev_transfer , fin_depo.data.WithdrawalDetails):
|
||||||
|
if prev_transfer.withdrawn == t.deposit:
|
||||||
|
del new_transfers[-1]
|
||||||
|
new_transfers.append(TransferDetails(prev_transfer, t))
|
||||||
|
continue
|
||||||
|
del prev_transfer
|
||||||
|
|
||||||
|
new_transfers.append(t)
|
||||||
|
del t
|
||||||
|
|
||||||
|
return new_transfers
|
||||||
|
|
||||||
|
|
||||||
def compute_fifo(transfers: list) -> TaxReport:
|
def compute_fifo(transfers: list) -> TaxReport:
|
||||||
transfers.sort(key=lambda t:t.executed_time)
|
transfers.sort(key=lambda t:t.executed_time)
|
||||||
|
transfers = collate_interaccount_transfers(transfers)
|
||||||
|
|
||||||
|
|
||||||
bought_and_sold_for: list[BoughtAndSold] = []
|
bought_and_sold_for: list[BoughtAndSold] = []
|
||||||
|
@ -52,7 +93,7 @@ def compute_fifo(transfers: list) -> TaxReport:
|
||||||
ledger_entries = []
|
ledger_entries = []
|
||||||
|
|
||||||
prices_bought_for: dict[Asset, deque[BoughtAndNotYetSold]] = {}
|
prices_bought_for: dict[Asset, deque[BoughtAndNotYetSold]] = {}
|
||||||
if False:
|
if True:
|
||||||
prices_bought_for[MPC] = deque()
|
prices_bought_for[MPC] = deque()
|
||||||
# TODO:
|
# TODO:
|
||||||
prices_bought_for[MPC].append(BoughtAndNotYetSold(AssetAmount(MPC, Decimal(80)), datetime.datetime(2024, 4,1,1,1,1,1)))
|
prices_bought_for[MPC].append(BoughtAndNotYetSold(AssetAmount(MPC, Decimal(80)), datetime.datetime(2024, 4,1,1,1,1,1)))
|
||||||
|
@ -67,7 +108,8 @@ def compute_fifo(transfers: list) -> TaxReport:
|
||||||
amount = amount_to_sell
|
amount = amount_to_sell
|
||||||
while amount.amount > 0:
|
while amount.amount > 0:
|
||||||
if len(prices_bought_for[amount.asset]) == 0:
|
if len(prices_bought_for[amount.asset]) == 0:
|
||||||
raise Exception('Miscalculation: ' + str(amount))
|
msg = f'Miscalculation: {amount} of {amount_to_sell}'
|
||||||
|
raise Exception(msg)
|
||||||
partial = prices_bought_for[amount.asset].popleft()
|
partial = prices_bought_for[amount.asset].popleft()
|
||||||
|
|
||||||
amount_covered_by_partial = min(partial.amount, amount)
|
amount_covered_by_partial = min(partial.amount, amount)
|
||||||
|
@ -116,6 +158,7 @@ def compute_fifo(transfers: list) -> TaxReport:
|
||||||
|
|
||||||
|
|
||||||
for transfer in transfers:
|
for transfer in transfers:
|
||||||
|
|
||||||
# Sell
|
# Sell
|
||||||
if _input := transfer.input:
|
if _input := transfer.input:
|
||||||
variant = 'WITHDRAW' if transfer.output is None else 'SELL'
|
variant = 'WITHDRAW' if transfer.output is None else 'SELL'
|
||||||
|
@ -130,6 +173,8 @@ def compute_fifo(transfers: list) -> TaxReport:
|
||||||
del variant
|
del variant
|
||||||
del output
|
del output
|
||||||
|
|
||||||
|
# TODO: Output line for transfer.
|
||||||
|
|
||||||
# Fee
|
# Fee
|
||||||
if fee := transfer.fee:
|
if fee := transfer.fee:
|
||||||
spend(fee, transfer.executed_time)
|
spend(fee, transfer.executed_time)
|
||||||
|
|
|
@ -55,13 +55,13 @@ def add_headers(sheet, column_headers):
|
||||||
cell.alignment = ALIGN_CENTER
|
cell.alignment = ALIGN_CENTER
|
||||||
cell.border = BORDER_BOTTOM
|
cell.border = BORDER_BOTTOM
|
||||||
|
|
||||||
def set_number_format(sheet, range):
|
def set_number_format(sheet, range, format="0.00"):
|
||||||
for row in sheet[range]:
|
for row in sheet[range]:
|
||||||
for cell in row:
|
for cell in row:
|
||||||
cell.number_format = "0.00"
|
cell.number_format = format
|
||||||
|
|
||||||
def write_current_assets(sheet, tax_report: TaxReport):
|
def write_current_assets(sheet, tax_report: TaxReport):
|
||||||
column_headers = ['Værdipapir', 'Mængde', 'Kurs', 'Værdi (DKK)',
|
column_headers = ['Værdipapir', 'Mængde', 'Kurs', 'Sum (DKK)',
|
||||||
'Beskatningstype']
|
'Beskatningstype']
|
||||||
add_headers(sheet, column_headers)
|
add_headers(sheet, column_headers)
|
||||||
row_idx = 2
|
row_idx = 2
|
||||||
|
@ -72,7 +72,7 @@ def write_current_assets(sheet, tax_report: TaxReport):
|
||||||
row = [
|
row = [
|
||||||
asset.raw_short_name(),
|
asset.raw_short_name(),
|
||||||
total_amount,
|
total_amount,
|
||||||
exchange_rate_asset_to_dkk,
|
exchange_rate_asset_to_dkk or 'Unknown',
|
||||||
f'=B{row_idx}*C{row_idx}',
|
f'=B{row_idx}*C{row_idx}',
|
||||||
TAX_TYPES[asset],
|
TAX_TYPES[asset],
|
||||||
]
|
]
|
||||||
|
@ -97,7 +97,7 @@ def write_ledger_sheet(sheet, tax_report: TaxReport):
|
||||||
'Mængde',
|
'Mængde',
|
||||||
'Kontoudbyder',
|
'Kontoudbyder',
|
||||||
''
|
''
|
||||||
] + [a.raw_short_name() for a in assets]
|
] + [a.raw_short_name() for a in assets] + ['', 'Kommentarer']
|
||||||
|
|
||||||
add_headers(sheet, column_headers)
|
add_headers(sheet, column_headers)
|
||||||
row_idx = 2
|
row_idx = 2
|
||||||
|
@ -156,9 +156,9 @@ def write_fifo_sheet(sheet, bought_and_sold_for: list, exchange_rate_at_time) ->
|
||||||
'Mængde',
|
'Mængde',
|
||||||
'Anskaffelseskurs',
|
'Anskaffelseskurs',
|
||||||
'Salgskurs',
|
'Salgskurs',
|
||||||
'Anskaffelsesværdi (DKK)',
|
'Købssum (DKK)',
|
||||||
'Salgsværdi (DKK)',
|
'Salgssum (DKK)',
|
||||||
'Profit (DKK)', 'Tab (DKK)',
|
'Gevinst (DKK)', 'Tab (DKK)',
|
||||||
]
|
]
|
||||||
add_headers(sheet, column_headers)
|
add_headers(sheet, column_headers)
|
||||||
row_idx = 2
|
row_idx = 2
|
||||||
|
@ -175,12 +175,12 @@ def write_fifo_sheet(sheet, bought_and_sold_for: list, exchange_rate_at_time) ->
|
||||||
fifo_entry.time_sold.replace(tzinfo=None),
|
fifo_entry.time_sold.replace(tzinfo=None),
|
||||||
asset.raw_short_name(),
|
asset.raw_short_name(),
|
||||||
fifo_entry.amount.amount,
|
fifo_entry.amount.amount,
|
||||||
exchange_rate_dkk_bought,
|
exchange_rate_dkk_bought or 'Unknown',
|
||||||
exchange_rate_dkk_sold,
|
exchange_rate_dkk_sold or 'Unknown',
|
||||||
f'=F{row_idx}*D{row_idx}',
|
f'=D{row_idx}*E{row_idx}',
|
||||||
f'=E{row_idx}*D{row_idx}',
|
f'=D{row_idx}*F{row_idx}',
|
||||||
f'=max(0, G{row_idx} - H{row_idx})',
|
|
||||||
f'=max(0, H{row_idx} - G{row_idx})',
|
f'=max(0, H{row_idx} - G{row_idx})',
|
||||||
|
f'=max(0, G{row_idx} - H{row_idx})',
|
||||||
]
|
]
|
||||||
sheet.append(row)
|
sheet.append(row)
|
||||||
row_idx+= 1
|
row_idx+= 1
|
||||||
|
@ -245,26 +245,33 @@ def write_overview(sheet, tax_report: TaxReport, sums):
|
||||||
sheet['A9'] = 'Ledger'
|
sheet['A9'] = 'Ledger'
|
||||||
sheet['B9'] = 'Afdækker alle handler og overførsler.'
|
sheet['B9'] = 'Afdækker alle handler og overførsler.'
|
||||||
sheet['A10'] = 'FIFO Stablecoin'
|
sheet['A10'] = 'FIFO Stablecoin'
|
||||||
sheet['B10'] = 'Beregner profit og tab for stablecoins ved FIFO-pricippet.'
|
sheet['B10'] = 'Beregner gevinst og tab for stablecoins ved FIFO-pricippet.'
|
||||||
sheet['A11'] = 'FIFO Kryptovaluta'
|
sheet['A11'] = 'FIFO Kryptovaluta'
|
||||||
sheet['B11'] = 'Beregner profit og tab for kryptovaluta ved FIFO-pricippet.'
|
sheet['B11'] = 'Beregner gevinst og tab for kryptovaluta ved FIFO-pricippet.'
|
||||||
sheet['A12'] = 'FIFO Fiat'
|
sheet['A12'] = 'FIFO Fiat'
|
||||||
sheet['B12'] = 'Beregner profit og tab for udenlandsk valuta ved FIFO-pricippet.'
|
sheet['B12'] = 'Beregner gevinst og tab for udenlandsk valuta ved FIFO-pricippet.'
|
||||||
|
|
||||||
# Beregnet kolonner
|
# Beregnet kolonner
|
||||||
sheet['D6'] = 'Beregnet Skatte Kolonnner' # TODO
|
sheet['D6'] = 'Beregnet Skatte Rubrikker' # TODO
|
||||||
sheet.merge_cells('D6:E6')
|
sheet.merge_cells('D6:E6')
|
||||||
sheet['A4'].alignment = ALIGN_CENTER
|
sheet['A4'].alignment = ALIGN_CENTER
|
||||||
sheet['D7'] = 'Kolonne' # TODO
|
sheet['D7'] = 'Rubrik' # TODO
|
||||||
sheet['E7'] = 'Værdi'
|
sheet['E7'] = 'Værdi'
|
||||||
sheet['D8'] = 'Profit Krypto'
|
|
||||||
|
sheet['D8'] = 'Rubrik 20'
|
||||||
sheet['E8'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][0]
|
sheet['E8'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][0]
|
||||||
sheet['D9'] = 'Tab Krypto'
|
sheet['F8'] = '(Gevinst ved kryptospekulation)'
|
||||||
|
sheet['G8'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/beregn-og-oplys-gevinst-og-tab-paa-krypto'
|
||||||
|
|
||||||
|
sheet['D9'] = 'Rubrik 58'
|
||||||
sheet['E9'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][1]
|
sheet['E9'] = '=$\'FIFO Kryptovaluta\'.'+sums['Kryptovaluta'][1]
|
||||||
sheet['D10'] = 'Profit Stable Coin'
|
sheet['F9'] = '(Tab ved kryptospekulation)'
|
||||||
sheet['E10'] = '=$\'FIFO Stable Coin\'.'+sums['Stable Coin'][0]
|
sheet['G10'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/beregn-og-oplys-gevinst-og-tab-paa-krypto'
|
||||||
sheet['D11'] = 'Profit Stable Coin'
|
|
||||||
sheet['E11'] = '=$\'FIFO Stable Coin\'.'+sums['Stable Coin'][1]
|
sheet['D10'] = 'Rubrik 346'
|
||||||
|
sheet['E10'] = f"=$'FIFO Stable Coin'.{sums['Stable Coin'][0]}'-$'FIFO Stable Coin'.{sums['Stable Coin'][1]}'"
|
||||||
|
sheet['F10'] = '(Gevinst og Tab ved Stable Coin / Financiel Kontrakt)'
|
||||||
|
sheet['G10'] = 'Kilde: https://skat.dk/borger/aktier-og-andre-vaerdipapirer/skat-paa-krypto-kend-reglerne-saa-du-undgaar-et-skattesmaek/stablecoins-finansielle-kontrakter'
|
||||||
|
|
||||||
|
|
||||||
# Disclaimer
|
# Disclaimer
|
||||||
|
@ -275,6 +282,11 @@ def write_overview(sheet, tax_report: TaxReport, sums):
|
||||||
sheet.column_dimensions['B'].width = 70
|
sheet.column_dimensions['B'].width = 70
|
||||||
sheet.row_dimensions[4].height = 60
|
sheet.row_dimensions[4].height = 60
|
||||||
|
|
||||||
|
sheet.column_dimensions['D'].width = 20
|
||||||
|
sheet.column_dimensions['E'].width = 20
|
||||||
|
sheet.column_dimensions['F'].width = 50
|
||||||
|
sheet.column_dimensions['G'].width = 80
|
||||||
|
|
||||||
|
|
||||||
def produce_excel_report(report: TaxReport, output_path: Path):
|
def produce_excel_report(report: TaxReport, output_path: Path):
|
||||||
workbook = openpyxl.Workbook()
|
workbook = openpyxl.Workbook()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user