Price data for US tax reporting

According to the IRS’s Frequently Asked Questions on Virtual Currency Transactions, reporting cryptocurrency-related income in various scenario requires determining the market price at a given date and time.

For example (emphasis mine):

Q26. I received cryptocurrency in a peer-to-peer transaction […]. How do I determine the cryptocurrency’s fair market value at the time of receipt?

A26. If you receive cryptocurrency in a peer-to-peer transaction […], the fair market value of the cryptocurrency is determined as of the date and time the transaction is recorded on the distributed ledger, or would have been recorded on the ledger if it had been an on-chain transaction. The IRS will accept as evidence of fair market value the value as determined by a cryptocurrency or blockchain explorer that analyzes worldwide indices of a cryptocurrency and calculates the value of the cryptocurrency at an exact date and time. If you do not use an explorer value, you must establish that the value you used is an accurate representation of the cryptocurrency’s fair market value.

There is similar language for other scenarios.

Are there any publicly-available data sources for minute-by-minute historical Zcash pricing data? Which can be looked up programmatically, by precise time or by transaction ID?

It used to be common practice to use something like CoinMarketCap’s historical Zcash data for the day when the transaction occured, by averaging the day’s opening and closing prices. But this doesn’t seem to match the new “exact date and time” guidance.

Update: provides the requisite API access (see below).

Are there any publicly-available data sources for minute-by-minute historical Zcash pricing data?

We are ingesting price data for 10 exchanges across ZEC/USD and ZEC/BTC pairs in the Exchanges section of Zcash Service Status Dashboard.

Which can be looked up programmatically, by precise time or by transaction ID?

In the current tool, it is only possible via exporting the DB. Buiding an API service on top will not be that great a problem.

But this doesn’t seem to match the new “exact date and time” guidance.

Agreed. I was going through these laws myself to understand compliance in USA and was in the same dilemma.

@tromer Do you think this is a problem being faced by many?
If so, we can add these functionalities to support this particular use-case.

It would also make sense to refactor Zcash service status dashboard fat stack codebase into small lego blocks so that the service that connects to all these exchanges can be isolated in a different repo for the community to add features to it for their specific use-cases.


I believe provides very detailed and accurate historical data for paying customers.

1 Like

Oh yeah, this is what makes it so tedious
A way to paste a swath of timestamps and get the corresponding prices would great
A way to paste the values too and get the FMVs would basially cut out ALL the work
(Not gonna lie though, doing it this way for a few years now has improved my numpad skills significantly!)

@prastut, yes, any US taxpayer who sells any amount of ZEC (and in some cases, who receives ZEC) probably needs this information to properly file their tax returns.

Providing this data via your Zcash Service Status Dashboard is a great idea! I see a few caveats, though:

  • What people really need is the aggregate data, i.e., some kind of (volume?) weighted average of reasonably-chosen exchanges. Accompanied by a rationale they can show to the IRS if asked for justification for why they use this data source.
  • How far back does can your data go? Would it help with 2019 returns?
  • Querying an online service for all of one’s transactions creates a privacy issue. People may prefer to download the whole data; or a tool can be built that fetches entry using (say) Tor and at randomized intervals.
  • Many ZEC holders also have taxable events related to other cryptocurrencies, so they’d still need to find a decent data source for those… which, if it exists, may cover ZEC as well anyway.

@anon16456014, yes there are several services that seem to provide such data with paid API access. But all the ones I’ve seen consider historical access of over a year to be a premium feature offered only in their top paid tiers. For example, CoinMarketCap offers it only in their “Enterprise” tier, at some “inquire for pricing” cost that’s higher than their merely $699/month “Professional” tier (which only goes 12 months back, not enough for an annual tax return). There was another such example mentioned in the (now deleted) community chat.

1 Like

Oh look, does provide the requisite API access for free, with minute-level granularity, and going back years:

$ START="`date -d "2017-01-01 23:00:00" "+%s"`000"
$ END="`date -d "2017-01-01 23:01:00" "+%s"`000"
$ curl "$START&end=$END"

Go ShapeShift! :smiley:

Whoever first writes the script that gets a transaction ID and outputs the ZECUSD price at the time of the transaction, please share!


Give or take on the setup, and assuming you have a zcash full node on mainnet:

HEIGHT="$(./zcash-cli getblockcount)" && \
./zcash-cli getblock "$HEIGHT" | jq '.tx[]' && \ 
END="`date -d "@"$(./zcash-cli getblock "$HEIGHT" | jq '.time')"" "+%s"`000" && \
START="$(expr $END - 60000)" && \
curl -s "$START&end=$END" | jq '.data[0].priceUsd'

:money_mouth_face: Would need to still step into tx info to get the above price for the total transaction.

I’ve written a python script that when given a transaction id
fetches the timestamp from the blockchain explorer and uses
that time to ask for price data from CoinCap. It appears to
work as expected … but of course there may be some bugs.
Python3 program to retrieve the unix timestamp
associated with a given zcash transaction ID -
and if timestamp retrieval is sucessful fetch
the zcash price information in USD associated
with that timestamp.

Uses website API interfaces described here:

import requests
import datetime

txid = input('Enter Zcash TxID: ')

time_api_string = ‘
time_api_string = time_api_string + txid

t_response = requests.get(time_api_string)

if t_response.status_code == 200:
tpayload = t_response.json()
timestamp = tpayload.get(‘timestamp’)
utc_time = datetime.datetime.utcfromtimestamp(timestamp).replace(tzinfo=datetime.timezone.utc)
print(‘Blockchain Unix Timestamp:’, timestamp,’ = ',utc_time.strftime("%Y-%m-%d %H:%M:%S %Z"))
timegood = True
print('Time Failure - response status code: ', t_response.status_code)
timegood = False

if timegood:
start_time = timestamp * 1000 # (timestamp in milliseconds)
end_time = start_time + 60000 # (one minute later)
price_api_string = ‘
price_api_string = price_api_string + str(start_time) + ‘&end=’ + str(end_time)

p_response = requests.get(price_api_string)

if p_response.status_code == 200:
    ppayload = p_response.json()
    ppayload_list = ppayload.get('data')
    datet = ppayload_list[0].get('date')
    price = ppayload_list[0].get('priceUsd')
    print('At time', datet, 'Zcash price was', price, 'USD\n')
    print('Price Failure - response status code: ', p_response.status_code)
1 Like

Oops, looks like it stripped away the python formatting.