def test_buy_event_creation(accountant): history = [{ 'timestamp': 1476979735, 'pair': 'BTC_EUR', 'trade_type': 'buy', 'rate': 578.505, 'fee': 0.0012, 'fee_currency': 'BTC', 'amount': 5, 'location': 'kraken', }, { 'timestamp': 1476979735, 'pair': 'BTC_EUR', 'trade_type': 'buy', 'rate': 578.505, 'fee': 0.0012, 'fee_currency': 'EUR', 'amount': 5, 'location': 'kraken', }] accounting_history_process(accountant, 1436979735, 1519693374, history) buys = accountant.events.events['BTC'].buys assert len(buys) == 2 assert buys[0].amount == FVal(5) assert buys[0].timestamp == 1476979735 assert buys[0].rate == FVal('578.505') assert buys[0].fee_rate == FVal('0.1388412') assert buys[1].amount == FVal(5) assert buys[1].timestamp == 1476979735 assert buys[1].rate == FVal('578.505') assert buys[1].fee_rate == FVal('2.4e-4')
def test_no_corresponding_buy_for_sell(accountant, google_service): """Test that if there is no corresponding buy for a sell, the entire sell counts as profit""" history = [ Trade( timestamp=1476979735, location=Location.KRAKEN, base_asset=A_BTC, quote_asset=A_EUR, trade_type=TradeType.SELL, amount=FVal(1), rate=FVal('2519.62'), fee=FVal('0.02'), fee_currency=A_EUR, link=None, ) ] accounting_history_process( accountant=accountant, start_ts=1436979735, end_ts=1519693374, history_list=history, ) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('2519.62'), free=ZERO), AccountingEventType.FEE: PNL(taxable=FVal('-0.02'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_buy_event_creation(accountant): history = [{ "timestamp": 1476979735, "pair": "BTC_EUR", "type": "buy", "rate": 578.505, "fee": 0.0012, "fee_currency": "BTC", "amount": 5, "location": "kraken", }, { "timestamp": 1476979735, "pair": "BTC_EUR", "type": "buy", "rate": 578.505, "fee": 0.0012, "fee_currency": "EUR", "amount": 5, "location": "kraken", }] accounting_history_process(accountant, 1436979735, 1519693374, history) buys = accountant.events.events['BTC'].buys assert len(buys) == 2 assert buys[0].amount == FVal(5) assert buys[0].timestamp == 1476979735 assert buys[0].rate == FVal('578.505') assert buys[0].fee_rate == FVal('0.1388412') assert buys[1].amount == FVal(5) assert buys[1].timestamp == 1476979735 assert buys[1].rate == FVal('578.505') assert buys[1].fee_rate == FVal('2.4e-4')
def test_receiving_value_from_tx(accountant, google_service): """ Test that receiving a transaction that provides value works fine """ addr2 = make_ethereum_address() tx_hash = '0x5cc0e6e62753551313412492296d5e57bea0a9d1ce507cc96aa4aa076c5bde7a' history = [ HistoryBaseEntry( event_identifier=tx_hash, sequence_index=0, timestamp=1569924574000, location=Location.BLOCKCHAIN, location_label=make_ethereum_address(), asset=A_ETH, balance=Balance(amount=FVal('1.5')), notes=f'Received 1.5 ETH from {addr2}', event_type=HistoryEventType.RECEIVE, event_subtype=HistoryEventSubType.NONE, counterparty=addr2, ) ] accounting_history_process( accountant, start_ts=0, end_ts=1640493376, history_list=history, ) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRANSACTION_EVENT: PNL(taxable=FVal('242.385'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_taxable_ledger_action_setting(accountant, expected, google_service): """Test that ledger actions respect the taxable setting""" history = [ LedgerAction( identifier=1, timestamp=1476979735, action_type=LedgerActionType.INCOME, location=Location.EXTERNAL, amount=FVal(1), # 578.505 EUR/BTC from mocked prices asset=A_BTC, rate=None, rate_asset=None, link=None, notes=None, ), LedgerAction( identifier=2, timestamp=1491062063, action_type=LedgerActionType.AIRDROP, location=Location.EXTERNAL, amount=FVal(10), # 47.865 EUR/ETH from mocked prices asset=A_ETH, rate=None, rate_asset=None, link='foo', notes='boo', ), LedgerAction( identifier=3, timestamp=1501062063, action_type=LedgerActionType.LOSS, location=Location.BLOCKCHAIN, amount=FVal(2), # 175.44 EUR/ETH from mocked prices asset=A_ETH, rate=FVal(400), # but should use the given rate of 400 EUR rate_asset=A_EUR, link='goo', notes='hoo', ), LedgerAction( # include a non taxed ledger action too identifier=4, timestamp=1501062064, action_type=LedgerActionType.EXPENSE, location=Location.BLOCKCHAIN, amount=FVal(1), asset=A_ETH, rate=FVal(400), rate_asset=A_EUR, link='goo2', notes='hoo2', ), ] accounting_history_process( accountant=accountant, start_ts=1436979735, end_ts=1519693374, history_list=history, ) expected_pnls = PnlTotals() if expected != 0: expected_pnls[AccountingEventType.LEDGER_ACTION] = PNL(taxable=FVal(expected), free=ZERO) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_buying_selling_eth_before_daofork(accountant, google_service): history3 = [ Trade( timestamp=1446979735, # 11/08/2015 location=Location.EXTERNAL, base_asset=A_ETH, quote_asset=A_EUR, trade_type=TradeType.BUY, amount=FVal(1450), rate=FVal('0.2315893'), fee=None, fee_currency=None, link=None, ), Trade( # selling ETH prefork should also reduce our ETC amount timestamp=1461021812, # 18/04/2016 (taxable) location=Location.KRAKEN, base_asset=A_ETH, # cryptocompare hourly ETC/EUR price: 7.88 quote_asset=A_EUR, trade_type=TradeType.SELL, amount=FVal(50), rate=FVal('7.88'), fee=FVal('0.5215'), fee_currency=A_EUR, link=None, ), Trade( # selling ETC after the fork timestamp=1481979135, # 17/12/2016 location=Location.KRAKEN, base_asset=A_ETC, # cryptocompare hourly ETC/EUR price: 7.88 quote_asset=A_EUR, trade_type=TradeType.SELL, # not-taxable -- considered bought with ETH so after year amount=FVal(550), rate=FVal('1.78'), fee=FVal('0.9375'), fee_currency=A_EUR, link=None, ), Trade( # selling ETH after the fork timestamp=1482138141, # 19/12/2016 location=Location.KRAKEN, base_asset=A_ETH, # cryptocompare hourly ETH/EUR price: 7.45 quote_asset=A_EUR, trade_type=TradeType.SELL, # not-taxable -- after 1 year amount=FVal(10), rate=FVal('7.45'), fee=FVal('0.12'), fee_currency=A_EUR, link=None, ), ] accounting_history_process(accountant, 1436979735, 1495751688, history3) no_message_errors(accountant.msg_aggregator) # make sure that the intermediate ETH sell before the fork reduced our ETC assert accountant.pots[0].cost_basis.get_calculated_asset_amount('ETC') == FVal(850) assert accountant.pots[0].cost_basis.get_calculated_asset_amount('ETH') == FVal(1390) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('382.4205350'), free=FVal('923.8099920')), AccountingEventType.FEE: PNL(taxable=FVal('-1.579'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_buying_selling_btc_before_bchfork(accountant): history = [{ 'timestamp': 1491593374, # 04/07/2017 'base_asset': 'BTC', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 1128.905, 'fee': 0.55, 'fee_currency': 'EUR', 'amount': 6.5, 'location': 'external', }, { # selling BTC prefork should also reduce the BCH equivalent -- taxable 'timestamp': 1500595200, # 21/07/2017 'base_asset': 'BTC', 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 2380.835, 'fee': 0.15, 'fee_currency': 'EUR', 'amount': 0.5, 'location': 'external', }, { # selling BCH after the fork -- taxable 'timestamp': 1512693374, # 08/12/2017 'base_asset': 'BCH', # cryptocompare hourly BCH/EUR price: 995.935 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 995.935, 'fee': 0.26, 'fee_currency': 'EUR', 'amount': 2.1, 'location': 'kraken', }, { 'timestamp': 1514937600, # 03/01/2018 'base_asset': 'BTC', # cryptocompare hourly BCH/EUR price: 995.935 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 12404.88, 'fee': 0.52, 'fee_currency': 'EUR', 'amount': 1.2, 'location': 'kraken', }] accounting_history_process(accountant, 1436979735, 1519693374, history) amount_bch = FVal(3.9) amount_btc = FVal(4.8) buys = accountant.events.cost_basis.get_events(A_BCH).acquisitions assert len(buys) == 1 assert buys[0].remaining_amount == amount_bch assert buys[0].timestamp == 1491593374 assert buys[0].rate == FVal('1128.905') assert buys[0].fee_rate.is_close(FVal('0.0846153846154')) assert accountant.events.cost_basis.get_calculated_asset_amount( A_BCH) == amount_bch assert accountant.events.cost_basis.get_calculated_asset_amount( A_BTC) == amount_btc assert accountant.general_trade_pl.is_close('13876.6464615') assert accountant.taxable_trade_pl.is_close('13876.6464615')
def test_mismatch_in_amount_rate_and_cost(accountant): with pytest.raises(CorruptData): accounting_history_process(accountant, 1436979735, 1495751688, bad_history1) with pytest.raises(CorruptData): accounting_history_process(accountant, 1436979735, 1495751688, bad_history2)
def test_nocrypto2crypto(accountant): accounting_history_process(accountant, 1436979735, 1519693374, history5) # Expected = 3 trades + the creation of ETC and BCH after fork times msg = 'The crypto to crypto trades should not appear in the list at all' assert len(accountant.csvexporter.all_events) == 5, msg assert accountant.general_trade_pl.is_close("264693.43364282") assert accountant.taxable_trade_pl.is_close("0")
def test_selling_crypto_bought_with_crypto(accountant, google_service): history = [ Trade( timestamp=1446979735, location=Location.EXTERNAL, base_asset=A_BTC, quote_asset=A_EUR, trade_type=TradeType.BUY, amount=FVal(82), rate=FVal('268.678317859'), fee=None, fee_currency=None, link=None, ), Trade( timestamp=1449809536, # cryptocompare hourly BTC/EUR price: 386.175 location=Location.POLONIEX, base_asset=A_XMR, # cryptocompare hourly XMR/EUR price: 0.39665 quote_asset=A_BTC, trade_type=TradeType.BUY, amount=FVal(375), rate=FVal('0.0010275'), fee=FVal('0.9375'), fee_currency=A_XMR, link=None, ), Trade( timestamp= 1458070370, # cryptocompare hourly rate XMR/EUR price: 1.0443027675 location=Location.KRAKEN, base_asset=A_XMR, quote_asset=A_EUR, trade_type=TradeType.SELL, amount=FVal(45), rate=FVal('1.0443027675'), fee=FVal('0.117484061344'), fee_currency=A_XMR, link=None, ), ] accounting_history_process(accountant, 1436979735, 1495751688, history) no_message_errors(accountant.msg_aggregator) # Make sure buying XMR with BTC also creates a BTC sell sells = accountant.pots[0].cost_basis.get_events(A_BTC).spends assert len(sells) == 1 assert sells[0].timestamp == 1449809536 assert sells[0].amount.is_close(FVal('0.3853125')) assert sells[0].rate.is_close(FVal('386.03406326')) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('74.3118704999540625'), free=ZERO), AccountingEventType.FEE: PNL(taxable=FVal('-0.419658351381311222'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_no_taxfree_period(accountant, google_service): accounting_history_process(accountant, 1436979735, 1519693374, history5) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('265253.1283582327833875'), free=ZERO), AccountingEventType.FEE: PNL(taxable=FVal('-0.238868129979988140934107'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_nocrypto2crypto(accountant, google_service): accounting_history_process(accountant, 1436979735, 1519693374, history5) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=ZERO, free=FVal('264693.433642820')), AccountingEventType.FEE: PNL(taxable=FVal('-1.1708853227087498964'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_simple_accounting(accountant, google_service): accounting_history_process(accountant, 1436979735, 1495751688, history1) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('559.6947154'), free=ZERO), AccountingEventType.FEE: PNL(taxable=FVal('-0.23886813'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_fees_count_in_cost_basis(accountant, google_service): """Make sure that asset amounts used in fees are reduced.""" history = [ Trade( timestamp=1609537953, location=Location.KRAKEN, base_asset=A_ETH, quote_asset=A_EUR, trade_type=TradeType.BUY, amount=ONE, rate=FVal('598.26'), fee=ONE, fee_currency=A_EUR, link=None, ), Trade( # PNL: 0.5 * 1862.06 - 0.5 * 599.26 -> 631.4 # fee: -0.5 * 1862.06 + 0.5 * 1862.06 - 0.5 * 599.26 -> -299.63 timestamp=1624395186, location=Location.KRAKEN, base_asset=A_ETH, quote_asset=A_EUR, trade_type=TradeType.SELL, amount=FVal('0.5'), rate=FVal('1862.06'), fee=FVal('0.5'), fee_currency=A_ETH, link=None, ), Trade( timestamp=1625001464, location=Location.KRAKEN, base_asset=A_ETH, quote_asset=A_EUR, trade_type=TradeType.SELL, amount=FVal('0.5'), rate=FVal('1837.31'), fee=None, fee_currency=None, link=None, ), ] accounting_history_process( accountant=accountant, start_ts=1436979735, end_ts=1625001466, history_list=history, ) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=FVal('1550.055'), free=ZERO), AccountingEventType.FEE: PNL(taxable=FVal('-300.630'), free=ZERO), }) assert accountant.pots[0].cost_basis.get_calculated_asset_amount(A_ETH) is None warnings = accountant.msg_aggregator.consume_warnings() assert len(warnings) == 0 check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_accounting_works_for_empty_history(accountant, google_service): history = [] accounting_history_process( accountant=accountant, start_ts=1436979735, end_ts=1519693374, history_list=history, ) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals() check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_selling_crypto_bought_with_crypto(accountant): history = [ { "timestamp": 1446979735, "pair": "BTC_EUR", "type": "buy", "rate": 268.678317859, "cost": 22031.6220644, "cost_currency": "EUR", "fee": 0, "fee_currency": "BTC", "amount": 82, "location": "external", }, { 'timestamp': 1449809536, # cryptocompare hourly BTC/EUR price: 386.175 'pair': 'BTC_XMR', # cryptocompare hourly XMR/EUR price: 0.396987900 'type': 'buy', # Buy XMR with BTC 'rate': 0.0010275, 'cost': 0.3853125, 'cost_currency': 'BTC', 'fee': 0.9375, 'fee_currency': 'XMR', 'amount': 375, 'location': 'poloniex', }, { 'timestamp': 1458070370, # cryptocompare hourly rate XMR/EUR price: 1.0443027675 'pair': 'XMR_EUR', 'type': 'sell', # Sell XMR for EUR 'rate': 1.0443027675, 'cost': 46.9936245375, 'cost_currency': 'EUR', 'fee': 0.117484061344, 'fee_currency': 'EUR', 'amount': 45, 'location': 'kraken', } ] accounting_history_process(accountant, 1436979735, 1495751688, history) # Make sure buying XMR with BTC also creates a BTC sell sells = accountant.events.events['BTC'].sells assert len(sells) == 1 assert sells[0].amount == FVal('0.3853125') assert sells[0].timestamp == 1449809536 assert sells[0].rate == FVal('386.175') assert sells[0].fee_rate.is_close(FVal('0.96590729927')) assert sells[0].gain.is_close(FVal('148.798054688')) assert accountant.general_trade_pl.is_close("73.8764769569") assert accountant.taxable_trade_pl.is_close("73.8764769569")
def test_buying_selling_eth_before_daofork(accountant): history3 = [ { "timestamp": 1446979735, # 11/08/2015 "pair": "ETH_EUR", "type": "buy", "rate": 0.2315893, "cost": 335.804485, "cost_currency": "EUR", "fee": 0, "fee_currency": "ETH", "amount": 1450, "location": "external", }, { # selling ETH prefork should also reduce our ETC amount 'timestamp': 1461021812, # 18/04/2016 (taxable) 'pair': 'ETH_EUR', # cryptocompare hourly ETC/EUR price: 7.88 'type': 'sell', 'rate': 7.88, 'cost': 394, 'cost_currency': 'EUR', 'fee': 0.5215, 'fee_currency': 'EUR', 'amount': 50, 'location': 'kraken', }, { # sell ETC after the fork 'timestamp': 1481979135, # 17/12/2016 'pair': 'ETC_EUR', # cryptocompare hourly ETC/EUR price: 1.78 'type': 'sell', # not-taxable -- considered bought with ETH so after year 'rate': 1.78, 'cost': 979, 'cost_currency': 'EUR', 'fee': 0.9375, 'fee_currency': 'EUR', 'amount': 550, 'location': 'kraken', }, { # selling ETH after fork should not affect ETC amount 'timestamp': 1482138141, # 19/12/2016 'pair': 'ETH_EUR', # cryptocompare hourly ETC/EUR price: 7.45 'type': 'sell', # not taxable after 1 year 'rate': 7.45, 'cost': 74.5, 'cost_currency': 'EUR', 'fee': 0.12, 'fee_currency': 'EUR', 'amount': 10, 'location': 'kraken', }, ] accounting_history_process(accountant, 1436979735, 1495751688, history3) # make sure that the intermediate ETH sell before the fork reduced our ETC assert accountant.get_calculated_asset_amount('ETC') == FVal(850) assert accountant.get_calculated_asset_amount('ETH') == FVal(1390) assert accountant.general_trade_pl.is_close('1304.651527') assert accountant.taxable_trade_pl.is_close('381.899035')
def test_kfee_price_in_accounting(accountant, google_service): """ Test that KFEEs are correctly handled during accounting KFEE price is fixed at $0.01 """ history = [ LedgerAction( identifier=0, timestamp=Timestamp(1539713238), # 178.615 EUR/ETH action_type=LedgerActionType.INCOME, location=Location.KRAKEN, amount=FVal(1), asset=A_ETH, rate=None, rate_asset=None, link=None, notes='', ), LedgerAction( identifier=0, timestamp=Timestamp(1539713238), # 0.8612 USD/EUR. 1 KFEE = $0.01 so 8.612 EUR action_type=LedgerActionType.INCOME, location=Location.KRAKEN, amount=FVal(1000), asset=A_KFEE, rate=None, rate_asset=None, link=None, notes='', ), Trade( timestamp=1609537953, location=Location.KRAKEN, # 0.89 USDT/EUR -> PNL: 20 * 0.89 - 0.02*178.615 -> 14.2277 base_asset=A_ETH, quote_asset=A_USDT, trade_type=TradeType.SELL, amount=FVal('0.02'), rate=FVal(1000), fee=FVal(30), # KFEE should not be taken into account fee_currency=A_KFEE, link=None, ), ] accounting_history_process( accountant, start_ts=1539713238, end_ts=1624395187, history_list=history, ) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=ZERO, free=FVal('14.2277')), AccountingEventType.LEDGER_ACTION: PNL(taxable=FVal('187.227'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_buying_selling_btc_before_bchfork(accountant): history = [{ "timestamp": 1491593374, # 04/07/2017 "pair": "BTC_EUR", "type": "buy", "rate": 1128.905, "fee": 0.55, "fee_currency": "EUR", "amount": 6.5, "location": "external", }, { # selling BTC prefork should also reduce the BCH equivalent -- taxable "timestamp": 1500595200, # 21/07/2017 "pair": "BTC_EUR", "type": "sell", "rate": 2380.835, "fee": 0.15, "fee_currency": "EUR", "amount": 0.5, "location": "external", }, { # selling BCH after the fork -- taxable 'timestamp': 1512693374, # 08/12/2017 'pair': 'BCH_EUR', # cryptocompare hourly BCH/EUR price: 995.935 'type': 'sell', 'rate': 995.935, 'fee': 0.26, 'fee_currency': 'EUR', 'amount': 2.1, 'location': 'kraken', }, { 'timestamp': 1514937600, # 03/01/2018 'pair': 'BTC_EUR', # cryptocompare hourly BCH/EUR price: 995.935 'type': 'sell', 'rate': 12404.88, 'fee': 0.52, 'fee_currency': 'EUR', 'amount': 1.2, 'location': 'kraken', }] accounting_history_process(accountant, 1436979735, 1519693374, history) amount_BCH = FVal(3.9) amount_BTC = FVal(4.8) buys = accountant.events.events['BCH'].buys assert len(buys) == 1 assert buys[0].amount == amount_BCH assert buys[0].timestamp == 1491593374 assert buys[0].rate == FVal('1128.905') assert buys[0].fee_rate.is_close(FVal('0.0846153846154')) assert accountant.get_calculated_asset_amount('BCH') == amount_BCH assert accountant.get_calculated_asset_amount('BTC') == amount_BTC assert accountant.general_trade_pl.is_close("13876.6464615") assert accountant.taxable_trade_pl.is_close("13876.6464615")
def test_buying_selling_eth_before_daofork(accountant): history3 = [ { 'timestamp': 1446979735, # 11/08/2015 'base_asset': 'ETH', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 0.2315893, 'fee': 0, 'fee_currency': 'ETH', 'amount': 1450, 'location': 'external', }, { # selling ETH prefork should also reduce our ETC amount 'timestamp': 1461021812, # 18/04/2016 (taxable) 'base_asset': 'ETH', # cryptocompare hourly ETC/EUR price: 7.88 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 7.88, 'fee': 0.5215, 'fee_currency': 'EUR', 'amount': 50, 'location': 'kraken', }, { # sell ETC after the fork 'timestamp': 1481979135, # 17/12/2016 'base_asset': 'ETC', # cryptocompare hourly ETC/EUR price: 1.78 'quote_asset': 'EUR', 'trade_type': 'sell', # not-taxable -- considered bought with ETH so after year 'rate': 1.78, 'fee': 0.9375, 'fee_currency': 'EUR', 'amount': 550, 'location': 'kraken', }, { # selling ETH after fork should not affect ETC amount 'timestamp': 1482138141, # 19/12/2016 'base_asset': 'ETH', # cryptocompare hourly ETC/EUR price: 7.45 'quote_asset': 'EUR', 'trade_type': 'sell', # not taxable after 1 year 'rate': 7.45, 'fee': 0.12, 'fee_currency': 'EUR', 'amount': 10, 'location': 'kraken', }, ] accounting_history_process(accountant, 1436979735, 1495751688, history3) # make sure that the intermediate ETH sell before the fork reduced our ETC assert accountant.events.cost_basis.get_calculated_asset_amount( 'ETC') == FVal(850) assert accountant.events.cost_basis.get_calculated_asset_amount( 'ETH') == FVal(1390) assert accountant.general_trade_pl.is_close('1304.651527') assert accountant.taxable_trade_pl.is_close('381.899035')
def test_big_taxfree_period(accountant, google_service): accounting_history_process(accountant, 1436979735, 1519693374, history5) no_message_errors(accountant.msg_aggregator) expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=ZERO, free=FVal('265253.1283582327833875')), AccountingEventType.FEE: PNL( taxable=FVal('-1.170885322708749896'), free=FVal('0.932017192728761755465893'), ), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_selling_crypto_bought_with_crypto(accountant): history = [ { 'timestamp': 1446979735, 'base_asset': 'BTC', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 268.678317859, 'fee': 0, 'fee_currency': 'BTC', 'amount': 82, 'location': 'external', }, { 'timestamp': 1449809536, # cryptocompare hourly BTC/EUR price: 386.175 'base_asset': 'XMR', # cryptocompare hourly XMR/EUR price: 0.39665 'quote_asset': 'BTC', 'trade_type': 'buy', # Buy XMR with BTC 'rate': 0.0010275, 'fee': 0.9375, 'fee_currency': 'XMR', 'amount': 375, 'location': 'poloniex', }, { 'timestamp': 1458070370, # cryptocompare hourly rate XMR/EUR price: 1.0443027675 'base_asset': 'XMR', 'quote_asset': 'EUR', 'trade_type': 'sell', # Sell XMR for EUR 'rate': 1.0443027675, 'fee': 0.117484061344, 'fee_currency': 'EUR', 'amount': 45, 'location': 'kraken', } ] accounting_history_process(accountant, 1436979735, 1495751688, history) # Make sure buying XMR with BTC also creates a BTC sell sells = accountant.events.cost_basis.get_events(A_BTC).spends assert len(sells) == 1 assert sells[0].amount == FVal('0.3853125') assert sells[0].timestamp == 1449809536 assert sells[0].rate.is_close(FVal('386.0340632603')) assert sells[0].fee_rate == Fee( ZERO) # the fee should not be double counted assert sells[0].gain.is_close(FVal('148.74375')) assert accountant.general_trade_pl.is_close('74.1943864386100625') assert accountant.taxable_trade_pl.is_close('74.1943864386100625')
def test_fees_in_received_asset(accountant, google_service): """ Test the sell trade where the fee is nominated in the asset received. We had a bug where the PnL report said that there was no documented acquisition. """ history = [ LedgerAction( identifier=0, timestamp=Timestamp(1539713238), # 178.615 EUR/ETH action_type=LedgerActionType.INCOME, location=Location.BINANCE, amount=ONE, asset=A_ETH, rate=None, rate_asset=None, link=None, notes='', ), Trade( # Sell 0.02 ETH for USDT with rate 1000 USDT/ETH and 0.10 USDT fee # So acquired 20 USDT for 0.02 ETH + 0.10 USDT # So acquired 20 USDT for 0.02 * 598.26 + 0.10 * 0.89 -> 12.0542 EUR # So paid 12.0542/20 -> 0.60271 EUR/USDT timestamp=1609537953, # 0.89 EUR/USDT location=Location.BINANCE, base_asset=A_ETH, # 598.26 EUR/ETH quote_asset=A_USDT, trade_type=TradeType.SELL, amount=FVal('0.02'), rate=FVal(1000), fee=FVal('0.10'), fee_currency=A_USDT, link=None, ), ] accounting_history_process( accountant, start_ts=1539713238, end_ts=1624395187, history_list=history, ) no_message_errors(accountant.msg_aggregator) assert accountant.pots[0].cost_basis.get_calculated_asset_amount(A_USDT.identifier).is_close('19.90') # noqa: E501 expected_pnls = PnlTotals({ AccountingEventType.TRADE: PNL(taxable=ZERO, free=FVal('14.2277')), AccountingEventType.FEE: PNL(taxable=FVal('-0.060271'), free=ZERO), AccountingEventType.LEDGER_ACTION: PNL(taxable=FVal('178.615'), free=ZERO), }) check_pnls_and_csv(accountant, expected_pnls, google_service)
def test_simple_accounting_with_unknown_and_unsupported_assets(accountant): """Make sure that if for some reason in the action processing we get an unknown asset a warning is logged and we don't crash. Note though that if this happens probably something wrong happened in the history creation as the unknown/unsupported assets should have been filtered out then""" history = history1 + history_unknown_assets accounting_history_process(accountant, 1436979735, 1495751688, history) assert accountant.general_trade_pl.is_close('557.52845490257') assert accountant.taxable_trade_pl.is_close('557.52845490257') warnings = accountant.msg_aggregator.consume_warnings() assert len(warnings) == 1 assert 'found a trade containing unknown asset UNKNOWNASSET. Ignoring it.' in warnings[0]
def test_ignored_assets(accountant): history = history1 + [{ 'timestamp': 1476979735, 'base_asset': 'DASH', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 9.76775956284, 'fee': 0.0011, 'fee_currency': 'DASH', 'amount': 10, 'location': 'kraken', }, { 'timestamp': 1496979735, 'base_asset': 'DASH', 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 128.09, 'fee': 0.015, 'fee_currency': 'EUR', 'amount': 5, 'location': 'kraken', }] result = accounting_history_process(accountant, 1436979735, 1519693374, history) assert FVal(result['overview']['total_taxable_profit_loss']).is_close( '557.5284549025')
def test_ignored_assets(accountant): history = history1 + [{ "timestamp": 1476979735, "pair": "DASH_EUR", "type": "buy", "rate": 9.76775956284, "cost": 97.6775956284, "cost_currency": "EUR", "fee": 0.0011, "fee_currency": "DASH", "amount": 10, "location": "kraken", }, { "timestamp": 1496979735, "pair": "DASH_EUR", "type": "sell", "rate": 128.09, "cost": 640.45, "cost_currency": "EUR", "fee": 0.015, "fee_currency": "EUR", "amount": 5, "location": "kraken", }] result = accounting_history_process(accountant, 1436979735, 1519693374, history) assert FVal(result['overview']['total_taxable_profit_loss']).is_close( "557.528104903")
def test_asset_and_price_not_found_in_history_processing(accountant): """ Make sure that in history processing if no price is found for a trade it's skipped and an error is logged. Regression for https://github.com/rotki/rotki/issues/432 """ bad_trades = [{ 'timestamp': 1492685761, 'pair': 'FGP_BTC', 'trade_type': 'buy', 'rate': '0.100', 'fee': '0.15', 'fee_currency': 'FGP', 'amount': 2.5, 'location': 'kraken', }] result = accounting_history_process( accountant=accountant, start_ts=0, end_ts=1514764799, # 31/12/2017 history_list=bad_trades, loans_list=[], asset_movements_list=[], eth_transaction_list=[], margin_list=[], ) result = result['overview'] errors = accountant.msg_aggregator.consume_errors() assert len(errors) == 1 assert 'due to inability to find a price at that point in time' in errors[ 0] # assert 'due to an asset unknown to cryptocompare being involved' in errors[1] assert FVal(result['total_profit_loss']) == FVal('0')
def test_selling_crypto_bought_with_crypto(accountant): history = [ { 'timestamp': 1446979735, 'pair': 'BTC_EUR', 'trade_type': 'buy', 'rate': 268.678317859, 'fee': 0, 'fee_currency': 'BTC', 'amount': 82, 'location': 'external', }, { 'timestamp': 1449809536, # cryptocompare hourly BTC/EUR price: 386.175 'pair': 'XMR_BTC', # cryptocompare hourly XMR/EUR price: 0.39665 'trade_type': 'buy', # Buy XMR with BTC 'rate': 0.0010275, 'fee': 0.9375, 'fee_currency': 'XMR', 'amount': 375, 'location': 'poloniex', }, { 'timestamp': 1458070370, # cryptocompare hourly rate XMR/EUR price: 1.0443027675 'pair': 'XMR_EUR', 'trade_type': 'sell', # Sell XMR for EUR 'rate': 1.0443027675, 'fee': 0.117484061344, 'fee_currency': 'EUR', 'amount': 45, 'location': 'kraken', } ] accounting_history_process(accountant, 1436979735, 1495751688, history) # Make sure buying XMR with BTC also creates a BTC sell sells = accountant.events.events['BTC'].sells assert len(sells) == 1 assert sells[0].amount == FVal('0.3853125') assert sells[0].timestamp == 1449809536 assert sells[0].rate.is_close(FVal('386.0340632603')) assert sells[0].fee_rate.is_close(FVal('0.96508515815085')) assert sells[0].gain.is_close(FVal('148.74375')) assert accountant.general_trade_pl.is_close('73.8225270636') assert accountant.taxable_trade_pl.is_close('73.8225270636')
def test_margin_events_affect_gained_lost_amount(accountant): history = [{ 'timestamp': 1476979735, 'pair': 'BTC_EUR', 'trade_type': 'buy', 'rate': 578.505, 'fee': 0.0012, 'fee_currency': 'BTC', 'amount': 5, 'location': 'kraken', }, { # 2519.62-0.02-((0.0012*578.505)/5 + 578.505) 'timestamp': 1496979735, 'pair': 'BTC_EUR', 'trade_type': 'sell', 'rate': 2519.62, 'fee': 0.02, 'fee_currency': 'EUR', 'amount': 1, 'location': 'kraken', }] margin_history = [ MarginPosition( location=Location.POLONIEX, # BTC/EUR: 810.49 open_time=1484438400, # 15/01/2017 close_time=1484629704, # 17/01/2017 profit_loss=FVal('-0.5'), pl_currency=A_BTC, fee=FVal('0.001'), fee_currency=A_BTC, link='1', notes='margin1', ), MarginPosition( location=Location.POLONIEX, # BTC/EUR: 979.39 open_time=1487116800, # 15/02/2017 close_time=1487289600, # 17/02/2017 profit_loss=FVal('0.25'), pl_currency=A_BTC, fee=FVal('0.001'), fee_currency=A_BTC, link='2', notes='margin2', ) ] result = accounting_history_process( accountant, 1436979735, 1519693374, history, margin_list=margin_history, ) assert accountant.get_calculated_asset_amount('BTC').is_close('3.748') assert FVal(result['overview']['general_trade_profit_loss']).is_close( '1940.9561588') assert FVal(result['overview']['margin_positions_profit_loss']).is_close( '-162.18738') assert FVal(result['overview']['total_taxable_profit_loss']).is_close( '1778.7687788')
def test_not_calculate_past_cost_basis(accountant, db_settings): # trades copied from # rotkehlchen/tests/integration/test_end_to_end_tax_report.py history = [ { 'timestamp': 1446979735, # 08/11/2015 'base_asset': 'BTC', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 268.678317859, 'fee': 0, 'fee_currency': 'BTC', 'amount': 5, 'location': 'external', }, { 'timestamp': 1446979735, # 08/11/2015 'base_asset': 'ETH', 'quote_asset': 'EUR', 'trade_type': 'buy', 'rate': 0.2315893, 'fee': 0, 'fee_currency': 'ETH', 'amount': 1450, 'location': 'external', }, { 'timestamp': 1488373504, # 29/02/2017 'base_asset': 'BTC', 'quote_asset': 'EUR', 'trade_type': 'sell', 'rate': 1146.22, 'fee': 0.01, 'fee_currency': 'EUR', 'amount': 2, 'location': 'kraken', } ] result = accounting_history_process( accountant=accountant, start_ts=1466979735, end_ts=1519693374, history_list=history, ) sell_gain = (FVal(history[-1]['rate']) * FVal(history[-1]['amount']) - FVal(history[-1]['fee'])) if db_settings['calculate_past_cost_basis'] is True: buy_cost = FVal(history[0]['rate']) * FVal(history[-1]['amount']) expected = sell_gain - buy_cost else: expected = sell_gain assert FVal( result['overview']['taxable_trade_profit_loss']).is_close(expected) assert FVal( result['overview']['total_taxable_profit_loss']).is_close(expected) assert FVal(result['overview']['total_profit_loss']).is_close(expected)