---
title: "7.4.6 Fiscalidad del trading en España"
description: "Base del ahorro de 2026, FIFO, permutas de cripto, regla de los dos meses, compensación de pérdidas y convenios, con un motor fiscal probado en Python."
url: "https://pythonparatrading.com/curso-python-trading/nivel-7/fiscalidad-del-trading-en-espana/"
lang: "es"
image: "https://pythonparatrading.com/og/curso-python-trading/nivel-7/fiscalidad-del-trading-en-espana.png"
---

# 7.4.6 · Fiscalidad del trading en España

> Un año de operaciones se convierte en una cifra de la declaración siguiendo reglas que se pueden programar: qué lote se vende, cuándo una pérdida no cuenta, cómo se compensan los saldos y qué parte del impuesto pagado fuera se recupera. Esta lección las lee en el BOE y en las consultas de la DGT y las convierte en un motor probado contra casos calculados a mano. No es asesoramiento fiscal.

- Curso: [Nivel 7: Producción, MLOps, regulación, carrera y capstone](https://pythonparatrading.com/curso-python-trading/nivel-7/)
- Módulo: 7.4 · Regulación, ética y fiscalidad
- Duración: 65 min
- Requisitos: [4.4.1 · Elegir bróker desde España o la UE: regulación, activos, costes y API](https://pythonparatrading.com/curso-python-trading/nivel-4/elegir-broker-desde-espana-y-la-ue/), [1.2.1 · Acciones: splits, dividendos y eventos corporativos](https://pythonparatrading.com/curso-python-trading/nivel-1/acciones-splits-dividendos-y-eventos-corporativos/), [0.3.1 · Variables, tipos y operadores; coma flotante y decimal para precios y ticks](https://pythonparatrading.com/curso-python-trading/nivel-0/variables-tipos-y-decimal/)

## Al terminar esta lección

- Calcular la cuota de la base del ahorro con la escala de 2026 (arts. 66 y 76 de la Ley del IRPF) y distinguir el tipo marginal del tipo medio.
- Determinar ganancias y pérdidas con FIFO sobre todo el patrimonio, también en criptomonedas y en permutas entre ellas, como interpreta la DGT.
- Aplicar la regla de los dos meses del art. 33.5 f): diferir una pérdida con recompra e integrarla cuando la venta es definitiva.
- Compensar saldos y pérdidas pendientes con el límite del 25 % y el plazo de cuatro años, y limitar la deducción por doble imposición a lo que permite el convenio.

<aside class="callout" data-kind="riesgo">

**No es asesoramiento fiscal.** Esta lección explica normas generales del IRPF para residentes en territorio común
(País Vasco y Navarra tienen normativa foral propia) y las convierte en código didáctico. No cubre actividades
económicas, sociedades, derivados, no residentes ni muchos casos particulares. Las cifras se comprobaron en el BOE, la
AEAT y la DGT el 23 de octubre de 2026; la norma cambia. Para una declaración real, la fuente es la AEAT y, si hace
falta, un asesor.

</aside>

## La base del ahorro y su escala

El IRPF separa dos bases. La **general** recoge el trabajo, las actividades económicas y otras rentas; la **del
ahorro** recoge, entre otras, los rendimientos del capital mobiliario (dividendos e intereses, art. 25) y las ganancias
y pérdidas patrimoniales que se ponen de manifiesto al transmitir elementos patrimoniales (art. 46)[^1]. Un particular
que compra y vende acciones, ETFs o criptomonedas, y que cobra dividendos, tributa por ellos en la base del ahorro.

La escala tiene dos mitades iguales: la estatal (art. 66.1) y la autonómica (art. 76), ambas fijadas en la ley
estatal. Desde el 1 de enero de 2025, tras la Ley 7/2024, el último tramo pasó del 28 % al 30 %, y el texto
consolidado del BOE no recoge cambios posteriores en esos dos artículos: la escala de 2025 es la de 2026[^1].

| Base liquidable del ahorro | Estatal | Autonómica | Total | Cuota acumulada al final |
|---|---|---|---|---|
| Hasta 6.000 € | 9,5 % | 9,5 % | 19 % | 1.140 € |
| 6.000 a 50.000 € | 10,5 % | 10,5 % | 21 % | 10.380 € |
| 50.000 a 200.000 € | 11,5 % | 11,5 % | 23 % | 44.880 € |
| 200.000 a 300.000 € | 13,5 % | 13,5 % | 27 % | 71.880 € |
| Más de 300.000 € | 15 % | 15 % | 30 % | — |

La columna de la cuota acumulada no es un cálculo propio: es la de la escala del art. 66.2, que aplica los tipos
completos a los residentes en el extranjero del art. 8.2 y 10.1, y sirve para comprobar el código.

*Fig. — Tipos del IRPF sobre la base del ahorro en España por tramo (territorio común).* Barras escalonadas con el tipo de cada tramo de la base liquidable del ahorro: 19 % hasta 6.000 euros, 21 % hasta 50.000, 23 % hasta 200.000, 27 % hasta 300.000 y 30 % por encima, el tramo más alto, destacado.

La escala se aplica a la parte de la base del ahorro que excede del mínimo personal y familiar (art. 66.1). Aquí se
supone que la base general lo absorbe entero, que es lo habitual con un sueldo; si no, la cuota del ahorro baja. Con
importes en `Decimal` (lección 0.3.1), para que los céntimos cuadren:

```python
from decimal import Decimal as D, ROUND_HALF_UP

# Escala del ahorro 2026: (hasta, estatal art. 66, autonómica art. 76)
TRAMOS = [
    (D(6000), D("0.095"), D("0.095")),
    (D(50000), D("0.105"), D("0.105")),
    (D(200000), D("0.115"), D("0.115")),
    (D(300000), D("0.135"), D("0.135")),
    (None, D("0.15"), D("0.15")),
]


def c2(x):
    """Redondea a céntimos, como en la declaración."""
    return D(x).quantize(D("0.01"), rounding=ROUND_HALF_UP)


def cuota_ahorro(base):
    """Cuota íntegra del ahorro y su desglose por tramos."""
    base, desde, filas = D(base), D(0), []
    for hasta, estatal, autonomico in TRAMOS:
        if base <= desde:
            break
        tope = base if hasta is None else min(base, hasta)
        tipo = estatal + autonomico
        filas.append((desde, tope, tipo, c2((tope - desde) * tipo)))
        if hasta is None:
            break
        desde = hasta
    return sum((f[3] for f in filas), D(0)), filas


total, filas = cuota_ahorro(75000)
for desde, hasta, tipo, cuota in filas:
    print(f"{desde:>7,.0f} a {hasta:>7,.0f}  {tipo:.0%}"
          f"  {cuota:>9,.2f}")
print(f"{'Cuota íntegra':>27}  {total:>9,.2f}")
```
```output
      0 a   6,000  19%   1,140.00
  6,000 a  50,000  21%   9,240.00
 50,000 a  75,000  23%   5,750.00
              Cuota íntegra  16,130.00
```

La cuota de 75.000 euros no es el 23 % de 75.000, sino cada tramo a su tipo. La diferencia entre el tipo del último
euro y el de toda la base importa al estimar lo que una estrategia rinde después de impuestos:

```python
print(" base       marginal   medio")
for base in (6000, 20000, 50000, 120000, 300000, 1000000):
    cuota, filas = cuota_ahorro(base)
    print(f"{base:>9,}  {filas[-1][2]:>8.0%}  {cuota / base:>7.2%}")
```
```output
 base       marginal   medio
    6,000       19%   19.00%
   20,000       21%   20.40%
   50,000       21%   20.76%
  120,000       23%   22.07%
  300,000       27%   23.96%
1,000,000       30%   28.19%
```

La figura de la cabecera dibuja las dos curvas. Para decidir si realizar una ganancia este año o el siguiente cuenta
el marginal; para estimar el impuesto total de un año, el medio. Con 300.000 euros de base, el tipo medio es del
23,96 %, y cada euro más tributa ya al 30 %.

## Valor de adquisición, FIFO y plataformas

Una ganancia o pérdida patrimonial es la diferencia entre el valor de transmisión y el de adquisición, y los dos
incluyen los gastos y tributos inherentes a la operación: la comisión de compra suma al coste y la de venta resta del
importe (art. 35)[^1]. El problema práctico es qué títulos se venden cuando se han comprado en varias veces a precios
distintos. Para valores homogéneos, el art. 37.2 lo resuelve: «se considerará que los transmitidos por el
contribuyente son aquéllos que adquirió en primer lugar». Es FIFO, y es obligatorio: no se puede elegir el lote más
caro para declarar menos.

Para las criptomonedas la ley no dice nada, pero la DGT aplica el mismo criterio. En la consulta V1604-18 concluye que
en ventas parciales de bitcoin «debe considerarse que los "bitcoin" que se transmiten son los adquiridos en primer
lugar», y que comprarlos y venderlos en distintos exchanges «no constituye una circunstancia que altere la
homogeneidad». Lo repiten la V0975-22 y la V1550-25, de septiembre de 2025, que añade que el criterio se circunscribe
a las criptomonedas, no a otros criptoactivos, cuya homogeneidad requeriría un análisis propio[^2].

El registro de operaciones de la lección es sintético y está hecho para que cada regla tenga al menos un caso que la
ponga a prueba. Los activos son ficticios salvo BTC y ETH, y los importes son euros ya netos de comisiones (en una
cuenta en dólares, cada compra y cada venta se convierten al cambio de su fecha):

```python
from dataclasses import dataclass, field
from datetime import date


@dataclass
class Op:
    fecha: date
    tipo: str        # compra, venta, permuta o dividendo
    activo: str
    cantidad: D
    importe: D       # euros netos de comisiones
    sitio: str       # bróker o exchange
    clase: str       # "valor" (cotizado) o "cripto"
    datos: dict = field(default_factory=dict)


def op(f, tipo, activo, cant, imp, sitio="B1", clase="valor", **k):
    return Op(date.fromisoformat(f), tipo, activo, D(cant), D(imp),
              sitio, clase, k)


def registro_sintetico():
    """Operaciones ficticias con los casos que hay que acertar."""
    return [
        op("2019-05-06", "compra", "ETFX", 1000, "40005"),
        op("2025-01-15", "compra", "GAMMA", 300, "6005"),
        op("2025-02-10", "compra", "BTC", "0.1", "9009", "EX1",
           "cripto"),
        op("2025-03-10", "compra", "ACME", 100, "5005"),
        op("2025-06-02", "compra", "BETA", 200, "8005"),
        op("2025-09-15", "compra", "ACME", 100, "6005"),
        op("2025-11-03", "compra", "DELTA", 100, "8005"),
        op("2025-12-01", "compra", "BTC", "0.1", "8008", "EX2",
           "cripto"),
        op("2026-02-20", "venta", "ACME", 150, "13495"),
        op("2026-03-02", "venta", "DELTA", 100, "5995"),
        op("2026-03-15", "venta", "BTC", "0.1", "7492.5", "EX2",
           "cripto"),
        op("2026-03-20", "compra", "DELTA", 100, "5805"),
        op("2026-04-01", "compra", "EPSI", 400, "4005"),
        op("2026-04-15", "dividendo", "ACME", 0, "500",
           retencion_es=D(95)),
        op("2026-05-11", "venta", "BETA", 200, "5995"),
        op("2026-05-20", "venta", "EPSI", 200, "1795"),
        op("2026-06-10", "venta", "ETFX", 1000, "98995"),
        op("2026-06-25", "compra", "BETA", 200, "6205"),
        op("2026-06-30", "dividendo", "USAA", 0, "800", "B2",
           retencion_ext=D(120), tipo_convenio=D("0.15")),
        op("2026-07-15", "venta", "DELTA", 100, "6595"),
        op("2026-08-10", "permuta", "BTC", "0.05", "4600", "EX1",
           "cripto", recibe="ETH", cantidad_recibida=D("1.5"),
           valor_recibido=D(4575)),
        op("2026-09-01", "venta", "GAMMA", 300, "4495"),
        op("2026-09-30", "dividendo", "USBB", 0, "400", "B2",
           retencion_ext=D(120), tipo_convenio=D("0.15")),
        op("2026-10-20", "compra", "GAMMA", 100, "1405"),
        op("2026-11-05", "venta", "ETH", "0.5", "1648.35", "EX1",
           "cripto"),
    ]


REG = registro_sintetico()
print(len(REG), "operaciones;",
      sum(o.tipo == "venta" for o in REG), "ventas")
```
```output
25 operaciones; 9 ventas
```

El motor recorre el registro por fechas y lleva una cola de lotes por activo. Cada venta consume los lotes más
antiguos; cada lote guarda, además del coste, la pérdida diferida que arrastra por la regla de los dos meses, que se
explica más abajo:

```python
from collections import defaultdict, deque
from dateutil.relativedelta import relativedelta

DOS_MESES = relativedelta(months=2)


@dataclass
class Lote:
    origen: int        # id de la compra que lo creó
    cantidad: D
    coste: D           # valor de adquisición de lo que queda
    diferida: D = D(0)  # pérdida diferida que arrastra (art. 33.5)


class Motor:
    """Ganancias y pérdidas del ejercicio con FIFO y recompras."""

    def __init__(self, registro, ejercicio, por_sitio=False):
        self.reg = sorted(registro, key=lambda o: o.fecha)
        self.ejercicio, self.por_sitio = ejercicio, por_sitio
        self.lotes = defaultdict(deque)
        self.libre = {id(o): o.cantidad for o in self.reg
                      if o.tipo == "compra"}  # aún no son recompra
        self.por_llegar = defaultdict(D)  # diferida de compras futuras
        self.gp, self.rcm, self.diferidas = [], [], []

    def clave(self, o, activo=None):
        activo = activo or o.activo
        return (activo, o.sitio) if self.por_sitio else activo

    def comprar(self, o, activo, cantidad, coste):
        lote = Lote(id(o), cantidad, coste,
                    self.por_llegar.pop(id(o), D(0)))
        self.lotes[self.clave(o, activo)].append(lote)

    def sacar_fifo(self, o):
        """Consume los lotes más antiguos (coste y diferida)."""
        cola, falta = self.lotes[self.clave(o)], o.cantidad
        coste = diferida = D(0)
        while falta > 0:
            if not cola:
                raise ValueError(f"{o.fecha} {o.activo}: sin títulos")
            lote = cola[0]
            u = min(falta, lote.cantidad)
            parte = u / lote.cantidad
            coste += lote.coste * parte
            diferida += lote.diferida * parte
            lote.coste -= lote.coste * parte
            lote.diferida -= lote.diferida * parte
            lote.cantidad -= u
            falta -= u
            if lote.cantidad == 0:
                cola.popleft()
        return coste, diferida

    def compras(self, o, desde, hasta):
        return [c for c in self.reg if c.tipo == "compra"
                and c.activo == o.activo and desde <= c.fecha <= hasta
                and c is not o]

    def saldo(self, activo, antes_de):
        s = D(0)
        for c in self.reg:
            if c.activo == activo and c.fecha < antes_de:
                s += c.cantidad if c.tipo == "compra" else -c.cantidad
        return s

    def recompras(self, o):
        """Unidades de compras homogéneas que cuentan como recompra."""
        d = o.fecha
        antes = [c for c in self.compras(o, d - DOS_MESES, d)
                 if c.fecha < d]
        despues = [c for c in self.compras(o, d, d + DOS_MESES)
                   if c.fecha > d]
        quedan = sum(l.cantidad for l in self.lotes[self.clave(o)])
        inicio = self.saldo(o.activo, o.fecha - DOS_MESES)
        if len(antes) == 1 and inicio == 0:
            antes = []  # única compra y sin títulos: no es recompra
        usadas, falta, tope = [], o.cantidad, quedan
        previas = {id(c) for c in antes}
        for c in antes + despues:
            u = min(self.libre[id(c)], falta)
            if id(c) in previas:
                u = min(u, tope)
                tope -= u
            if u > 0:
                usadas.append((c, u))
                self.libre[id(c)] -= u
                falta -= u
        return usadas

    def vender(self, o, valor, nota):
        coste, liberada = self.sacar_fifo(o)
        resultado = valor - coste
        if liberada and self.compras(o, o.fecha - DOS_MESES,
                                     o.fecha + DOS_MESES):
            raise NotImplementedError(
                f"{o.activo} {o.fecha}: venta no definitiva de títulos"
                " con pérdida diferida; revisar a mano")
        if resultado < 0 and o.clase == "valor":
            usadas = self.recompras(o)
            n = sum((u for _, u in usadas), D(0))
            diferida = resultado * n / o.cantidad
            for c, u in usadas:
                self.asignar(c, resultado * u / o.cantidad)
            if n:
                self.diferidas.append(
                    (o.fecha, o.activo, c2(-diferida)))
                nota += f" (difiere {n} de {o.cantidad})"
            resultado -= diferida
        self.anotar(o, resultado, nota)
        if liberada:
            self.anotar(o, -liberada, "pérdida diferida que se integra")

    def asignar(self, compra, perdida):
        for cola in self.lotes.values():
            for lote in cola:
                if lote.origen == id(compra):
                    lote.diferida += -perdida
                    return
        self.por_llegar[id(compra)] += -perdida

    def anotar(self, o, importe, nota):
        if o.fecha.year == self.ejercicio:
            self.gp.append((o.fecha, o.activo, c2(importe), nota))

    def procesar(self):
        for o in self.reg:
            if o.tipo == "compra":
                self.comprar(o, o.activo, o.cantidad, o.importe)
            elif o.tipo == "venta":
                self.vender(o, o.importe, "venta")
            elif o.tipo == "permuta":
                d = o.datos
                valor = max(o.importe, d["valor_recibido"])  # 37.1.h
                self.vender(o, valor, f"permuta por {d['recibe']}")
                self.comprar(o, d["recibe"], d["cantidad_recibida"],
                             valor)
            elif o.tipo == "dividendo":
                if o.fecha.year == self.ejercicio:
                    self.rcm.append(o)
        return self


m = Motor(REG, 2026).procesar()
for fecha, activo, importe, nota in m.gp:
    print(f"{fecha}  {activo:<6}{importe:>10,.2f}  {nota}")
```
```output
2026-02-20  ACME    5,487.50  venta
2026-03-02  DELTA       0.00  venta (difiere 100 de 100)
2026-03-15  BTC    -1,516.50  venta
2026-05-11  BETA        0.00  venta (difiere 200 de 200)
2026-05-20  EPSI     -207.50  venta
2026-06-10  ETFX   58,990.00  venta
2026-07-15  DELTA     790.00  venta
2026-07-15  DELTA  -2,010.00  pérdida diferida que se integra
2026-08-10  BTC       596.00  permuta por ETH
2026-09-01  GAMMA  -1,006.67  venta (difiere 100 de 300)
2026-11-05  ETH       115.02  venta
```

Las ganancias de ACME salen de FIFO: las 150 acciones vendidas son las 100 de marzo de 2025 (5.005 euros) y la mitad
del lote de septiembre (3.002,50), así que la ganancia es 13.495 − 8.007,50 = 5.487,50 euros. La de ETFX, 58.990
euros, viene de un ETF comprado en 2019: la antigüedad no reduce la ganancia.

El error de llevar un FIFO por exchange, que es lo que hace quien suma los informes de cada plataforma por separado:

```python
def resultado(motor, activo):
    return sum(i for _, a, i, _ in motor.gp if a == activo)


bien = Motor(REG, 2026).procesar()
mal = Motor(REG, 2026, por_sitio=True).procesar()
print("BTC, FIFO de todo el patrimonio:", resultado(bien, "BTC"))
print("BTC, FIFO por exchange:        ", resultado(mal, "BTC"))
```
```output
BTC, FIFO de todo el patrimonio: -920.50
BTC, FIFO por exchange:         -420.00
```

La venta de marzo se hizo en el segundo exchange, pero las unidades vendidas a efectos fiscales son las primeras que
se compraron, en el primero. Contar por exchange declara 500,50 euros menos de pérdida en 2026 y deja en cartera un
coste equivocado para los años siguientes.

## Criptomonedas: cada permuta es una venta

Cambiar un criptoactivo por otro no es neutral. La DGT, en la V0999-18, califica el intercambio entre monedas
virtuales distintas como una **permuta** que genera una ganancia o pérdida patrimonial en la base del ahorro, valorada
con el art. 37.1 h): la diferencia entre el valor de adquisición de lo entregado y **el mayor** del valor de mercado de
lo entregado y de lo recibido. Ese mismo valor pasa a ser el de adquisición de lo recibido[^3].

