Tax Loss Harvesting
Tax Loss Harvesting is a strategy portfolio managers and/or end-users utilize to minimize their tax liabilities by offsetting gains with losses in their portfolio. The goal is to lower the overall taxable income and reduce the amount of taxes owed by the ultimate taxpayer.
Taxbit's Inventory APIs enable digital asset platforms to build Tax Loss Harvesting and other Portfolio Optimization experiences within their web/mobile applications. Specifically, the APIs can fetch a user's current inventory lots, where a "lot" includes details about the quantity, purchase cost, and acquisition date. The unrealized gain/loss for each lot can be calculated using this inventory lot data and the current asset spot price. These calculated unrealized gains can then be displayed to the user in a portfolio performance or trading workflow experience, which enables the user to make more optimal trading decisions.
The rest of this guide will walk through the prerequisite data integration and the API call sequences to build a hypothetical experience for a single platform end user.
Prerequisites and Requirements
- Transaction API Integration - Taxbit's Tax Loss Harvesting and portfolio optimization capabilities require an existing integration with our Transactions API. As transactions are sent from the digital asset platform to Taxbit, inventory and lot information are automatically updated.
- Asset Spot Price - The current asset spot price data for each asset must be available and provided by the platform. Each platform has its market pricing that changes in real-time and the end user should see estimated gain/loss calculations based on the pricing that matches what is otherwise visible on the platform.
Integration Steps
The following steps reference
/v1/inventory/summary
while it is recommended to integrate with the newv1/inventory/summaries
Document update coming soon
This guide will walk through the following steps:
- Checking a user's inventory summary - Determination of assets held
- Retrieving the lot-level detail for each asset
- Combining the lot level detail with asset spot price data to calculate unrealized gain/loss estimates
The guide assumes a tenant scoped {{authToken}} and a {{userId}} have already been obtained using Get a Tenant Scoped Bearer Token and Create Taxbit User APIs.
1. Fetch Inventory Summary
Use the Inventory Summary by Asset API to get a list of all active asset balances and the asset identifiers needed in Step 2.
The code below demonstrates the fetching of the inventory summary with the explicit filter out of any inventory lots with missing cost basis.
curl --request GET \
--url 'https://api.multi1.enterprise.taxbit.com/v1/inventory/summary?exclude_missing_cost_basis=true' \
--header 'accept: application/json' \
--header 'authorization: Bearer {{authToken}}' \
--header 'x-user-id: {{userId}}'
The snippet below demonstrates the inventory response showing the balances for two assets: BTC and ETH.
The total_qty.asset.uuid
values for each asset will be needed in Step 2.
[
{
"total_cost": {
"asset": {
"name": "United States Dollar",
"symbol": "$",
"code": "USD",
"type": "Fiat",
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396"
},
"quantity": "30000.00"
},
"updated_datetime": "2023-07-25T17:40:39.281Z",
"total_qty": {
"asset": {
"name": "Bitcoin",
"symbol": "₿",
"code": "BTC",
"type": "Crypto",
"uuid": "9cd9f4d4-078b-4e44-a308-7662fec0f546"
},
"quantity": "2.0"
}
},
{
"total_cost": {
"asset": {
"name": "United States Dollar",
"symbol": "$",
"code": "USD",
"type": "Fiat",
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396"
},
"quantity": "5250.00"
},
"updated_datetime": "2023-07-25T17:40:39.281Z",
"total_qty": {
"asset": {
"name": "Ethereum",
"symbol": "Ξ",
"code": "ETH",
"type": "Crypto",
"uuid": "b7a005b5-f4d5-44ea-ae80-d4f9e8313558"
},
"quantity": "2.5"
}
}
]
2. Fetch lot-level detail for each asset
Use the Get Inventory For a Specific Asset API to fetch the inventory details for ETH:
curl --request GET \
--url 'https://api.multi1.enterprise.taxbit.com/v1/inventory?include_missing_cost_basis=false&asset_id=b7a005b5-f4d5-44ea-ae80-d4f9e8313558' \
--header 'accept: application/json' \
--header 'authorization: Bearer {{authToken}}' \
--header 'x-user-id: {{userId}}'
An array with all the lots of ETH will be returned. There are two lots in the sample below:
[
{
"amount": {
"asset": {
"code": "ETH",
"name": "Ethereum",
"symbol": "Ξ",
"type": "Crypto",
"uuid": "b7a005b5-f4d5-44ea-ae80-d4f9e8313558"
},
"quantity": "0.5"
},
"acquired_date": "2022-02-01T08:08:08.000Z",
"term": "Long",
"unit_cost": {
"asset": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"type": "Fiat",
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396"
},
"quantity": "2500.00"
},
"exchange_name": "AcmeExchange",
"exchange_id": "075a0bec-fbbf-4542-8c31-065497862c23"
},
{
"amount": {
"asset": {
"code": "ETH",
"name": "Ethereum",
"symbol": "Ξ",
"type": "Crypto",
"uuid": "b7a005b5-f4d5-44ea-ae80-d4f9e8313558"
},
"quantity": "2.0"
},
"acquired_date": "2022-02-01T08:08:08.000Z",
"term": "Long",
"unit_cost": {
"asset": {
"code": "USD",
"name": "United States Dollar",
"symbol": "$",
"type": "Fiat",
"uuid": "df939ab7-b7ed-4216-be63-ca1d2a130396"
},
"quantity": "2000.00"
},
"exchange_name": "AcmeExchange",
"exchange_id": "075a0bec-fbbf-4542-8c31-065497862c23"
}
]
Repeat the process for BTC using the corresponding assetId from Step 1.
3. Calculate unrealized gain/loss for each lot
Assume the JSON response objects from Step 2 are stored in javascript variables invEth
and invBtc
. Additionally, assume the current spot price for ETH and BTC are in javascript variables priceEth
and priceBtc
. The code snippet below will print out the gain/loss amounts for each lot in the user’s inventory.
var invEth = []; // From Step 2
var invBtc = []; // From Step 2
var priceEth = 2000.00; // Curent market price
var priceBtc = 30000.00; // Curent market price
invEth.forEach(lot => console.log("Eth Lot gain: " + lot.amount.quantity * (priceEth - lot.unit_cost.quantity)));
invBtc.forEach(lot => console.log("BTC Log gain: " + lot.amount.quantity * (priceBtc - lot.unit_cost.quantity)));
Note: The guide ignores potential floating point precision issues. Digital asset quantities can use up to 18 decimals of precision, so a BigDecimal type library should be used to parse the JSON responses from the APIs in Step 2.
Conclusion
This guide has demonstrated how to materialize the unrealized gain/loss amount for each lot in the user’s inventory. This data can be exposed on a portfolio performance table or embedded in a trade execution workflow to help users optimize their trading decisions.
Updated 4 months ago