In this vignette, we will demonstrate that calculations of the
adjusted cost base by cryptoTax
closely follows those of https://www.adjustedcostbase.ca/.
Basic ACB
To begin, we will replicate the basic ACB example showcased in https://www.adjustedcostbase.ca/blog/how-to-calculate-adjusted-cost-base-acb-and-capital-gains/
We first generate the data:
library(cryptoTax)
#> Error in get(paste0(generic, ".", class), envir = get_method_env()) :
#> object 'type_sum.accel' not found
data <- data_adjustedcostbase1
data
date | transaction | quantity | price | fees |
---|---|---|---|---|
2014-03-03 | buy | 100 | 50 | 10 |
2014-05-01 | sell | 50 | 120 | 10 |
2014-07-18 | buy | 50 | 130 | 10 |
2014-09-25 | sell | 40 | 90 | 10 |
Next, we generate the calculations to achieve the following result:
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | fees | total.price | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2014-03-03 | buy | 100 | 50 | 10 | 5000 | 100 | 5010 | 50.10 | NA |
2014-05-01 | sell | 50 | 120 | 10 | 6000 | 50 | 2505 | 50.10 | 3485 |
2014-07-18 | buy | 50 | 130 | 10 | 6500 | 100 | 9015 | 90.15 | NA |
2014-09-25 | sell | 40 | 90 | 10 | 3600 | 60 | 5409 | 90.15 | -16 |
Superficial losses
We will now replicate the more advanced superficial loss example showcased at https://www.adjustedcostbase.ca/blog/what-is-the-superficial-loss-rule/.
Example 1
We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_adjustedcostbase2
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2014-01-06 | buy | 100 | 50 | 5000 | 0 | 100 | 5000 | 50 | NA |
2014-11-03 | sell | 100 | 30 | 3000 | 0 | 0 | 0 | 0 | -2000 |
2014-11-04 | buy | 100 | 30 | 3000 | 0 | 100 | 3000 | 30 | NA |
2015-12-02 | sell | 100 | 80 | 8000 | 0 | 0 | 0 | 0 | 5000 |
Next, we do it the correct way, accounting for superficial losses:
Per default, setting sup.loss = TRUE
(the default)
generates a lot of columns to provide as much information as possible.
To make it look as short as the adjustedcostbase.ca example, we can
subselect relevant columns:
library(dplyr)
ACB(data, spot.rate = "price") %>%
select(date, transaction, quantity, price, total.quantity, ACB, ACB.share, gains)
date | transaction | quantity | price | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2014-01-06 | buy | 100 | 50 | 100 | 5000 | 50 | NA |
2014-11-03 | sell | 100 | 30 | 0 | 0 | 0 | NA |
2014-11-04 | buy | 100 | 30 | 100 | 5000 | 50 | NA |
2015-12-02 | sell | 100 | 80 | 0 | 0 | 0 | 3000 |
Example 2
We continue with the second superficial loss example. We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_adjustedcostbase3
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2014-01-06 | buy | 100 | 50 | 5000 | 0 | 100 | 5000 | 50 | NA |
2014-11-03 | buy | 100 | 30 | 3000 | 0 | 200 | 8000 | 40 | NA |
2014-11-04 | sell | 100 | 30 | 3000 | 0 | 100 | 4000 | 40 | -1000 |
2015-12-02 | sell | 100 | 80 | 8000 | 0 | 0 | 0 | 0 | 4000 |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, spot.rate = "price") %>%
select(date, transaction, quantity, price, total.quantity, ACB, ACB.share, gains)
date | transaction | quantity | price | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2014-01-06 | buy | 100 | 50 | 100 | 5000 | 50 | NA |
2014-11-03 | buy | 100 | 30 | 200 | 8000 | 40 | NA |
2014-11-04 | sell | 100 | 30 | 100 | 5000 | 50 | NA |
2015-12-02 | sell | 100 | 80 | 0 | 0 | 0 | 3000 |
Example 3
We continue with the third superficial loss example (first example in https://www.adjustedcostbase.ca/blog/applying-the-superficial-loss-rule-for-a-partial-disposition-of-shares/). We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
When Shares are Sold at a Loss and then Partially Reacquired within the Superficial Loss Period
data <- data_adjustedcostbase4
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2015-01-02 | buy | 100 | 3.0 | 300 | 0 | 100 | 300 | 3.0 | NA |
2015-04-09 | sell | 100 | 2.0 | 200 | 0 | 0 | 0 | 0.0 | -100 |
2015-04-10 | buy | 25 | 2.2 | 55 | 0 | 25 | 55 | 2.2 | NA |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, spot.rate = "price") %>%
select(date, transaction, quantity, price, total.quantity, ACB, ACB.share, gains)
date | transaction | quantity | price | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2015-01-02 | buy | 100 | 3.0 | 100 | 300 | 3.0 | NA |
2015-04-09 | sell | 100 | 2.0 | 0 | 0 | 0.0 | -75 |
2015-04-10 | buy | 25 | 2.2 | 25 | 80 | 3.2 | NA |
Example 4
We continue with the fourth superficial loss example (second example in https://www.adjustedcostbase.ca/blog/applying-the-superficial-loss-rule-for-a-partial-disposition-of-shares/). We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
When Shares are Purchased and then Partially Sold within the Superficial Loss Period
data <- data_adjustedcostbase5
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2015-04-09 | buy | 100 | 3 | 300 | 0 | 100 | 300 | 3 | NA |
2015-04-10 | sell | 80 | 2 | 160 | 0 | 20 | 60 | 3 | -80 |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, spot.rate = "price") %>%
select(date, transaction, quantity, price, total.quantity, ACB, ACB.share, gains)
date | transaction | quantity | price | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2015-04-09 | buy | 100 | 3 | 100 | 300 | 3 | NA |
2015-04-10 | sell | 80 | 2 | 20 | 80 | 4 | NA |
Example 5
When Multiple Acquisitions and/or Multiple Dispositions Occur Within the Superficial Loss Period
There are no examples given for this one, so we make our own. adjustedcostbase.ca writes that the web-based application does not support claiming partial losses automatically:
Note that AdjustedCostBase.ca does not automatically apply the superficial loss rule for you. Although you’ll see superficial loss rule warnings being displayed in many cases, it’s up to you to edit the transaction to apply the superficial loss rule. Also, in cases where you’re partially claiming a loss due to the superficial loss rule, you’ll need to manually calculate the partial capital loss using the methods described above.
Fortunately, cryptoTax
allows claiming partial losses
automatically. We first demonstrate the “Violation of the Superficial
Loss Rule” by using regular ACB without accounting for
superficial losses:
data <- data_adjustedcostbase6
ACB(data, spot.rate = "price", sup.loss = FALSE)
date | transaction | quantity | price | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
2015-04-09 | buy | 150 | 3 | 450 | 0 | 150 | 450 | 3 | NA |
2015-04-10 | sell | 20 | 2 | 40 | 0 | 130 | 390 | 3 | -20 |
2015-04-15 | buy | 50 | 3 | 150 | 0 | 180 | 540 | 3 | NA |
2015-04-20 | sell | 10 | 2 | 20 | 0 | 170 | 510 | 3 | -10 |
2015-05-15 | sell | 80 | 2 | 160 | 0 | 90 | 270 | 3 | -80 |
Next, we do it the correct way, accounting for superficial losses, and include a few more columns for the demonstration:
ACB(data, spot.rate = "price") %>%
select(
date, transaction, quantity, price, total.quantity,
suploss.range, sup.loss, sup.loss.quantity, ACB, ACB.share,
gains.uncorrected, gains.sup, gains.excess, gains
)
date | transaction | quantity | price | total.quantity | suploss.range | sup.loss | sup.loss.quantity | ACB | ACB.share | gains.uncorrected | gains.sup | gains.excess | gains |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2015-04-09 | buy | 150 | 3 | 150 | 2015-03-10 UTC–2015-05-09 UTC | FALSE | 0 | 450.0000 | 3.000000 | 0.00000 | NA | NA | NA |
2015-04-10 | sell | 20 | 2 | 130 | 2015-03-11 UTC–2015-05-10 UTC | TRUE | 20 | 410.0000 | 3.153846 | -20.00000 | -20.00000 | NA | NA |
2015-04-15 | buy | 50 | 3 | 180 | 2015-03-16 UTC–2015-05-15 UTC | FALSE | 0 | 580.0000 | 3.222222 | 0.00000 | NA | NA | NA |
2015-04-20 | sell | 10 | 2 | 170 | 2015-03-21 UTC–2015-05-20 UTC | TRUE | 10 | 560.0000 | 3.294118 | -12.22222 | -12.22222 | NA | NA |
2015-05-15 | sell | 80 | 2 | 90 | 2015-04-15 UTC–2015-06-14 UTC | TRUE | 80 | 361.1765 | 4.013072 | -103.52941 | -64.70588 | -38.82353 | -38.82353 |
Other examples from the internet
CryptoTaxCalculator
Example 1
Here is an example from CryptoTaxCalculator, showcased at: https://cryptotaxcalculator.io/guides/crypto-tax-canada-cra/. We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_cryptotaxcalculator1
ACB(data, transaction = "trade", spot.rate = "price", sup.loss = FALSE)
date | trade | currency | price | quantity | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|---|
2020-01-01 | buy | BTC | 5000 | 2 | 10000 | 0 | 2 | 10000 | 5000 | NA |
2020-02-03 | sell | BTC | 3000 | 2 | 6000 | 0 | 0 | 0 | 0 | -4000 |
2020-02-04 | buy | BTC | 3000 | 2 | 6000 | 0 | 2 | 6000 | 3000 | NA |
2021-02-04 | sell | BTC | 10000 | 2 | 20000 | 0 | 0 | 0 | 0 | 14000 |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, transaction = "trade", spot.rate = "price") %>%
select(date, trade, price, quantity, total.quantity, ACB, ACB.share, gains)
date | trade | price | quantity | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2020-01-01 | buy | 5000 | 2 | 2 | 10000 | 5000 | NA |
2020-02-03 | sell | 3000 | 2 | 0 | 0 | 0 | NA |
2020-02-04 | buy | 3000 | 2 | 2 | 10000 | 5000 | NA |
2021-02-04 | sell | 10000 | 2 | 0 | 0 | 0 | 10000 |
Example 2
We continue with the second superficial loss example. We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_cryptotaxcalculator2
ACB(data, transaction = "trade", spot.rate = "price", sup.loss = FALSE)
date | trade | currency | price | quantity | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|---|
2020-01-01 | buy | BTC | 5000 | 2 | 10000 | 0 | 2 | 10000 | 5000 | NA |
2020-02-05 | buy | BTC | 1000 | 2 | 2000 | 0 | 4 | 12000 | 3000 | NA |
2020-02-06 | sell | BTC | 1000 | 2 | 2000 | 0 | 2 | 6000 | 3000 | -4000 |
2021-02-06 | sell | BTC | 10000 | 2 | 20000 | 0 | 0 | 0 | 0 | 14000 |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, transaction = "trade", spot.rate = "price") %>%
select(date, trade, price, quantity, total.quantity, ACB, ACB.share, gains)
date | trade | price | quantity | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2020-01-01 | buy | 5000 | 2 | 2 | 10000 | 5000 | NA |
2020-02-05 | buy | 1000 | 2 | 4 | 12000 | 3000 | NA |
2020-02-06 | sell | 1000 | 2 | 2 | 10000 | 5000 | NA |
2021-02-06 | sell | 10000 | 2 | 0 | 0 | 0 | 10000 |
Coinpanda
Example 1
Here is an example from Coinpanda, showcased at: https://coinpanda.io/blog/crypto-taxes-canada-adjusted-cost-base/.
The first example does not require the superficial loss rule so we can
set it to FALSE
without worry.
data <- data_coinpanda1
ACB(data,
transaction = "type", quantity = "amount",
total.price = "price", sup.loss = FALSE
)
type | date | currency | amount | price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
buy | 2019-08-14 | BTC | 0.2 | 1800 | 20 | 0.2 | 1820 | 9100.000 | NA |
buy | 2019-10-29 | BTC | 0.6 | 4300 | 20 | 0.8 | 6140 | 7675.000 | NA |
sell | 2020-06-05 | BTC | 0.8 | 5700 | 0 | 0.0 | 0 | 0.000 | -440 |
buy | 2020-09-23 | BTC | 1.2 | 8200 | 0 | 1.2 | 8200 | 6833.333 | NA |
Example 2
We continue with the second superficial loss example. We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_coinpanda2
ACB(data,
transaction = "type", quantity = "amount",
total.price = "price", sup.loss = FALSE
)
type | date | currency | amount | price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|
buy | 2019-08-14 | BTC | 0.2 | 1800 | 20 | 0.2 | 1820 | 9100.000 | NA |
buy | 2019-10-29 | BTC | 0.6 | 4300 | 20 | 0.8 | 6140 | 7675.000 | NA |
sell | 2020-06-05 | BTC | 0.8 | 5700 | 0 | 0.0 | 0 | 0.000 | -440 |
buy | 2020-06-07 | BTC | 1.2 | 7000 | 0 | 1.2 | 7000 | 5833.333 | NA |
Next, we do it the correct way, accounting for superficial losses:
ACB(data, transaction = "type", quantity = "amount", total.price = "price") %>%
select(type, date, amount, price, fees, ACB, ACB.share, gains)
type | date | amount | price | fees | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
buy | 2019-08-14 | 0.2 | 1800 | 20 | 1820 | 9100 | NA |
buy | 2019-10-29 | 0.6 | 4300 | 20 | 6140 | 7675 | NA |
sell | 2020-06-05 | 0.8 | 5700 | 0 | 0 | 0 | NA |
buy | 2020-06-07 | 1.2 | 7000 | 0 | 7440 | 6200 | NA |
Koinly
Here is an example from Koinly, showcased at: https://koinly.io/blog/calculating-crypto-taxes-canada/. We first demonstrate the “Violation of the Superficial Loss Rule” by using regular ACB without accounting for superficial losses:
data <- data_koinly
ACB(data, sup.loss = FALSE)
date | transaction | currency | quantity | spot.rate | total.price | fees | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|---|---|---|
2019-01-06 | buy | ETH | 100 | 50 | 5000 | 0 | 100 | 5000 | 50 | NA |
2019-11-03 | sell | ETH | 100 | 30 | 3000 | 0 | 0 | 0 | 0 | -2000 |
2019-11-04 | buy | ETH | 100 | 30 | 3000 | 0 | 100 | 3000 | 30 | NA |
Next, we do it the correct way, accounting for superficial losses:
date | transaction | quantity | spot.rate | total.quantity | ACB | ACB.share | gains |
---|---|---|---|---|---|---|---|
2019-01-06 | buy | 100 | 50 | 100 | 5000 | 50 | NA |
2019-11-03 | sell | 100 | 30 | 0 | 0 | 0 | NA |
2019-11-04 | buy | 100 | 30 | 100 | 5000 | 50 | NA |