En el registro, el 10 de agosto se entregan 0,05 BTC (valor de mercado 4.600 euros) a cambio de 1,5 ETH (4.575
euros). El coste FIFO de esos 0,05 BTC es la mitad del lote de diciembre, 4.004 euros, así que la ganancia es 4.600 −
4.004 = 596 euros y los ETH entran en cartera con un coste de 4.600. La venta posterior de 0,5 ETH por 1.648,35 euros
da 1.648,35 − 4.600/3 = 115,02 euros. La permuta no pasó por euros y tributa igual que una venta.

Dos límites del motor que conviene decir. El primero: la regla de los dos meses de la sección siguiente habla de
«valores o participaciones admitidos a negociación», y una criptomoneda no lo es; la letra e) del mismo art. 33.5
trata la recompra de «elementos patrimoniales» en el plazo de un año. Las consultas leídas para esta lección no
resuelven cómo se aplica a las criptomonedas, así que el motor no aplica ninguna regla de recompra a la clase
`cripto` y lo deja como decisión explícita. El segundo: staking, airdrops, préstamos o DeFi tienen tratamientos
propios que el motor no modela.

## La regla de los dos meses

El art. 33.5 f) dice que no se computan como pérdidas las derivadas de transmitir valores admitidos a negociación
«cuando el contribuyente hubiera adquirido valores homogéneos dentro de los dos meses anteriores o posteriores a dichas
transmisiones», y que esas pérdidas «se integrarán a medida que se transmitan los valores o participaciones que
permanezcan en el patrimonio». Para valores no cotizados, la letra g) alarga el plazo a un año[^1]. La finalidad, en
palabras de la DGT, es no permitir la pérdida «en tanto el patrimonio del contribuyente permanezca constante».

