Skip to content

Repository files navigation

🔍 Crypto FIFO Calculator (Spanish Hacienda)

Important

Supported Platforms: Currently, this tool is designed to work specifically with Binance and Bitvavo CSV exports. Other platforms are not officially supported yet.

Warning

Potential Calculation Errors: While the engine is backed by a robust automated test suite, cryptocurrency tax rules are highly complex. This tool is provided "as is" and may contain bugs or miscalculations. Always cross-verify the results and consult a professional tax advisor before filing.

A high-precision Python CLI tool that parses platform transaction exports, resolves historical prices in EUR, applies a global FIFO engine with anti-wash sale rules, and generates detailed tax reports for the Spanish tax authorities (Hacienda Estatal - Modelo 100 or Hacienda Foral de Gipuzkoa - Modelo 109).


✨ Key Features

  1. Global FIFO Engine with High Precision: Uses Python's Decimal class for all mathematical calculations, preventing rounding errors common with standard float values.
  2. Dual Tax Regimes (Gipuzkoa vs. State):
    • Gipuzkoa (Modelo 109): Maps transactions to boxes 37, 38, 03, and 06.
    • State / Territorio Común (Modelo 100): Maps transactions to boxes 1626, 1631, 0033, and 0304.
  3. Anti-Wash Sale Rules (365-day Window): Implements the legally correct Spanish/Gipuzkoa anti-application of losses (regla anti-aplicación). If you sell an asset at a loss and repurchase it within ±365 days, the loss is deferred and added to the cost basis of the repurchased assets.
  4. Transfer Matching & Reconciliation Engine: Automatically matches a withdrawal from exchange A to a deposit on exchange B if they occur within a 2-hour window. The difference between the withdrawal and deposit amounts is recognized as a network transfer fee, which is deducted from the oldest FIFO lots and capitalized into the remaining lot units to preserve original cost basis.
  5. Data Health Check & Sanity Report: Chronologically pre-sweeps your transactions to detect negative balances (attempting to trade/withdraw more crypto than is present in the inventory) and missing price resolutions (resolving to 0.0 EUR), flagging potential missing CSV imports or API resolution issues.
  6. Non-Taxable Transfer Handling: Categorizes unmatched deposits and withdrawals (e.g. transfers to/from personal external wallets) as non-taxable transfers. These update the exchange balances without triggering phantom gains or generating new FIFO lots.
  7. Fair Transaction Fee Division: Groups transactions sharing a timestamp (e.g. swaps/converts) and splits the fee equally among the active legs, preventing transaction fees from being double-counted.
  8. Multi-Source Price Resolution:
    • Primary: minute-by-minute historical data from the Binance API.
    • Fallback: daily historical prices from CoinGecko.
    • Fiat Conversion: conversion of USD/other values using official ECB / Frankfurter API rates.
  9. Staking, Airdrops & Deferred Income: Separates staking rewards (Rendimientos del Capital Mobiliario) from airdrops (Base General) and handles locked assets (e.g. welcome incentives) using an unlock schedule.

🚀 Installation & Setup

Ensure you have Python 3.12+ installed.

  1. Clone or navigate to the workspace directory:
    cd CryptoFifoCalculator
  2. Set up a virtual environment and install the required dependencies (using uv or pip):
    python -m venv .venv
    source .venv/bin/activate  # On Linux/macOS
    # .venv\Scripts\activate   # On Windows
    pip install -r pyproject.toml  # or use `uv pip install -r pyproject.toml`

📂 Project Structure

  • main.py: CLI entry point for configuring and running the analysis.
  • config.py: Configures transaction mappings, tax box definitions, token rebrandings, and API maps.
  • transaction_service.py: Processes transactions in chronological groups, distributes fees, and tracks balances.
  • fifo_service.py: Core FIFO calculator implementing lot queueing and anti-wash sale window logic.
  • price_service.py: Parallel price prefetcher and resolver with local persistent caching.
  • console_renderer.py: Formats and renders estimated liquidations, tax boxes, and warnings to the console.
  • report_service.py: Exports detailed transaction audit logs to CSV format.
  • logger_config.py: Setting up concurrent file-based (session.log) and custom console-based logging.
  • loaders/: Platform-specific loader modules for parsing CSV formats of different exchanges.
  • tests/: Comprehensive pytest suite covering loaders, services, and core calculations.

💻 Usage

To run the calculator, you must place your platforms' transaction exports as CSV files inside a folder named plataforms/ in the project root directory.

📥 Exporting Your Data

1. Binance Exports

