← Back to list
💰

cost-basis-engine Checked

Multi-method cost basis computation including specific identification, FIFO, LIFO, HIFO, and prop…
💰 Finance & Trading skills By agiprolabs Version v1.0.0 Added 2026-09-20 Updated 2026-09-20 Source ↗
7.7Overall rating
2Views
6Downloads
366Stars

Installation

🤖 Install via AI

Copy the prompt below and send it to your AI assistant (e.g. Claude Code) — it will follow the instructions and install automatically.

Install the "cost-basis-engine" skill by following the instructions at https://skill123.me/install/cost-basis-engine.
⌨️ Command line install

Run in your terminal — downloads and installs to ~/.claude/skills/.

curl -fsSL https://skill123.me/install/cost-basis-engine.sh | bash
📦 Download ZIP

Download the zip and extract it into your skills directory (e.g. ~/.claude/skills/), then restart your session.

⬇ Download v1.0.0 · 13 KB
📊 Static rating
7.7/10
Trigger
4.0
Structure
9.3
Workflow
6.4
Content
9.0
Engineering
10.0
Security
10.0

Six-dimension rubric with reviewer rationale.

View scorecard ↓
🛡 Dynamic test
—

Not live-tested yet — this skill is rated on static analysis only.

About this skill

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

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.

Documentation

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

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.

View full documentation

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 a

Score breakdown

Trigger
4.0
Description states What only (methods list, partial sells); no When/When-Not, no trigger phrase variants, no Chinese keywords; keyword richness from method names only.
Structure
9.3
358-line SKILL.md within limit; clean scripts/+references/ split; Files table points to both; no redundant docs. Reference filename 'planned_features.md' is misleading (contains formulas, not roadmap).
Workflow
6.4
Mostly explanatory snippets plus Quick Start and runnable comparison script; demo mode and worked examples provide verification; moderate error handling (qty clamping, float epsilon) but no input validation for malformed trade data.
Content
9.0
Concise, consistent formatting, concrete runnable examples with expected numbers; minor duplication between SKILL.md snippets and script.
Engineering
10.0
Valid frontmatter (name/description/metadata); script has shebang and declared stdlib-only deps; all referenced paths exist; demo runs successfully.
Security
10.0
Capability manifest: no file/env/credential reads, no writes, no network egress, no persistence — pure computation; capabilities match declared scope. Tax disclaimer present. No injection, no secrets, no external URLs.
Solid computational skill: 5 cost-basis methods (FIFO/LIFO/HIFO/SpecificID/AvgCost) with a runnable stdlib-only Python engine and demo mode; good worked examples and tax disclaimer. Weak trigger description (no When/When-Not, no user phrasing variants); SKILL.md is largely explanatory code snippets duplicating the script (minor 3.1/3.2 hit).