```mermaid
flowchart TB
  V[Venta con pérdida] --> C{¿Valor cotizado?}
  C -- no --> G[No cotiza: 1 año]
  C -- sí --> R{¿Compra ±2 meses?}
  R -- no --> I[Se integra]
  R -- sí --> D[Se difiere]
  D --> T[Venta definitiva]
  T --> I
```

El detalle está en la doctrina de la DGT, que la consulta V5316-26 (julio de 2026) resume en un procedimiento[^4]:

- **Compras posteriores** a la venta, dentro de los dos meses: impiden computar la pérdida de las unidades
  recompradas.
- **Compras anteriores**, dentro de los dos meses: solo cuentan como recompra hasta el saldo de títulos que queda
  después de la venta. Y no cuentan si en ese plazo hubo **una única compra** y al empezarlo no se tenían títulos.
- Una misma compra no puede bloquear dos pérdidas: las compras ya usadas como recompra no vuelven a contar.
- La pérdida diferida se integra cuando se venden los títulos recomprados en una venta **definitiva**, sin recompra
  en los dos meses. La V0754-26 lo aplica por unidades: integra la pérdida de 185 de las 207 acciones de una venta, y
  la V0089-26 no deja computar una pérdida porque en los dos meses anteriores se habían comprado más títulos de los
  vendidos.