To process your Binance operations correctly, you must download two separate histories and place them in plataforms/:

  • Full Transaction History (plataforms/Binance.csv): Retrieve this by going to Binance's Data Download Center and exporting your complete transaction history.
  • Simple Earn History (plataforms/BinanceSimpleEarnFlexible.csv): Retrieve this by going to Binance's Data Download Center and exporting your complete Simple Earn.

2. Bitvavo Exports

  • Transaction History (plataforms/Bitvavo.csv): Export the full transaction ledger in CSV format from your Bitvavo dashboard.

🚀 Execution Commands

1. Default Run (Gipuzkoa Modelo 109)

Runs the calculator for all transactions and prints the summary mapped to Gipuzkoa's Modelo 109 boxes:

python main.py

2. State / Common Territory Run (Modelo 100)

Runs the calculator using the Spanish State tax regime and prints the summary mapped to the Modelo 100 boxes:

python main.py --regime comun
# or
python main.py -r comun

3. Filter by Specific Year(s)

Filter calculations for a specific tax year:

python main.py --year 2021

4. Audit / Diagnostic Mode (Trace Coin)

Focuses on auditing a single coin (e.g. BTC) and prints every FIFO lot entry, consumption event, and cost basis adjustment in detail:

python main.py --trace BTC

5. Clear Cache

Clear the price cache and fetch fresh historical market prices:

python main.py --clear-cache

📈 CLI Arguments Reference

Argument Description Default
-r, --regime Tax regime to use: gipuzkoa (Modelo 109) or comun (State Modelo 100). gipuzkoa
-y, --year Specific year(s) to process. All years
-d, --dust Filters out wallet balances below this EUR threshold from the final report. 0.01
-l, --limit Limits execution to the first N transactions (Diagnostic Mode). None
--from Start date filter (YYYY-MM-DD). None
--to End date filter (YYYY-MM-DD). None
-c, --check-only Performs calculations and checks logic without saving CSV reports. False
-o, --output Custom directory to save CSV reports. reports
--no-cache Ignores the local JSON price cache. False
--clear-cache Deletes the local JSON price cache before starting. False
-t, --trace Traces FIFO queue history for a specific coin (Diagnostic Mode). None
--detailed Print detailed transaction-by-transaction logs to the terminal. False
-v, --verbose Shows detailed debug output. False
-q, --quiet Suppresses progress logging. False

⚙️ Customization & User Configuration

You can customize the calculator to match your specific cryptocurrency transactions and asset migrations by modifying config.py. The key configuration parameters include:

  • UNLOCK_SCHEDULE: Adjust or add entries to define specific UTC release dates for locked promotional tokens (e.g., welcome rewards, signup bonuses, vesting schedules). Once the date passes, the engine automatically unlocks the assets for active trading.
  • COIN_MAPPING: Define token rebrandings and migrations (such as MATIC to POL or KLAY to KAIA). This instructs the FIFO engine to treat both tickers as the same continuous lot sequence, maintaining cost basis correctly.
  • COIN_RATIO: Define split ratios for migrations (e.g., MC to BEAMX with a multiplier ratio of 100.0). The system automatically scales your token quantities and reduces the acquisition cost basis proportionately.
  • DEFAULT_CG_ID_MAP: Set unique CoinGecko API ID slugs for custom or exotic coins (e.g., mapping ticker BTC to ID slug bitcoin). Use this if a coin ticker fails to resolve automatically on CoinGecko.
  • MANUAL_PRICES: Provide price overrides for specific tokens on specific dates in format 'COIN_YYMMDD' : price_in_eur. Useful if APIs miss pricing data or for private OTC transactions.

🛠️ Development & Quality Control

1. Running Tests

The project features a comprehensive pytest suite testing FIFO queues, loaders, price resolving, and the transaction processor. Run the tests using uv (recommended) or direct python/pytest commands:

uv run pytest
# or
.venv/bin/pytest

2. Code Linting & Formatting (Ruff)

We use Ruff for lightning-fast Python linting and formatting. It enforces PEP-8 rules, imports sorting, clean exception handling, and common bug prevention logic (defined in pyproject.toml).

  • Check for code style / quality errors:
    uv run ruff check .
  • Auto-format source files:
    uv run ruff format .

⚖️ Legal Disclaimer

This software is an analytical tool designed to help you process cryptocurrency transaction logs. The estimations and tax box mappings generated are not official tax advice. Cryptocurrency tax regulations are subject to frequent updates; always consult with a qualified tax advisor (Asesor Fiscal) before submitting any tax returns.

About

A high-precision Python CLI FIFO tax calculator for Binance & Bitvavo, tailored for Spanish tax declarations (Hacienda - Modelo 100 & 109). Features Decimal math, anti-wash sale rules, transfer fee reconciliation, and automatic EUR price resolution.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages