关于 cost-basis-engine
cost-basis-engine 是用于加密货币交易的成本基础计算技能,可供整理税务记录的交易者比较不同会计方法下的已实现收益和估算税额。它涵盖部分卖出及空投、质押奖励、LP 和多跳兑换等链上事件;结果仅供参考,不构成税务建议。
主要功能
- 01比较 FIFO、LIFO、HIFO 等五种方法
- 02计算部分卖出的已实现收益
- 03处理空投、质押奖励和代币迁移
- 04将 LP 进出仓建模为代币兑换
- 05拆分多跳兑换的应税事件
适用场景
- 01按多种方法核算年度交易记录
- 02跟踪定投过程中的部分卖出与剩余成本
- 03记录 LP 进出仓产生的收益或损失
- 04核算空投及质押收入和后续成本
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agiprolabs/ claude-trading-skills --skill cost-basis-engine安装后在 Claude Code 中输入/cost-basis-engine确认已加载。
附带文件references/planned_features.mdscripts/cost_basis_calculator.py
详细介绍
成本基础引擎
使用多种会计方法计算加密货币交易的成本基础,并比较不同方法得出的纳税义务。本技能可处理链上活动的全部复杂情况:部分卖出、代币迁移、空投、质押奖励、LP 进入/退出以及多跳兑换。
免责声明:本技能提供的计算工具仅用于提供信息,不构成税务、法律或财务建议。请咨询合格的税务专业人士,了解您的具体情况。税法因司法管辖区而异,且经常变化。
前提条件
- Python 3.10+
- 不需要外部依赖(仅使用标准库)
- 交易历史记录为 dict 列表或 CSV,包含以下列:
date、action、token、quantity、price_usd、fee_usd
方法概览
| 方法 | 逻辑 | 最适用场景 |
|---|---|---|
| FIFO | 先买入的批次先卖出 | 简单易用,许多司法管辖区默认采用 |
| LIFO | 后买入的批次先卖出 | 价格随时间上涨时递延收益 |
| HIFO | 成本最高的批次先卖出 | 最大限度降低当前纳税义务 |
| Specific ID | 交易者选择要卖出的批次 | 控制度最高,但需要保留记录 |
| Average Cost | 对持有的所有批次计算加权平均值 | 简单易用,部分司法管辖区要求采用 |
1. FIFO(先进先出)
优先卖出最早的批次。如果未选择其他方法,这是美国的默认方法。
def fifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
"""Sell using FIFO. lots sorted oldest-first."""
remaining = sell_qty
realized = []
while remaining > 0 and lots:
lot = lots[0]
used = min(lot["qty"], remaining)
gain = (sell_price - lot["cost_per_unit"]) * used
realized.append({"qty": used, "basis": lot["cost_per_unit"], "gain": gain})
lot["qty"] -= used
remaining -= used
if lot["qty"] <= 0:
lots.pop(0)
return realized
部分卖出示例
您持有三个 TOKEN 批次:
- 批次 A:100 单位 @ $1.00(最早买入)
- 批次 B:50 单位 @ $2.00
- 批次 C:75 单位 @ $1.50
您以 $3.00 的价格卖出 120 单位:
- 从批次 A 卖出 100 单位:收益 = (3.00 - 1.00) * 100 = $200
- 从批次 B 卖出 20 单位:收益 = (3.00 - 2.00) * 20 = $20
- 已实现收益合计:$220
- 批次 B 剩余:30 单位 @ $2.00
2. LIFO(后进先出)
优先卖出最新的批次。与 FIFO 的顺序相反。
def lifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
"""Sell using LIFO. Pops from end (newest first)."""
remaining = sell_qty
realized = []
while remaining > 0 and lots:
lot = lots[-1]
used = min(lot["qty"], remaining)
gain = (sell_price - lot["cost_per_unit"]) * used
realized.append({"qty": used, "basis": lot["cost_per_unit"], "gain": gain})
lot["qty"] -= used
remaining -= used
if lot["qty"] <= 0:
lots.pop()
return realized
使用相同的批次,以 $3.00 的价格卖出 120 单位,采用 LIFO:
- 从批次 C 卖出 75 单位:收益 = (3.00 - 1.50) * 75 = $112.50
- 从批次 B 卖出 45 单位:收益 = (3.00 - 2.00) * 45 = $45
- 已实现收益合计:$157.50
3. HIFO(成本最高者先出)
优先卖出成本最高的批次,以最大限度减少已实现收益。
def hifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
"""Sell using HIFO. Sort by cost descending, consume highest first."""
lots.sort(key=lambda x: x["cost_per_unit"], reverse=True)
remaining = sell_qty
realized = []
for lot in lots:
if remaining <= 0:
break
used = min(lot["qty"], remaining)
gain = (sell_price - lot["cost_per_unit"]) * used
realized.append({"qty": used, "basis": lot["cost_per_unit"], "gain": gain})
lot["qty"] -= used
remaining -= used
lots[:] = [l for l in lots if l["qty"] > 0]
return realized
使用相同的批次,以 $3.00 的价格卖出 120 单位,采用 HIFO:
- 从批次 B 卖出 50 单位($2.00,成本最高):收益 = (3.00 - 2.00) * 50 = $50
- 从批次 C 卖出 70 单位($1.50,次高):收益 = (3.00 - 1.50) * 70 = $105
- 已实现收益合计:$155
- 剩余:批次 A 100 @ $1.00,批次 C 5 @ $1.50
4. 特定识别法
交易者明确选择要卖出的批次。该方法提供最大的控制权,但需要细致地保留记录。每个批次都必须有唯一标识(例如按买入日期和时间,或使用批次 ID)。
def specific_id_sell(lots: dict[str, dict], lot_ids: list[tuple[str, float]],
sell_price: float) -> list[dict]:
"""Sell specific lots by ID. lot_ids = [(lot_id, qty_to_sell), ...]"""
realized = []
for lot_id, sell_qty in lot_ids:
lot = lots[lot_id]
used = min(lot["qty"], sell_qty)
gain = (sell_price - lot["cost_per_unit"]) * used
realized.append({"lot_id": lot_id, "qty": used, "basis": lot["cost_per_unit"], "gain": gain})
lot["qty"] -= used
if lot["qty"] <= 0:
del lots[lot_id]
return realized
5. 比例 / 平均成本法
计算持有的所有批次中每单位的单一加权平均成本。每次卖出都使用该平均成本。每次买入后都会更新平均值。
def average_cost_basis(lots: list[dict]) -> float:
"""Compute weighted average cost per unit across all lots."""
total_cost = sum(l["qty"] * l["cost_per_unit"] for l in lots)
total_qty = sum(l["qty"] for l in lots)
if total_qty == 0:
return 0.0
return total_cost / total_qty
def average_cost_sell(lots: list[dict], sell_qty: float, sell_price: float) -> dict:
"""Sell using average cost. Reduces all lots proportionally."""
avg = average_cost_basis(lots)
total_qty = sum(l["qty"] for l in lots)
sell_qty = min(sell_qty, total_qty)
gain = (sell_price - avg) * sell_qty
# Reduce each lot proportionally
ratio = sell_qty / total_qty
for lot in lots:
lot["qty"] *= (1 - ratio)
lots[:] = [l for l in lots if l["qty"] > 1e-12]
return {"qty": sell_qty, "avg_basis": avg, "gain": gain}
使用平均成本部分卖出
批次:100 @ $1.00、50 @ $2.00、75 @ $1.50。总计:225 单位,总成本 $312.50。
平均成本 = $312.50 / 225 = $1.3889/单位
以 $3.00 的价格卖出 120 单位:收益 = (3.00 - 1.3889) * 120 = $193.33
卖出后,剩余 105 单位,平均成本仍为 $1.3889。
6. 特殊事件
空投
空投按收到当日的公平市场价值(FMV)作为收入处理。该 FMV 将作为未来卖出的成本基础。
airdrop_lot = {
"date": "2025-03-15",
"qty": 1000,
"cost_per_unit": 0.05, # FMV at time of receipt
"income_recognized": 50.0, # 1000 * 0.05 reported as income
"source": "airdrop"
}
质押奖励
质押奖励在收到时按 FMV 作为收入处理(与空投类似)。每次奖励事件都会产生一个新批次。
staking_lot = {
"date": "2025-04-01",
"qty": 5.2,
"cost_per_unit": 150.0, # SOL price at receipt
"income_recognized": 780.0,
"source": "staking_reward"
}
代币拆分和迁移
代币拆分或迁移(旧代币兑换新代币,比例为 1:1 或 N:M)通常不属于应税事件。总成本基础会转移至新代币。
def apply_split(lots: list[dict], split_ratio: float) -> None:
"""Apply a token split. split_ratio > 1 means more tokens."""
for lot in lots:
lot["qty"] *= split_ratio
lot["cost_per_unit"] /= split_ratio
对于 100 个代币 @ $5.00 的 1:10 拆分:结果为 1000 个代币 @ $0.50。总成本基础仍为 $500。
7. 将 LP 的进入/退出视为代币兑换
进入 LP 头寸时,视为卖出存入的代币并收到 LP 代币。退出则相反。
进入 LP(向 SOL/USDC 池存入 10 SOL + 1500 USDC):
- 按当前 FMV 处置 10 SOL → 产生资本利得/损失事件
- 按当前 FMV 处置 1500 USDC → 通常利得/损失可忽略不计
- 收到 LP 代币,成本基准 = 存入资产的 FMV
退出 LP(兑换 LP 代币,收到 12 SOL + 1400 USDC):
- 按收到资产的 FMV 处置 LP 代币 → 产生资本利得/损失
- 收到 12 SOL,成本基准 = 赎回时的 FMV
- 收到 1400 USDC,成本基准 = 赎回时的 FMV
def lp_entry(sol_qty: float, sol_price: float, usdc_qty: float,
lp_tokens_received: float) -> dict:
"""Model LP entry as disposal of component tokens."""
total_value = sol_qty * sol_price + usdc_qty * 1.0
lp_cost_basis = total_value / lp_tokens_received
return {
"disposals": [
{"token": "SOL", "qty": sol_qty, "price": sol_price},
{"token": "USDC", "qty": usdc_qty, "price": 1.0},
],
"lp_lot": {"qty": lp_tokens_received, "cost_per_unit": lp_cost_basis}
}
8. 多跳兑换
多跳兑换(例如 SOL -> USDC -> TOKEN)会产生多个应税事件,每个中间步骤各产生一个。Jupiter 经常会通过中间代币进行路由。
def multi_hop_events(hops: list[dict]) -> list[dict]:
"""
Each hop is: {"sell_token", "sell_qty", "sell_price",
"buy_token", "buy_qty", "buy_price"}
Each hop is a separate taxable event.
"""
events = []
for i, hop in enumerate(hops):
events.append({
"event": i + 1,
"dispose": hop["sell_token"],
"dispose_qty": hop["sell_qty"],
"dispose_value": hop["sell_qty"] * hop["sell_price"],
"acquire": hop["buy_token"],
"acquire_qty": hop["buy_qty"],
"acquire_basis": hop["buy_qty"] * hop["buy_price"],
})
return events
示例:将 1 SOL($150)兑换为 150 USDC,再兑换为 10,000 TOKEN(每个 $0.015)
- 事件 1:处置 1 SOL(成本基准与 $150 收益对比)→ SOL 产生利得/损失
- 事件 2:处置 150 USDC(成本基准与 $150 收益对比)→ 通常利得约为 $0
- 结果:获得 10,000 TOKEN,成本基准 = $0.015/单位
9. 对比视图
这项技能的核心价值:用全部五种方法处理相同的交易历史,并比较已实现利得总额和预估应纳税额。
methods = ["FIFO", "LIFO", "HIFO", "Specific ID", "Average Cost"]
# After processing all trades through each method:
comparison = {
"FIFO": {"total_gain": 220.00, "tax_at_30pct": 66.00},
"LIFO": {"total_gain": 157.50, "tax_at_30pct": 47.25},
"HIFO": {"total_gain": 155.00, "tax_at_30pct": 46.50},
"Specific ID": {"total_gain": 160.00, "tax_at_30pct": 48.00},
"Average Cost":{"total_gain": 193.33, "tax_at_30pct": 58.00},
}
# HIFO minimizes liability in this example
参见 scripts/cost_basis_calculator.py,其中提供了一个可完整运行的对比示例,使用了包含部分卖出的真实交易数据。
快速入门
from scripts.cost_basis_calculator import CostBasisEngine
engine = CostBasisEngine()
# Add purchases
engine.add_buy("2025-01-10", "TOKEN", 100, 1.00)
engine.add_buy("2025-02-15", "TOKEN", 50, 2.00)
engine.add_buy("2025-03-01", "TOKEN", 75, 1.50)
# Sell and compare methods
results = engine.sell_compare("2025-04-01", "TOKEN", 120, 3.00)
engine.print_comparison(results)
使用场景
- 税季准备:在选择申报方法前,使用所有方法处理全年交易记录。
- 累积策略:在 DCA 累积期间跟踪部分卖出,了解每种方法如何影响剩余成本基准。
- LP 头寸跟踪:将 LP 进入/退出建模为兑换,并记录相关的利得/损失事件。
- 空投和质押收入:正确记录收入事件,并为未来处置设定成本基准。
- 多跳兑换拆解:将 Jupiter 路由拆解为单独的应税事件。
文件
| 文件 | 描述 |
|---|---|
references/planned_features.md | 方法公式、部分卖出的示例、特殊事件处理、多跳兑换处理 |
scripts/cost_basis_calculator.py | 包含全部 5 种方法的完整引擎、对比表,以及使用真实交易的演示模式 |
请记住:“最佳”方法取决于您所在的司法管辖区、具体交易历史和税务状况。此引擎可帮助您进行比较,税务专业人士则可帮助您做出决定。