El motor programa esas cuatro reglas en `recompras` y `vender`, y el registro tiene un caso para cada una: BETA
(recompra posterior total), GAMMA (recompra posterior parcial, 100 de 300), EPSI (una única compra previa sin títulos
al empezar el plazo, el mismo patrón que la V5316-26) y DELTA (pérdida diferida que se libera al vender en julio sin
recompra). El resultado:

```python
print("Pérdidas diferidas en 2026:")
for fecha, activo, importe in m.diferidas:
    print(f"  {fecha} {activo:<6}{importe:>9,.2f}")
print("Siguen en cartera con pérdida diferida:")
for activo, cola in m.lotes.items():
    for lote in cola:
        if lote.diferida:
            print(f"  {activo:<6}{lote.cantidad:>5} títulos"
                  f"{c2(lote.diferida):>9,.2f}")
```
```output
Pérdidas diferidas en 2026:
  2026-03-02 DELTA  2,010.00
  2026-05-11 BETA   2,010.00
  2026-09-01 GAMMA    503.33
Siguen en cartera con pérdida diferida:
  GAMMA   100 títulos   503.33
  BETA    200 títulos 2,010.00
```

De las tres pérdidas diferidas en 2026, la de DELTA ya se ha integrado en el mismo año: la línea «pérdida diferida que
se integra» de la tabla anterior. Las de BETA y GAMMA siguen dentro de los lotes recomprados y se integrarán el año en
que se vendan de forma definitiva. Un motor sin esta regla habría declarado en 2026 2.513,33 euros más de pérdidas (los 2.010 de BETA y los 503,33 de GAMMA).

<aside class="callout" data-kind="aviso">

La ventana es de dos meses a cada lado, así que una venta de diciembre puede quedar bloqueada por una compra de enero
o febrero del año siguiente. El registro que alimenta el cálculo de un ejercicio tiene que incluir esos dos meses, y
el motor se niega (lanza `NotImplementedError`) ante una venta de títulos con pérdida diferida que vuelve a tener
compras alrededor: es un caso en que la doctrina encadena las recompras y conviene revisarlo a mano.

</aside>

## Dividendos, retenciones y convenios

Los dividendos son rendimientos del capital mobiliario (art. 25.1) y van a la base del ahorro por su importe íntegro,
antes de retenciones. Un pagador español retiene el 19 % a cuenta (art. 101.4), que se descuenta al final como pago a
cuenta[^1]. Un dividendo extranjero suele llegar con una retención del país de origen, y ahí entran dos piezas:

- **El convenio.** El de España con EE. UU., en la redacción del Protocolo de 2013 (publicado en el BOE el 23 de
  octubre de 2019), permite a EE. UU. gravar el dividendo que cobra un residente en España con un máximo del 15 %
  del importe bruto; con tipos menores solo para sociedades con participaciones significativas y fondos de pensiones (art. 10)[^5]. Para aplicar ese
  tipo, el bróker necesita el formulario **W-8BEN** del IRS, que acredita la residencia del beneficiario; sin él, la
  retención general sobre esos pagos es del 30 %. El formulario vale, en general, hasta el último día del tercer año
  natural siguiente al de la firma[^6].
- **La deducción por doble imposición internacional** (art. 80). Se deduce la menor de dos cantidades: lo
  efectivamente satisfecho en el extranjero y el resultado de aplicar el tipo medio efectivo del ahorro a la parte de
  la base obtenida fuera. La AEAT precisa que ese tipo medio es el de la base del ahorro sin descomponer y se expresa
  con dos decimales[^7]. Y la DGT entiende por importe satisfecho el que el otro Estado **puede aplicar según el
  convenio** (V5381-26)[^8]: lo retenido de más no se deduce en España y solo se recupera reclamándolo al país de
  origen.

En el registro hay un dividendo español (500 euros, 95 retenidos) y dos de EE. UU. de 800 y 400 euros, con 120 euros
retenidos en cada uno: el primero al 15 %, con W-8BEN; el segundo al 30 %, sin él.

