Generate a Full Tax Report

It is possible to generate a full tax report with cryptoTax. This vignette shows how.

Preparing your list of coins

First, you want to fetch the price information for all your coins.

Note: Some exchanges don’t require fetching this information from coinmarketcap because they already give the CAD value of your trades or revenues. However, this is still necessary to get the current value, and therefore your unrealized gains and losses.

library(cryptoTax)

my.coins <- c("BTC", "ETH", "ADA", "CRO", "LTC", "USDC", "BUSD", "CEL", "PRE", "ETHW", "BAT")
list.prices <- prepare_list_prices(coins = my.coins, start.date = "2021-01-01")

Note: When you have a lot of coins, it can be better to split the calls to coinmarketcap in two or more and row bind the results with rbind() because otherwise we risk getting an error from the coinmarketcap API. See below for an example:

library(cryptoTax)

my.coins1 <- c("BTC", "ETH", "ADA", "CRO", "LTC", "USDC")
my.coins2 <- c("BUSD", "CEL", "PRE", "ETHW", "BAT")

list.prices1 <- prepare_list_prices(coins = my.coins1, start.date = "2021-01-01")
#> ❯ Scraping historical crypto data
#> 
#> ❯ Processing historical crypto data
#> 
list.prices2 <- prepare_list_prices(coins = my.coins2, start.date = "2021-01-01")
#> ❯ Scraping historical crypto data
#> 
#> ❯ Processing historical crypto data
#> 

list.prices <- rbind(list.prices1, list.prices2)

Formatting your data

Below we use a shortcut for this vignette to format all exchanges quickly with lapply() and the format_detect() function. However, you can use the dedicated functions should you wish so.

exchanges <- list(
  data_adalite, data_binance, data_binance_withdrawals, data_blockfi, data_CDC, 
  data_CDC_exchange_rewards, data_CDC_exchange_trades, data_CDC_wallet, data_celsius,
  data_coinsmart, data_exodus, data_gemini, data_newton, data_pooltool, data_presearch,
  data_shakepay, data_uphold)

formatted.data <- format_detect(exchanges)

Adjusted Cost Base

Next, we can begin processing that data. We start by formatting the Adjusted Cost Base (ACB) of each transaction. The formatted.ACB is going to be our core object with which we will be working for all future steps.

formatted.ACB <- format_ACB(formatted.data)
#> Process started at 2023-02-17 20:49:01. Please be patient as the transactions process.
#> [Formatting ACB (progress bar repeats for each coin)...]
#> Warning in format_ACB(formatted.data): WARNING: Some balances have negative values. Double-check for missing transactions.
#> Note: Adjusted cost base (ACB) and capital gains have been adjusted for the superficial loss rule. To avoid this, use argument `sup.loss = FALSE`.
#> Process ended at 2023-02-17 20:49:08. Total time elapsed: 0.13 minutes

Per default, format_ACB() considers taxable revenue (and not aquisition at $0 ACB) the following transaction types: staking, interests, and mining. If you want a different treatment for those transactions (or other types of revenues like cashback and airdrops), use the as.revenue argument of format_ACB().

We get a warning that there are negative values in some places, therefore that we might have forgotten some transactions. The check_missing_transactions() function makes it easy to identify which transactions (and therefore which coin) are concerned with this.

check_missing_transactions(formatted.ACB)
#> # A tibble: 3 × 26
#> # Groups:   currency [11]
#>   date                currency quantity total.pr…¹ spot.…² trans…³  fees descr…⁴
#>   <dttm>              <chr>       <dbl>      <dbl>   <dbl> <chr>   <dbl> <chr>  
#> 1 2021-03-07 21:46:57 BAT         52.6        57.0    1.08 sell        0 trade  
#> 2 2021-04-05 12:22:00 BAT          8.52        0      1.55 revenue     0 in     
#> 3 2021-04-06 04:47:00 BAT          8.52       10.4    1.22 sell        0 trade  
#> # … with 18 more variables: comment <chr>, revenue.type <chr>, value <dbl>,
#> #   exchange <chr>, rate.source <chr>, currency2 <chr>, total.quantity <dbl>,
#> #   suploss.range <Interval>, quantity.60days <dbl>, share.left60 <dbl>,
#> #   sup.loss.quantity <dbl>, sup.loss <lgl>, gains.uncorrected <dbl>,
#> #   gains.sup <dbl>, gains.excess <lgl>, gains <dbl>, ACB <dbl>,
#> #   ACB.share <dbl>, and abbreviated variable names ¹​total.price, ²​spot.rate,
#> #   ³​transaction, ⁴​description

Next, we might want to make sure that we have downloaded the latest files for each exchange. If you shake your phone every day for sats, or you receive daily weekly payments from staking, you would expect the latest date to be recent. For this we use the get_latest_transactions() function.

