jpskill.com
💼 ビジネス コミュニティ

取得原価計算エンジン

cost-basis-engine

特定の株式売却方法(個別法、先入先出法など)や一部売却時の処理に対応し、さまざまな方法で取得費を計算して、税務申告などを支援するSkill。

📜 元の英語説明(参考)

Multi-method cost basis computation including specific identification, FIFO, LIFO, HIFO, and proportional average cost with partial sell handling

🇯🇵 日本人クリエイター向け解説

一言でいうと

特定の株式売却方法(個別法、先入先出法など)や一部売却時の処理に対応し、さまざまな方法で取得費を計算して、税務申告などを支援するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o cost-basis-engine.zip https://jpskill.com/download/10402.zip && unzip -o cost-basis-engine.zip && rm cost-basis-engine.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/10402.zip -OutFile "$d\cost-basis-engine.zip"; Expand-Archive "$d\cost-basis-engine.zip" -DestinationPath $d -Force; ri "$d\cost-basis-engine.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して cost-basis-engine.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → cost-basis-engine フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

Cost Basis Engine

複数の会計方法を使用して暗号通貨取引の原価基準を計算し、方法間で生じる税務上の責任を比較します。このスキルは、部分的な売却、トークンの移行、エアドロップ、ステーキング報酬、LP の参入/退出、マルチホップスワップなど、オンチェーンアクティビティの複雑さ全体を処理します。

免責事項: このスキルは、情報提供のみを目的とした計算ツールを提供します。税務、法務、または財務に関するアドバイスを構成するものではありません。具体的な状況については、資格のある税務専門家にご相談ください。税法は管轄区域によって異なり、頻繁に変更されます。

前提条件

  • Python 3.10+
  • 外部依存関係は不要 (標準ライブラリのみ)
  • 取引履歴は、辞書のリストまたは次の列を持つ CSV として: dateactiontokenquantityprice_usdfee_usd

メソッドの概要

メソッド ロジック 最適な用途
FIFO 最初に購入したロットから最初に売却する 単純さ、多くの管轄区域でのデフォルト
LIFO 最後に購入したロットから最初に売却する 価格が時間とともに上昇する場合に利益を繰り延べる
HIFO 最もコストの高いロットから最初に売却する 現在の税務上の責任を最小限に抑える
Specific ID トレーダーがどのロットを売却するかを選択する 最大限の制御、記録保持が必要
Average Cost 保有するすべてのロットの加重平均 単純さ、一部の管轄区域で必須

1. FIFO (First-In, First-Out)

最も古いロットから最初に売却します。これは、他の方法が選択されていない場合、米国でのデフォルトの方法です。

def fifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
    """FIFO を使用して売却します。lots は最も古いものから順にソートされます。"""
    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 の 3 つのロットを保有しています。

  • ロット A: 100 ユニット @ $1.00 (最古)
  • ロット B: 50 ユニット @ $2.00
  • ロット C: 75 ユニット @ $1.50

120 ユニットを $3.00 で売却します。

  • ロット A から 100: 利益 = (3.00 - 1.00) * 100 = $200
  • ロット B から 20: 利益 = (3.00 - 2.00) * 20 = $20
  • 合計実現利益: $220
  • ロット B の残り: 30 ユニット @ $2.00

2. LIFO (Last-In, First-Out)

最も新しいロットから最初に売却します。FIFO と比較して順序が逆になります。

def lifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
    """LIFO を使用して売却します。末尾からポップします (最も新しいものから)。"""
    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

同じロットを使用して、120 を $3.00 で LIFO で売却します。

  • ロット C から 75: 利益 = (3.00 - 1.50) * 75 = $112.50
  • ロット B から 45: 利益 = (3.00 - 2.00) * 45 = $45
  • 合計実現利益: $157.50

3. HIFO (Highest-In, First-Out)

実現利益を最小限に抑えるために、最もコストの高いロットから最初に売却します。

def hifo_sell(lots: list[dict], sell_qty: float, sell_price: float) -> list[dict]:
    """HIFO を使用して売却します。コストの高い順にソートし、最も高いものから消費します。"""
    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

同じロットを使用して、120 を $3.00 で 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. Specific Identification

トレーダーは、どのロットを売却するかを明示的に選択します。最大限の制御を提供しますが、綿密な記録保持が必要です。各ロットは、一意に識別可能である必要があります (例: 購入日時、またはロット ID)。