```python
def rendimientos(motor):
    bruto = sum((o.importe for o in motor.rcm), D(0))
    ext = [o for o in motor.rcm if "retencion_ext" in o.datos]
    base_ext = sum((o.importe for o in ext), D(0))
    retenido = sum((o.datos["retencion_ext"] for o in ext), D(0))
    admisible = sum((min(o.datos["retencion_ext"],
                         c2(o.importe * o.datos["tipo_convenio"]))
                     for o in ext), D(0))
    ret_es = sum((o.datos.get("retencion_es", D(0))
                  for o in motor.rcm), D(0))
    return dict(bruto=bruto, base_ext=base_ext, retenido_ext=retenido,
                admisible=admisible, retencion_es=ret_es)


for k, v in rendimientos(m).items():
    print(f"{k:<13}{v:>8,.2f}")
```
```output
bruto        1,700.00
base_ext     1,200.00
retenido_ext   240.00
admisible      180.00
retencion_es    95.00
```

De los 240 euros retenidos en EE. UU., solo 180 son deducibles: 120 del primer dividendo y 60 (el 15 % de 400) del
segundo. Como el tipo del convenio (15 %) es menor que el tipo medio mínimo de la base del ahorro (19 %), con
dividendos de EE. UU. el límite que manda es casi siempre el del convenio, no el del tipo medio.

## Compensación de pérdidas y liquidación

El art. 49 forma la base del ahorro con dos saldos que se calculan por separado: el de rendimientos del capital
mobiliario y el de ganancias y pérdidas patrimoniales. Si uno es negativo, compensa el positivo del otro **con el
límite del 25 %** de ese saldo positivo, y lo que quede se compensa «en los cuatro años siguientes en el mismo
orden»[^1]. El manual de la AEAT detalla el orden con los saldos de ejercicios anteriores: primero cada partida
pendiente con su propio saldo del año, sin límite; después, el resto de forma cruzada, con un 25 % que comparte con
la compensación del propio ejercicio[^9].

```mermaid
flowchart TB
  A[Saldo RCM] --> X{Cruce 25 %}
  B[Saldo GP] --> X
  X --> P[Pendientes propios]
  P --> Q[Pendientes, cruce]
  Q --> BA[Base del ahorro]
  BA --> E[Escala 19 a 30 %]
```

La mejor prueba de una función así es un caso resuelto por la propia administración. El manual de Renta 2025 trae
uno: rendimientos del capital mobiliario de −800 euros, ganancias de 5.600, pérdidas de 1.600 y partidas pendientes
de 2021 y 2022. Su solución da una base del ahorro de 200 euros:

```python
def compensar(rcm, gp, pend_rcm, pend_gp, ejercicio):
    """Art. 49 LIRPF, en el orden del manual de la AEAT."""
    rcm, gp = D(rcm), D(gp)
    pend_rcm, pend_gp = dict(pend_rcm), dict(pend_gp)
    vivas = range(ejercicio - 4, ejercicio)
    caducadas = {k: v for p in (pend_rcm, pend_gp)
                 for k, v in p.items() if k not in vivas}
    pend_rcm = {k: D(v) for k, v in pend_rcm.items() if k in vivas}
    pend_gp = {k: D(v) for k, v in pend_gp.items() if k in vivas}
    lim_gp, lim_rcm = D("0.25") * max(gp, 0), D("0.25") * max(rcm, 0)
    # Fase 1: saldos del ejercicio, cruce con el 25 %
    if rcm < 0 < gp:
        x = min(-rcm, lim_gp)
        rcm, gp, lim_gp = rcm + x, gp - x, lim_gp - x
    if gp < 0 < rcm:
        x = min(-gp, lim_rcm)
        gp, rcm, lim_rcm = gp + x, rcm - x, lim_rcm - x
    nuevas_rcm, nuevas_gp = -min(rcm, 0), -min(gp, 0)
    rcm, gp = max(rcm, 0), max(gp, 0)

    def gastar(pend, saldo, tope=None):
        for año in sorted(pend):
            x = min(pend[año], saldo,
                    saldo if tope is None else tope)
            pend[año] -= x
            saldo -= x
            if tope is not None:
                tope -= x
        return saldo, tope

    # Fase 2, 1.º: cada partida pendiente con su propio saldo
    rcm, _ = gastar(pend_rcm, rcm)
    gp, _ = gastar(pend_gp, gp)
    # Fase 2, 2.º: el resto, cruzado y dentro del 25 % que quede
    gp, lim_gp = gastar(pend_rcm, gp, lim_gp)
    rcm, lim_rcm = gastar(pend_gp, rcm, lim_rcm)
    if nuevas_rcm:
        pend_rcm[ejercicio] = nuevas_rcm
    if nuevas_gp:
        pend_gp[ejercicio] = nuevas_gp
    limpia = lambda p: {k: c2(v) for k, v in p.items() if v}
    return dict(base=c2(rcm + gp), rcm=c2(rcm), gp=c2(gp),
                pend_rcm=limpia(pend_rcm), pend_gp=limpia(pend_gp),
                caducadas=limpia(caducadas))


# Caso práctico del manual de la AEAT (Renta 2025, capítulo 12)
aeat = compensar(rcm=-800, gp=5600 - 1600,
                 pend_rcm={2021: 500}, pend_gp={2021: 700, 2022: 2100},
                 ejercicio=2025)
print("Base del ahorro:", aeat["base"])
print("RCM negativos de 2021 que quedan:", aeat["pend_rcm"][2021])
```
```output
Base del ahorro: 200.00
RCM negativos de 2021 que quedan: 300.00
```

Coincide: 800 euros de rendimientos negativos del año compensados dentro del límite de 1.000 (el 25 % de 4.000),
2.800 de pérdidas pendientes contra las ganancias y solo 200 de los 500 de rendimientos negativos de 2021, porque el
25 % ya estaba casi agotado. Los 300 restantes pasan al año siguiente.

Con todas las piezas, la liquidación de la base del ahorro del registro sintético, con pérdidas pendientes de 2021
(500 euros) y 2022 (1.000):

```python
def liquidar(motor, pend_rcm, pend_gp):
    r = rendimientos(motor)
    gp = sum((i for _, _, i, _ in motor.gp), D(0))
    comp = compensar(r["bruto"], gp, pend_rcm, pend_gp,
                     motor.ejercicio)
    base = comp["base"]
    cuota, filas = cuota_ahorro(base)
    tme = (cuota / base * 100).quantize(D("0.01")) if base else D(0)
    ddi = min(r["admisible"], c2(r["base_ext"] * tme / 100))
    liquida = cuota - ddi
    return dict(saldo_gp=gp, saldo_rcm=r["bruto"], base=base,
                filas=filas, cuota=cuota, tme=tme, ddi=ddi,
                liquida=liquida, retenciones=r["retencion_es"],
                diferencial=liquida - r["retencion_es"],
                pendientes=comp["pend_gp"], caducadas=comp["caducadas"])


liq = liquidar(m, pend_rcm={}, pend_gp={2021: 500, 2022: 1000})
for k in ("saldo_gp", "saldo_rcm", "base"):
    print(f"{k:<12}{liq[k]:>11,.2f}")
for desde, hasta, tipo, cuota in liq["filas"]:
    print(f"  {desde:>7,.0f} a {hasta:>9,.2f}"
          f"  {tipo:.0%}{cuota:>10,.2f}")
print(f"{'cuota':<12}{liq['cuota']:>11,.2f}")
print(f"{'TME':<12}{liq['tme']:>10} %")
for k in ("ddi", "liquida", "retenciones", "diferencial"):
    print(f"{k:<12}{liq[k]:>11,.2f}")
for k in ("caducadas", "pendientes"):
    años = ", ".join(f"{a}: {v:,.2f}" for a, v in liq[k].items())
    print(f"{k:<12}{años or 'ninguna'}")
```
```output
saldo_gp      61,237.85
saldo_rcm      1,700.00
base          61,937.85
        0 a  6,000.00  19%  1,140.00
    6,000 a 50,000.00  21%  9,240.00
   50,000 a 61,937.85  23%  2,745.71
cuota         13,125.71
TME              21.19 %
ddi              180.00
liquida       12,945.71
retenciones       95.00
diferencial   12,850.71
caducadas   2021: 500.00
pendientes  ninguna
```