get_latest_transactions(formatted.ACB)
#> # A tibble: 14 × 2
#> # Groups:   exchange [14]
#>    exchange     date               
#>    <chr>        <dttm>             
#>  1 CDC          2021-07-28 23:23:04
#>  2 CDC.exchange 2021-12-24 15:34:45
#>  3 CDC.wallet   2021-06-26 14:51:02
#>  4 adalite      2021-05-17 21:31:00
#>  5 binance      2022-11-27 08:05:35
#>  6 blockfi      2021-10-24 04:29:23
#>  7 celsius      2021-05-23 05:00:00
#>  8 coinsmart    2021-06-03 02:04:49
#>  9 exodus       2021-06-12 22:31:35
#> 10 gemini       2021-06-18 01:38:54
#> 11 newton       2021-06-16 18:49:11
#> 12 presearch    2021-05-07 05:55:33
#> 13 shakepay     2021-07-10 00:52:19
#> 14 uphold       2021-06-09 04:52:23

At this stage, it is possible to list transactions by coin, if you have few transactions. The output can be very long as soon as you have many transactions however, so we will not be showing it here, but you can have a look at the listby_coin() function and its example.

Full Tax Report

Next, we need to calculate a few extra bits of information for the final report. Fortunately, the prepare_report() function makes this easy for us.

report.info <- prepare_report(formatted.ACB, 
                              tax.year = 2021, 
                              local.timezone = "America/Toronto",
                              list.prices = list.prices)

The report.info object is a list containing all the different info (tables, figures) necessary for the final report. They can be accessed individually too:

names(report.info)
#> [1] "report.overview" "report.summary"  "proceeds"        "sup.losses"     
#> [5] "table.revenues"  "tax.box"         "pie_exchange"    "pie_revenue"

Finally, to generate the report, we use print_report() with the relevant tax year, name of the individual, and the report.info object we just created:

print_report(tax.year = "2021", 
             name = "Mr. Cryptoltruist", 
             report.info)

Full Crypto Tax Report for Tax Year 2021

Name: Mr. Cryptoltruist

Date: Fri Feb 17 20:49:10 2023

Summary

All time up in percentage (including all unrealized gains and revenues received) is -0.27%. In absolute dollars, that is -44.2900000000001 CAD.

Overview

Current Value

Superficial losses

Revenues

Revenue Sources by Exchanges

Revenue Sources by Types

Important Tax Information for Your Accountant



Capital gains

Your capital gains for 2021 are $12,655.68, whereas your capital losses are $0.00 (net = $12,655.68).

Those are only taxed at 50%. Your capital losses are calculated as total capital losses ($0.02) - superficial losses ($0.02) = actual capital losses ($0).

Your total “proceeds” for the coins you sold at a profit is: $19,370.09 (aggregated for all coins). Your total ACB for the coins you sold at a profit is: $6,714.41 (average of all coins). The difference between the two is your capital gains: $12,655.68.

Your total “proceeds” (adjusted for superficial gains) for the coins you sold at a loss is: $0.00 (aggregated for all coins). Your total ACB for the coins you sold at a loss is: $0.00 (average of all coins). The difference between the two is your capital losses: $0.00.

Income

Your total taxable income from crypto (from interest & staking exclusively) for 2021 is $45.23, which is considered 100% taxable income.

Note that per default, this amount excludes revenue from credit card cashback because it is considered rebate, not income, so considered acquired at the fair market value at the time of reception. The income reported above also excludes other forms of airdrops and rewards (e.g., from Shakepay, Brave, Presearch), referrals, and promos, which are considered acquired at a cost of 0$ (and will thus incur a capital gain of 100% upon selling). Note that should you wish to give different tax treatment to the different transaction types, you can do so through the ‘as.revenue’ argument of the ‘ACB’ function. Mining rewards needs to be labelled individually in the files before using format_ACB().

Total tax estimation

In general, you can expect to pay tax on 50% ($6,327.84) of your net capital gains + 100% of your taxable income ($45.23), for a total of $6,373.07. This amount will be taxed based on your tax bracket.

Note that if your capital gains are net negative for the current year, any excess capital losses can be deferred to following years. However, capital losses have to be used in the same year first if you have outstanding capital gains.

Form T1135

If your total acquisition cost has been greater than $100,000 at any point during 2021 (it is $16,637.00 at the time of this report), you will need to fill form T1135 (Foreign Income Verification Statement). Form T1135 is available for download, and more information about it can be found on the CRA website.

Summary table

Here is a summary of what you need to enter on which lines of your income tax:

Other situations

If applicable, you may also need to enter the following:

Interest expense on money borrowed to purchase investments for the purpose of gaining or producing income is tax-deductible. Use line 22100 (was line 221) of the personal income tax return, after completion of Schedule 4 (federal).





……………………………………………………………………………………………………………………………………………………………………………….