Crypto Tax Loss Harvesting Calculator
Sell losing positions to harvest losses, offset gains, and reduce your tax bill. Estimate savings in seconds.
Your Positions
| Asset | Units | Cost basis | Price now | Unrealized P/L |
|---|---|---|---|---|
| BTC Bitcoin | โ | |||
| ETH Ethereum | โ | |||
| SOL Solana | โ | |||
| DOGE Dogecoin | โ | |||
| XRP XRP | โ |
Tax Settings
Marginal rate for ordinary income / short-term gains.
Typically 0%, 15%, or 20%.
If you must buy back in, reduce harvested loss by this percent.
Total portfolio value
โ
Harvestable losses
โ
Estimated tax savings
โ
Net portfolio after harvest
โ
Harvest strategy
Enter your positions to see a personalized strategy.
How this works
- Unrealized loss: (cost basis โ current price) ร units. Only negative values can be harvested.
- Harvested loss: sum of unrealized losses, optionally reduced by the wash-sale buffer.
- Tax savings: losses first offset taxable capital gains, then up to $3,000 of ordinary income, at your entered rates.
- Net portfolio: current portfolio value minus the estimated tax savings you realize this year.
Important notes
- โข IRS rules let you deduct up to $3,000 of net capital losses against ordinary income annually.
- โข Excess losses carry forward indefinitely to future tax years.
- โข If you rebuy the same or substantially identical crypto within 30 days before or after the sale, the loss may be deferred under wash-sale rules (currently proposed for crypto; track manually).
- โข This is an estimate, not tax advice. Consult a CPA for your situation.
๐ค Use this tool in your agent
โ Agent-ready codeCopy the snippet below into your agent, newsletter, or script. The tool page at hermesdispatch.dev/tools/crypto-tax-loss-harvester/ is the canonical contract: inputs, outputs, and formulas.
# Hermes Dispatch Tool โ Crypto Tax Loss Harvester
# Source: https://hermesdispatch.dev/tools/crypto-tax-loss-harvester/
# Description: Estimate tax savings from harvesting unrealized crypto losses.
# License: MIT (generated by hermesdispatch.dev)
#
# INSTALL:
# 1. Save this file as ~/.hermes/hermes-agent/tools/crypto_tax_loss_harvester.py
# 2. Restart Hermes or run /reset in a session
# 3. The tool auto-registers if Hermes uses auto-discovery of tools/*.py
#
# MANUAL REGISTRY (if auto-discovery is off):
# from tools.crypto_tax_loss_harvester import register
# register()
import json
DATA = {"defaults": {"annual_income": 85000, "tax_filing": "single", "short_term_rate": 0.22, "long_term_rate": 0.15, "wash_sale_buffer_pct": 0}, "filing_statuses": {"single": {"name": "Single", "long_term_0_limit": 47125, "long_term_15_limit": 518900}, "married_joint": {"name": "Married filing jointly", "long_term_0_limit": 94250, "long_term_15_limit": 583750}, "married_separate": {"name": "Married filing separately", "long_term_0_limit": 47125, "long_term_15_limit": 291850}, "head_household": {"name": "Head of household", "long_term_0_limit": 63100, "long_term_15_limit": 551350}}, "coins": [{"symbol": "BTC", "name": "Bitcoin", "units": 0.5, "cost_basis": 48000, "current_price": 42000}, {"symbol": "ETH", "name": "Ethereum", "units": 4, "cost_basis": 3200, "current_price": 2450}, {"symbol": "SOL", "name": "Solana", "units": 25, "cost_basis": 145, "current_price": 88}, {"symbol": "DOGE", "name": "Dogecoin", "units": 10000, "cost_basis": 0.18, "current_price": 0.09}, {"symbol": "XRP", "name": "XRP", "units": 2000, "cost_basis": 1.1, "current_price": 0.55}], "notes": {"deduction_limit": 3000, "carryforward": true, "wash_sale_warning": "If you rebuy the same or substantially identical crypto within 30 days before or after the sale, the loss may be deferred under wash-sale rules (currently proposed for crypto; track manually).", "tax_rate_note": "Short-term capital gains are taxed as ordinary income. Long-term rates are 0%, 15%, or 20% depending on income. Enter your effective marginal rate for the most accurate estimate."}}
def _ok(result):
return json.dumps({"success": True, "data": result}, indent=2)
def _err(message):
return json.dumps({"success": False, "error": message}, indent=2)
TOOL_NAME = "crypto_tax_loss_harvester"
TOOLSET = "crypto"
SCHEMA = {
"type": "function",
"function": {
"name": "crypto_tax_loss_harvester",
"description": "Estimate tax savings from harvesting unrealized crypto losses.",
"parameters": {
"type": "object",
"properties": {
"annual_income": {
"type": "number",
"description": "Annual taxable income in USD."
},
"tax_filing": {
"type": "string",
"description": "Filing slug: single, married_joint, married_separate, head_household"
}
},
"required": []
}
}
}
def _run(args):
annual_income = float(args.get("annual_income", DATA["defaults"]["annual_income"]))
filing = args.get("tax_filing", DATA["defaults"]["tax_filing"])
filing_info = DATA["filing_statuses"].get(filing, DATA["filing_statuses"]["single"])
total_loss = 0
harvestable_coins = []
for coin in DATA["coins"]:
cost = coin["cost_basis"] * coin["units"]
value = coin["current_price"] * coin["units"]
loss = cost - value
if loss > 0:
total_loss += loss
harvestable_coins.append({
"symbol": coin["symbol"],
"units": coin["units"],
"unrealized_loss": round(loss, 2)
})
rate = 0.15
if annual_income <= filing_info["long_term_0_limit"]:
rate = 0
elif annual_income <= filing_info["long_term_15_limit"]:
rate = 0.15
else:
rate = 0.20
deduction_limit = DATA["notes"]["deduction_limit"]
deductible = min(deduction_limit, total_loss)
tax_savings = deductible * rate
return _ok({
"total_unrealized_loss": round(total_loss, 2),
"harvestable_coins": harvestable_coins,
"deductible_this_year": round(deductible, 2),
"carryforward_loss": round(max(0, total_loss - deductible), 2),
"estimated_tax_savings": round(tax_savings, 2),
"estimated_long_term_rate": rate,
"filing_status": filing_info["name"]
})
def HANDLER(args):
try:
return _run(args)
except Exception as e:
return _err(str(e))
def register():
"""Manual registry hook. Import and call this to register with Hermes."""
try:
from tools.registry import registry
registry.register(
name=TOOL_NAME,
toolset=TOOLSET,
schema=SCHEMA,
handler=HANDLER,
)
except ImportError:
print("Hermes registry not found; skipping manual registration.")
if __name__ == "__main__":
# CLI smoke test
print(HANDLER({}))
Want early access to the next locked tool? Subscribe to The Hermes Dispatch.