Las pérdidas de 2021 caducan: su plazo terminó en 2025. Las de 2022 se compensan enteras contra las ganancias de 2026,
el último año en que podían usarse. La base del ahorro, 61.937,85 euros, cruza tres tramos; el tipo medio es del
21,19 %, y la deducción por doble imposición, 180 euros (el límite del convenio, menor que el 21,19 % de 1.200).

Un motor fiscal sin pruebas es una opinión. Las que siguen fijan cada cifra calculada a mano en las secciones
anteriores, al estilo de pytest (`assert` desnudos dentro de funciones `test_`), y se ejecutan con un bucle para no
depender de un fichero aparte:

```python
def gp_de(motor, activo):
    return [i for _, a, i, _ in motor.gp if a == activo]


def test_escala_coincide_con_el_boe():
    # cuota acumulada de la tabla del art. 66.2 (estatal + autonómica)
    for base, cuota in [(6000, 1140), (50000, 10380),
                        (200000, 44880), (300000, 71880)]:
        assert cuota_ahorro(base)[0] == cuota


def test_fifo_ignora_el_exchange():
    assert gp_de(m, "BTC")[0] == D("-1516.50")    # 7.492,5 - 9.009
    assert gp_de(mal, "BTC")[0] == D("-515.50")   # el error


def test_permuta_usa_el_mayor_valor():
    assert gp_de(m, "BTC")[1] == D("596.00")      # 4.600 - 8.008/2
    assert gp_de(m, "ETH") == [D("115.02")]       # 1.648,35 - 4.600/3


def test_recompra_en_dos_meses_difiere_la_perdida():
    assert gp_de(m, "BETA") == [D("0.00")]        # 2.010 diferidos
    assert gp_de(m, "GAMMA") == [D("-1006.67")]   # 1/3 diferido


def test_unica_compra_previa_sin_titulos_no_es_recompra():
    assert gp_de(m, "EPSI") == [D("-207.50")]


def test_venta_definitiva_libera_la_perdida():
    assert gp_de(m, "DELTA") == [D("0.00"), D("790.00"),
                                 D("-2010.00")]


def test_compensacion_como_el_manual_de_la_aeat():
    assert aeat["base"] == 200
    assert aeat["pend_rcm"] == {2021: 300}


def test_limite_del_25_por_ciento():
    r = compensar(rcm=1000, gp=-600, pend_rcm={}, pend_gp={},
                  ejercicio=2026)
    assert r["base"] == 750 and r["pend_gp"] == {2026: 350}


def test_dividendos_y_convenio():
    assert rendimientos(m)["admisible"] == 180   # 120 + 15 % de 400
    assert liq["ddi"] == 180


def test_liquidacion_completa():
    assert liq["base"] == D("61937.85")
    # 1.140 + 9.240 + 23 % de 11.937,85
    assert liq["cuota"] == D("13125.71")
    assert liq["diferencial"] == D("12850.71")


pruebas = [f for n, f in list(globals().items())
           if n.startswith("test_")]
for prueba in pruebas:
    prueba()
print(f"{len(pruebas)} pruebas superadas")
```
```output
10 pruebas superadas
```

## Modelos 720 y 721: informar no es tributar

La lección 4.4.1 explica cuándo hay que presentar los modelos 720 (bienes y derechos en el extranjero) y 721 (monedas
virtuales custodiadas en el extranjero): umbral de 50.000 euros por bloque a 31 de diciembre, nueva declaración con un
incremento superior a 20.000 y plazo del 1 de enero al 31 de marzo (RD 1065/2007, arts. 42 ter y 42 quater; Órdenes
HAP/72/2013 y HFP/886/2023; el 721 se presentó por primera vez por el ejercicio 2023)[^10]. Aquí importa su relación
con el impuesto:

- **No liquidan nada.** Son declaraciones informativas. Las ganancias, pérdidas y dividendos de esos bienes se
  declaran en el IRPF como cualquier otros, con las reglas de esta lección.
- **El régimen de 2012 se corrigió en 2022.** La sentencia del Tribunal de Justicia de la UE de 27 de enero de 2022
  (asunto C-788/19) declaró contrarios al Derecho de la Unión aspectos del régimen asociado al modelo 720; la Ley
  5/2022 modificó en consecuencia la disposición adicional decimoctava de la Ley General Tributaria y el art. 39 de la
  Ley del IRPF[^10].
- **Lo que queda.** Según el art. 39 vigente, los bienes cuya tenencia no se corresponda con la renta o el patrimonio
  declarados son ganancias patrimoniales no justificadas que se integran en la **base general** del periodo en que se
  descubran, salvo que el contribuyente pruebe que los tenía desde antes del periodo de prescripción. Un historial de
  operaciones completo, como el registro que alimenta el motor, es también la prueba del origen.

Lo que el motor de la lección no hace, para que nadie lo confunda con un programa de declaración: no calcula la base
general ni el mínimo personal, no modela derivados, préstamos de valores, escisiones, ampliaciones, derechos de
suscripción ni fondos de inversión (que tienen su propio régimen de traspasos), no convierte divisas y no sabe nada
de la normativa foral ni de los no residentes.

## Ejercicios

1. Repite la liquidación suponiendo que el bróker tenía el W-8BEN también para el dividendo de USBB (retención del
   15 %). ¿Cambia lo que pagas en España? ¿Cuánto cuesta no haberlo presentado?

**Solución.**