def specific_id_sell(lots: dict[str, dict], lot_ids: list[tuple[str, float]],
                     sell_price: float) -> list[dict]:
    """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. Proportional / Average Cost Method

保有するすべてのロットにわたって、1 ユニットあたりの単一の加重平均コストを計算します。すべての売却はその平均コストを使用します。平均は購入ごとに更新されます。


def average_cost_basis(lots: list[dict]) -> float:
    """すべてのロットにわたって、1 ユニットあたりの加重平均コストを計算します。"""
    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:
    """平均コストを使用して売却します。すべてのロットを比例的に削減します。"""
    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
    # 各ロットを比例的に削減します
    ratio = sell_qty / total_qty
    for lo
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Cost Basis Engine

Compute cost basis for crypto trades using multiple accounting methods and compare the resulting tax liability across methods. This skill handles the full complexity of on-chain activity: partial sells, token migrations, airdrops, staking rewards, LP entry/exit, and multi-hop swaps.

Disclaimer: This skill provides computational tools for informational purposes only. It does not constitute tax, legal, or financial advice. Consult a qualified tax professional for your specific situation. Tax law varies by jurisdiction and changes frequently.

Prerequisites

  • Python 3.10+
  • No external dependencies required (standard library only)
  • Trade history as a list of dicts or CSV with columns: date, action, token, quantity, price_usd, fee_usd

Methods Overview

Method Logic Best For
FIFO First lots purchased are sold first Simplicity, many jurisdictions' default
LIFO Last lots purchased are sold first Deferring gains when prices rise over time
HIFO Highest-cost lots are sold first Minimizing current tax liability
Specific ID Trader selects which lots to sell Maximum control, requires record-keeping
Average Cost Weighted average of all held lots Simplicity, required in some jurisdictions

1. FIFO (First-In, First-Out)

Sell the oldest lots first. This is the default method in the US if no other method is elected.

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

Partial sell example

You hold three lots of TOKEN:

  • Lot A: 100 units @ $1.00 (oldest)
  • Lot B: 50 units @ $2.00
  • Lot C: 75 units @ $1.50

You sell 120 units at $3.00:

  • 100 from Lot A: gain = (3.00 - 1.00) * 100 = $200
  • 20 from Lot B: gain = (3.00 - 2.00) * 20 = $20
  • Total realized gain: $220
  • Lot B remainder: 30 units @ $2.00

2. LIFO (Last-In, First-Out)

Sell the newest lots first. Reverses the order compared to 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

Using the same lots and selling 120 at $3.00 with LIFO:

  • 75 from Lot C: gain = (3.00 - 1.50) * 75 = $112.50
  • 45 from Lot B: gain = (3.00 - 2.00) * 45 = $45
  • Total realized gain: $157.50

3. HIFO (Highest-In, First-Out)

Sell the highest-cost lots first to minimize realized gains.

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

Same lots, selling 120 at $3.00 with HIFO:

  • 50 from Lot B ($2.00, highest): gain = (3.00 - 2.00) * 50 = $50
  • 70 from Lot C ($1.50, next highest): gain = (3.00 - 1.50) * 70 = $105
  • Total realized gain: $155
  • Remaining: Lot A 100 @ $1.00, Lot C 5 @ $1.50

4. Specific Identification

The trader explicitly selects which lots to sell. Provides maximum control but requires meticulous record-keeping. Each lot must be uniquely identifiable (e.g., by purchase date and time, or a lot 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. Proportional / Average Cost Method

Compute a single weighted-average cost per unit across all held lots. Every sell uses that average cost. The average updates after each buy.

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}

Partial sell with average cost

Lots: 100 @ $1.00, 50 @ $2.00, 75 @ $1.50. Total: 225 units, total cost $312.50.

Average cost = $312.50 / 225 = $1.3889/unit

Sell 120 at $3.00: gain = (3.00 - 1.3889) * 120 = $193.33

After the sell, 105 units remain at the same $1.3889 average.


6. Special Events

Airdrops

Airdrops are treated as income at fair market value (FMV) on the date received. The FMV becomes the cost basis for future sales.

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"
}

Staking Rewards

Staking rewards are income at FMV when received (similar to airdrops). Each reward event creates a new lot.

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"
}

Token Splits and Migrations

A token split or migration (old token to new token 1:1 or N:M) is generally not a taxable event. The total cost basis transfers to the new tokens.

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

For a 1:10 split of 100 tokens @ $5.00: result is 1000 tokens @ $0.50. Total basis unchanged at $500.


7. LP Entry/Exit as Token Swaps

Entering an LP position is treated as selling the deposited tokens and receiving LP tokens. Exiting is the reverse.

LP Entry (deposit 10 SOL + 1500 USDC into SOL/USDC pool):

  1. Dispose of 10 SOL at current FMV → capital gain/loss event
  2. Dispose of 1500 USDC at current FMV → usually negligible gain/loss
  3. Receive LP tokens with cost basis = FMV of deposited assets

LP Exit (redeem LP tokens for 12 SOL + 1400 USDC):

  1. Dispose of LP tokens at FMV of received assets → capital gain/loss
  2. Receive 12 SOL with cost basis = FMV at redemption
  3. Receive 1400 USDC with cost basis = FMV at redemption
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. Multi-Hop Swaps

A multi-hop swap (e.g., SOL -> USDC -> TOKEN) creates multiple taxable events, one for each intermediate step. Jupiter often routes through intermediate tokens.

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

Example: Swap 1 SOL ($150) -> 150 USDC -> 10,000 TOKEN ($0.015 each)

  • Event 1: Dispose 1 SOL (basis vs. $150 proceeds) → gain/loss on SOL
  • Event 2: Dispose 150 USDC (basis vs. $150 proceeds) → usually ~$0 gain
  • Result: 10,000 TOKEN with cost basis = $0.015/unit

9. Comparison View

The core value of this skill: run the same trade history through all five methods and compare total realized gain and estimated tax liability.

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

See scripts/cost_basis_calculator.py for a full runnable comparison with realistic trade data including partial sells.


Quick Start

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)

Use Cases

  1. Tax season preparation: Run your full year of trades through all methods before choosing one to report.
  2. Accumulation strategy: Track partial sells during DCA accumulation, see how each method affects remaining basis.
  3. LP position tracking: Model LP entry/exit as swaps and capture the associated gain/loss events.
  4. Airdrop and staking income: Properly record income events and set cost basis for future disposals.
  5. Multi-hop swap decomposition: Break down Jupiter routes into individual taxable events.

Files

File Description
references/planned_features.md Method formulas, partial sell worked examples, special event handling, multi-hop treatment
scripts/cost_basis_calculator.py Full engine with all 5 methods, comparison table, demo mode with realistic trades

Remember: The "best" method depends on your jurisdiction, your specific trade history, and your tax situation. This engine helps you compare — a tax professional helps you decide.