```python
con_w8 = [o if o.activo != "USBB" else
          op("2026-09-30", "dividendo", "USBB", 0, "400", "B2",
             retencion_ext=D(60), tipo_convenio=D("0.15"))
          for o in REG]
m2 = Motor(con_w8, 2026).procesar()
liq2 = liquidar(m2, pend_rcm={}, pend_gp={2021: 500, 2022: 1000})
filas = [("Retenido en EE. UU.", rendimientos(m)["retenido_ext"],
          rendimientos(m2)["retenido_ext"]),
         ("Deducción en España", liq["ddi"], liq2["ddi"]),
         ("Cuota diferencial", liq["diferencial"], liq2["diferencial"])]
print(f"{'':<20}{'sin W-8BEN':>12}{'con W-8BEN':>12}")
for nombre, sin, con in filas:
    print(f"{nombre:<20}{sin:>12,.2f}{con:>12,.2f}")
```
```output
                      sin W-8BEN  con W-8BEN
Retenido en EE. UU.       240.00      180.00
Deducción en España       180.00      180.00
Cuota diferencial      12,850.71   12,850.71
```

Lo que se paga en España no cambia: en los dos casos se deducen 180 euros. Lo que cambia es lo retenido en EE. UU.:
60 euros más sin el formulario, que no se recuperan en la declaración española y solo pueden reclamarse a la
administración de EE. UU. Es el 15 % de cada dividendo que se cobre sin W-8BEN en vigor.

2. Escribe una comprobación previa a la orden: antes de vender con pérdida un valor cotizado, lista las compras de los
   dos meses anteriores y la fecha hasta la que no conviene recomprar. Pruébala con GAMMA el 10 de noviembre de 2026.

**Solución.**

```python
def aviso_recompra(registro, activo, fecha):
    f = date.fromisoformat(fecha)
    previas = [o for o in registro if o.tipo == "compra"
               and o.activo == activo and f - DOS_MESES <= o.fecha < f]
    return previas, f + DOS_MESES


previas, hasta = aviso_recompra(REG, "GAMMA", "2026-11-10")
for o in previas:
    print(f"Compra previa: {o.fecha} {o.cantidad} títulos")
print("Sin recompras hasta el", hasta, "para no diferir la pérdida")
```
```output
Compra previa: 2026-10-20 100 títulos
Sin recompras hasta el 2027-01-10 para no diferir la pérdida
```

La compra del 20 de octubre cae dentro de los dos meses anteriores, así que una venta con pérdida el 10 de noviembre
quedaría diferida en la parte que esa compra cubre (hasta el saldo que quede tras vender). Es un aviso, no el cálculo
completo: la excepción de la compra única y las compras ya usadas como recompra las decide `Motor.recompras`. En un
sistema real, la comprobación va en el control de riesgo previo a la orden (lección 4.5.1), junto a los límites.

3. Vendes con pérdida unas acciones cotizadas el 15 de diciembre de 2026 y vuelves a comprarlas el 20 de enero de
   2027. ¿En qué declaración aparece la pérdida y qué datos necesita el motor para saberlo?

**Solución.**

No aparece en la de 2026: hay una compra homogénea dentro de los dos meses posteriores, así que la pérdida se difiere
y se integrará el año en que se vendan de forma definitiva las acciones recompradas en enero. Para saberlo, el motor
tiene que leer las operaciones hasta el 15 de febrero de 2027 al calcular 2026. Un cierre del ejercicio que solo mira
el año natural declararía una pérdida que no se puede computar.

[^1]: Ley 35/2006, del IRPF, arts. 25, 33.5, 35, 37, 46, 49, 66, 76, 80 y 101.4; arts. 66 y 76 en la redacción de la
    Ley 7/2024 (efectos desde el 1 de enero de 2025). Texto consolidado del
    [BOE](https://www.boe.es/buscar/act.php?id=BOE-A-2006-20764), última actualización publicada el 07/10/2026,
    consultado el 23/10/2026.
[^2]: DGT, consultas vinculantes [V1604-18](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V1604-18)
    (11/06/2018), [V0975-22](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V0975-22) (04/05/2022) y
    [V1550-25](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V1550-25) (03/09/2025), leídas el
    23/10/2026.
[^3]: DGT, consulta vinculante [V0999-18](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V0999-18)
    (18/04/2018), leída el 23/10/2026.
[^4]: DGT, consultas vinculantes [V5316-26](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V5316-26)
    (28/07/2026), [V0754-26](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V0754-26) (06/04/2026) y
    [V0089-26](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V0089-26) (20/01/2026), leídas el
    23/10/2026.
[^5]: Convenio entre el Reino de España y los Estados Unidos de América para evitar la doble imposición, de 22 de
    febrero de 1990, arts. 10 y 24, texto consolidado con el Protocolo de 14 de enero de 2013 en el
    [BOE](https://www.boe.es/buscar/act.php?id=BOE-A-1990-30940) (Protocolo:
    [BOE-A-2019-15166](https://www.boe.es/diario_boe/txt.php?id=BOE-A-2019-15166)), consultado el 23/10/2026.
[^6]: IRS, [Instructions for Form W-8BEN](https://www.irs.gov/instructions/iw8ben) (revisión de octubre de 2021) y
    [NRA withholding](https://www.irs.gov/individuals/international-taxpayers/nra-withholding), consultadas el
    23/10/2026.
[^7]: AEAT, Manual práctico de Renta 2025, capítulo 18, [deducción por doble imposición
    internacional](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/irpf-2025/c18-cuota-liquida-resultante-autoliquidacion/deducciones-cuota-liquida-total/deduccion-doble-imposicion-internacional/objeto-regimen-general-deduccion.html),
    consultado el 23/10/2026.
[^8]: DGT, consulta vinculante [V5381-26](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V5381-26)
    (28/07/2026), leída el 23/10/2026. Su caso es un convenio distinto (Panamá); el criterio que se cita es el general
    sobre el art. 80.
[^9]: AEAT, Manual práctico de Renta 2025, capítulo 12: [integración y compensación en la base del
    ahorro](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/irpf-2025/c12-integracion-compensacion-rentas/reglas-integracion-compensacion-rentas/integracion-compensacion-rentas-base-imponible-ahorro.html)
    y [caso
    práctico](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/irpf-2025/c12-integracion-compensacion-rentas/caso-practico.html),
    consultados el 23/10/2026.
[^10]: Real Decreto 1065/2007, arts. 42 ter y 42 quater, texto consolidado en el
    [BOE](https://www.boe.es/buscar/act.php?id=BOE-A-2007-15984); Orden HAP/72/2013
    ([BOE-A-2013-954](https://www.boe.es/eli/es/o/2013/01/30/hap72/con)); Orden HFP/886/2023
    ([BOE-A-2023-17429](https://www.boe.es/eli/es/o/2023/07/26/hfp886)); Ley 5/2022, preámbulo y disposiciones finales
    cuarta y quinta ([BOE-A-2022-3712](https://www.boe.es/eli/es/l/2022/03/09/5)). Consultados el 23/10/2026.

## Autoevaluación

1. Con una base liquidable del ahorro de 75.000 euros en 2026, ¿cuál es la cuota íntegra (estatal más autonómica)?

   - A. 14.250 euros: el 19 % de toda la base
   - B. 16.130 euros: 1.140 + 9.240 + 5.750, cada tramo a su tipo
   - C. 17.250 euros: el 23 % de toda la base, porque el último euro tributa al 23 %
   - D. 22.500 euros: el 30 %, el tipo máximo

   *Respuesta B: 16.130 euros: 1.140 + 9.240 + 5.750, cada tramo a su tipo.* La escala es progresiva por tramos: 6.000 euros al 19 %, 44.000 al 21 % y los 25.000 restantes al 23 %. El tipo marginal es el 23 %, pero el medio es el 21,51 %. Aplicar el marginal a toda la base es el error más común al estimar el impuesto de una estrategia.

2. Vendes con pérdida el 11 de mayo de 2026 acciones cotizadas que tenías desde 2025 y compras las mismas acciones el 25 de junio. ¿Qué pasa con la pérdida?

   - A. Se integra en 2026 porque la venta fue anterior a la compra
   - B. Se pierde para siempre
   - C. Se integra en 2026 si la recompra es de otro bróker
   - D. No se computa en 2026: se integrará cuando vendas de forma definitiva las acciones recompradas

   *Respuesta D: No se computa en 2026: se integrará cuando vendas de forma definitiva las acciones recompradas.* El art. 33.5 f) impide computar la pérdida si se adquieren valores homogéneos dentro de los dos meses anteriores o posteriores a la venta, y dice que se integrará a medida que se transmitan los valores que permanecen. Es lo que hace el motor con BETA: 2.010 euros diferidos que viajan con el lote recomprado.

3. Compraste 0,1 BTC en un exchange en febrero de 2025 y otros 0,1 BTC en otro exchange en diciembre. En marzo de 2026 vendes 0,1 BTC en el segundo. ¿Qué valor de adquisición usas?

   - A. El de febrero de 2025: FIFO sobre todos los BTC, sin distinguir la plataforma
   - B. El de diciembre, porque la venta se hizo en ese exchange
   - C. La media de los dos
   - D. El que elijas, siempre que lo mantengas

   *Respuesta A: El de febrero de 2025: FIFO sobre todos los BTC, sin distinguir la plataforma.* La DGT aplica a las criptomonedas homogéneas el criterio del art. 37.2: se venden las adquiridas en primer lugar, y la plataforma no rompe la homogeneidad (V1604-18, V0975-22, V1550-25). En el registro de la lección, el FIFO por exchange da una pérdida de 515,50 euros en lugar de 1.516,50.

4. Un dividendo de 400 euros de una sociedad de EE. UU. llega con un 30 % retenido porque el bróker no tenía el formulario W-8BEN. ¿Cuánto puedes deducir en España por doble imposición?

   - A. Los 120 euros retenidos
   - B. Nada, porque no presentaste el W-8BEN
   - C. Como máximo 60 euros: el 15 % que permite el convenio; el exceso se reclama a la administración de EE. UU.
   - D. El 19 % del dividendo

   *Respuesta C: Como máximo 60 euros: el 15 % que permite el convenio; el exceso se reclama a la administración de EE. UU.* El art. 80 de la Ley del IRPF deduce lo efectivamente satisfecho fuera con el límite del tipo medio, y la DGT entiende por satisfecho el importe que el otro Estado puede aplicar según el convenio (V5381-26). El convenio con EE. UU. limita al 15 % el impuesto sobre dividendos de un particular.

5. En 2026 el saldo de ganancias y pérdidas es de –600 euros y el de dividendos e intereses de +1.000 euros. ¿Qué ocurre?

   - A. Se compensan los 600: la base del ahorro es de 400 euros
   - B. Se compensan 250 euros (el 25 % de 1.000); los 350 restantes se arrastran hasta cuatro años
   - C. No se compensan: ganancias y rendimientos nunca se mezclan
   - D. Se compensan contra la base general

   *Respuesta B: Se compensan 250 euros (el 25 % de 1.000); los 350 restantes se arrastran hasta cuatro años.* El art. 49 permite compensar el saldo negativo de un bloque con el positivo del otro, con el límite del 25 % de ese saldo positivo. Lo que quede se compensa en los cuatro años siguientes en el mismo orden. Es la prueba `test_limite_del_25_por_ciento`.

## Ideas clave

- La base del ahorro de 2026 tributa por tramos al 19, 21, 23, 27 y 30 % (mitad estatal y mitad autonómica, arts. 66 y 76; territorio común). Con 300.000 euros de base, el tipo medio es del 23,96 %.
- FIFO es la regla legal para valores homogéneos (art. 37.2) y la que aplica la DGT a las criptomonedas, sobre todas las unidades y sin separar por plataforma. Una permuta entre criptomonedas es una transmisión: se valora por el mayor de los dos valores de mercado.
- Una pérdida en valores cotizados no se computa si hay compras homogéneas dos meses antes o después; se integra cuando se venden los títulos recomprados. Un motor que no lo modele adelanta pérdidas que no son deducibles.
- Dividendos e intereses por un lado y ganancias y pérdidas por otro: cada saldo negativo compensa el positivo del otro solo hasta el 25 %, y lo pendiente caduca a los cuatro años.
- La deducción por doble imposición es la menor de lo pagado fuera (dentro de lo que permite el convenio: 15 % para dividendos de EE. UU.) y del tipo medio aplicado a esa renta. Sin W-8BEN, EE. UU. retiene el 30 % y la diferencia no se recupera en España.
- Los modelos 720 y 721 informan, no liquidan: no cambian la tributación de las ganancias, pero su omisión deja bienes sin justificar.

## Recursos

### Documentación

- [Ley 35/2006 del IRPF, texto consolidado (BOE)](https://www.boe.es/buscar/act.php?id=BOE-A-2006-20764) · boe.es
- [AEAT, Manual práctico de Renta 2025: integración y compensación de rentas en la base imponible del ahorro](https://sede.agenciatributaria.gob.es/Sede/ayuda/manuales-videos-folletos/manuales-practicos/irpf-2025/c12-integracion-compensacion-rentas/reglas-integracion-compensacion-rentas/integracion-compensacion-rentas-base-imponible-ahorro.html) · sede.agenciatributaria.gob.es
- [DGT, consulta vinculante V1550-25: FIFO en criptomonedas sin separar por plataforma](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V1550-25) · petete.tributos.hacienda.gob.es
- [DGT, consulta vinculante V5316-26: cómo se aplica la regla de los dos meses](https://petete.tributos.hacienda.gob.es/consultas/?num_consulta=V5316-26) · petete.tributos.hacienda.gob.es
- [Convenio entre España y EE. UU. para evitar la doble imposición, texto consolidado con el Protocolo de 2013 (BOE)](https://www.boe.es/buscar/act.php?id=BOE-A-1990-30940) · boe.es
- [IRS: Instructions for Form W-8BEN](https://www.irs.gov/instructions/iw8ben) · irs.gov

Lección anterior: [7.4.5 · Abuso de mercado: spoofing, layering y el bot que los imita sin querer](https://pythonparatrading.com/curso-python-trading/nivel-7/abuso-de-mercado-spoofing-y-bots/)

Lección siguiente: [7.4.7 · Ética: datos personales, inteligencia artificial y la venta de señales](https://pythonparatrading.com/curso-python-trading/nivel-7/etica-datos-personales-ia-y-senales/)
