“Di seguito la procedura manuale/algoritmica che seguirei per il calcolo LIFO: è scomoda da fare a mano ma implementabile via DB. Politica fee: [A/C]. Metodo bollo: [31/12 o Media]. Base giorni: [360/365].”
Lunga da leggere ma sicuramente interessante.
========
Procedura completa LIFO per plus/minusvalenze, giorni di detenzione e imposta 0,2%
0) Scopo e convenzioni
Obiettivi: calcolare (a) plus/minusvalenze su cessioni (incluse crypto?crypto), (b) giorni di detenzione dei lotti ceduti, (c) base imponibile per imposta 0,2% (“bollo patrimoniale”) su cripto e saldi fiat/stablecoin.
Valuta: tutte le valorizzazioni in EUR alla data dell’operazione o del giorno di riferimento.
Fee: scegliere una politica unica (vedi §5) e mantenerla in tutto il periodo.
LIFO: consumo dei lotti dai più recenti verso i meno recenti.
Periodo di calcolo: risultati per un intervallo [DataInizio; DataFine], attingendo a lotti acquistati anche prima.
Booleani Access: usare TRUE/FALSE (non “Sì/No”).
---
1) Ingest, pulizia e normalizzazione
1.1 Sorgente dati
Usare i dati consolidati (es. TATAX via API/CSV) dentro una tabella di staging (es. [tblImportTataxRaw]). Per ora il progetto lavora solo su TATAX (come deciso).
1.2 Deduplica deterministica
Identifica duplicati per chiavi operative (suggerito):
[Criptovaluta], [MovementType], [Quantita], [ControvaloreEUR], [CommissioniEUR], [DataOraTransazione], [TipoOperazione], [Exchange].
Regola: tieni la riga con [IDTransazione] più basso e marca le altre con [EscludiDalCalcolo]=TRUE.
Se esistono “falsi duplicati” (stessi dati ma fee diversa), tieni quella con fee maggiore (più prudente) e marca l’altra.
1.3 Mappatura campi minimi per la “query base” (es. [qryTransazioni])
Per ogni movimento non escluso:
[IDTransazione] (chiave)
[DataOraTransazione] (timezone coerente)
[Criptovaluta]
[MovementType]: CREDIT / DEBIT
[Quantita] (sempre positiva)
[ControvaloreEUR] (se non fornito: prezzo×quantità×cambio?EUR)
[CommissioniEUR] (se fee in cripto: valorizzare in EUR alla stessa data)
[TipoOperazione] (acquisto, vendita, crypto?crypto, stake, airdrop, trasferimento, fee, ecc.)
[Exchange], [Note] (facoltativi)
[EscludiDalCalcolo] (TRUE/FALSE)
1.4 Classificazione rilevanza fiscale
Rilevanti (disposal): vendite verso fiat; crypto?crypto (cessione dell’asset A); spese contro beni/servizi.
Non rilevanti: trasferimenti interni; movimenti tecnici; rettifiche senza cambio proprietà.
Entrate tipo reddito (stake, airdrop): generano CREDIT e nuovi lotti (vedi §6).
---
2) Costruzione dei lotti disponibili (da CREDIT)
Per ogni riga CREDIT che genera giacenza:
[IDLotto] (ID interno)
[Criptovaluta]
[DataAcquisto] = [DataOraTransazione]
[QtaTotale] (netta se sconti fee qui; altrimenti lorda e fee separata, ma sii coerente)
[QtaResidua] = [QtaTotale]
[CostoTotaleEUR]
Opzione A (consigliata): ControvaloreEUR + CommissioniEUR (fee come costo accessorio)
Opzione B: solo ControvaloreEUR (fee gestite altrove: sconsigliato)
[CostoUnitarioEUR] = [CostoTotaleEUR] / [QtaTotale]
[IDTransazioneCREDIT] (riferimento alla riga sorgente)
> Crypto?crypto: la ricezione della B crea un CREDIT B con costo pari al valore EUR della B al momento dello scambio (di norma uguale al corrispettivo della cessione di A, al netto/ lordo fee secondo la tua politica). Vedi §6.
---
3) Consumo LIFO dei lotti (su DEBIT)
Per ogni riga DEBIT della [Criptovaluta] X nel periodo:
1. QtaDaVendere = [Quantita] del DEBIT.
2. CorrispettivoTotaleEUR:
se verso fiat: ControvaloreEUR (eventualmente - CommissioniEUR se adotti Opzione C, vedi §5)
se crypto?crypto: valore EUR dell’asset ricevuto (al netto/ lordo fee secondo politica).
3. Applica LIFO: prendi i lotti più recenti di X con [QtaResidua] > 0 e scala finché QtaDaVendere=0:
QtaAbbinata = min(QtaDaVendere, QtaResidua del lotto)
CostoAbbinatoEUR = QtaAbbinata × [CostoUnitarioEUR] del lotto
GiorniDetenzione = differenza in giorni interi tra [DataAcquisto] del lotto e [DataVendita]=[DataOraTransazione] (se stessa data ? 0).
In Access: DateDiff("d", DateValue([DataAcquisto]), DateValue([DataVendita]))
Registra una riga in [tblRisultatiLIFO] (vedi §8) e aggiorna [QtaResidua] del lotto.
4. Ripartizione corrispettivo e fee pro-quota sugli abbinamenti (in base a QtaAbbinata).
---
4) Plus/minusvalenza per ogni abbinamento
Per ogni riga di abbinamento (lotto?vendita):
RicavoAbbinatoEUR = quota di CorrispettivoTotaleEUR ripartita pro-quota
(già ridotta dalle fee se usi Opzione C).
CostoAbbinatoEUR = QtaAbbinata × CostoUnitario (+ quota fee se usi Opzione A).
PlusMinusAbbinataEUR = RicavoAbbinatoEUR - CostoAbbinatoEUR.
Conserva [GiorniDetenzione].
Somme richieste:
per [IDTransazioneDEBIT]
per [Criptovaluta] e Periodo
totale complessivo del periodo.
---
5) Politica sulle commissioni (scegline una e mantienila)
Opzione A (consigliata): fee come costo accessorio (acquisto e vendita) ? aggiungi la quota fee a CostoAbbinatoEUR.
Opzione C: fee come riduzione del corrispettivo ? sottrai dal CorrispettivoTotaleEUR prima della ripartizione.
Opzione B (fee a parte) è sconsigliata per coerenza fiscale.
Nota: A e C portano allo stesso effetto netto sulla plus/minus; differisce la presentazione.
---
6) Casi particolari
Crypto?crypto: sempre due movimenti logici:
(1) DEBIT A (disposal rilevante) con corrispettivo = valore EUR dell’asset ricevuto B (gestione fee secondo §5).
(2) CREDIT B con costo di carico = stesso valore EUR (più fee lato acquisto se A).
Trasferimenti interni: non sono disposal; non consumano lotti. Le fee di rete, se presenti, possono essere registrate come costo ma non generano cessione.
Staking/airdrop/reward: generano CREDIT e nuovi lotti. Costo iniziale:
Valore normale di mercato (EUR) alla data di accredito (più rigoroso), oppure
0 EUR (più semplice ma impatta le plus future).
Scegline uno e resta coerente.
Fork: crea nuovi lotti con costo definito da policy (spesso 0 o primo prezzo disponibile).
---
7) Filtri di periodo e riporti
Nel PeriodoCalcolo considera solo i DEBIT con data dentro [DataInizio; DataFine].
I CREDIT antecedenti restano disponibili per essere consumati (LIFO).
Le giacenze finali al 31/12 (o a DataFine) sono i lotti iniziali dell’anno/periodo successivo (stesso [QtaResidua] e [CostoUnitarioEUR]).
---
8) Struttura tabelle consigliata (minimale)
8.1 [qryTransazioni] (o tabella normalizzata equivalente)
[IDTransazione], [DataOraTransazione], [Criptovaluta], [MovementType] (CREDIT/DEBIT)
[Quantita], [ControvaloreEUR], [CommissioniEUR], [TipoOperazione], [Exchange], [Note]
[EscludiDalCalcolo] (TRUE/FALSE), [RilevanteFiscale] (TRUE/FALSE)
8.2 [tblLottiDisponibili]
[IDLotto] (PK), [IDTransazioneCREDIT], [Criptovaluta], [DataAcquisto]
[QtaTotale], [QtaResidua], [CostoTotaleEUR], [CostoUnitarioEUR]
8.3 [tblRisultatiLIFO] (dettaglio abbinamenti lotto?vendita)
[IDRisultato] (PK), [IDTransazioneDEBIT], [IDLotto], [Criptovaluta]
[DataAcquisto], [DataVendita], [GiorniDetenzione]
[QtaAbbinata], [CostoAbbinatoEUR], [RicavoAbbinatoEUR], [PlusMinusAbbinataEUR]
8.4 [tblTipoOperazione] (lookup)
[IDTipo], [DescrizioneTipo], [RilevanteFiscale] (TRUE/FALSE)
(Se utile al programmatore, si può aggiungere [tblParametriCalcolo] con: [DataInizio], [DataFine], [FeePolicy] {A|C}, [BaseGiorni] {360|365}, [MetodoBollo] {31/12|Media}).
---
9) Output richiesti
9.1 Dettaglio abbinamenti (per audit)
Una riga per ogni consumo di lotto, con tutti i campi di [tblRisultatiLIFO].
9.2 Riepilogo per transazione di vendita (DEBIT)
Somma delle righe abbinate alla stessa [IDTransazioneDEBIT]:
Qta venduta, Ricavo totale, Costo totale, Plus/Minus, GiorniDetenzione medi (opzionale: media ponderata su QtaAbbinata).
9.3 Riepilogo per cripto e complessivo periodo
Per [Criptovaluta]: quantità vendute, costo, ricavo, plus/minus totali.
Totale periodo: PlusvalenzaNetta, Minusvalenze (riportabili secondo normativa vigente).
---
10) Calcolo dei giorni di detenzione (lotti ceduti)
Per ciascun abbinamento:
GiorniDetenzione = DateDiff("d", DateValue([DataAcquisto]), DateValue([DataVendita]))
(stessa data ? 0; non aggiungere +1).
Se serve una statistica: calcola media ponderata con pesi = [QtaAbbinata].
---
11) Valorizzazione patrimoniale per imposta 0,2%
> La base imponibile è il valore in EUR degli asset detenuti (cripto e saldi fiat/stablecoin). Due metodi operativi: istantanea 31/12 oppure media nel tempo.
11.1 Metodo “istantanea 31/12” (più semplice e diffuso)
1. Fotografa i saldi al 31/12 per ogni asset:
Fiat (EUR/USD...): il valore è l’ammontare convertito in EUR (USD×cambio EUR).
Stablecoin: quantità × prezzo in EUR (spesso ˜ 1 USD × cambio EUR).
Altre cripto: quantità × prezzo in EUR al 31/12 (fonte prezzi coerente).
2. Somma tutti i valori in EUR ? ValoreTotale_31_12.
3. Imposta 0,2% = ValoreTotale_31_12 × 0,002.
(La “foto” al 01/01 è utile per confronti e controlli ma non sempre necessaria ai fini dell’imposta.)
11.2 Metodo “media ponderata nel tempo”
1. Costruisci il saldo giornaliero per ciascun asset (quantità costante tra un evento e il successivo).
2. Per ogni giorno, valorizza in EUR (prezzo del giorno × quantità).
3. Somma i valori giornalieri e dividi per il n. di giorni del periodo ? ValoreMedioEUR.
4. Imposta 0,2% = ValoreMedioEUR × 0,002.
> Prezzi: usa una fonte unica e coerente (es. prezzi di chiusura UTC) per tutto l’anno.
11.3 Gestione cripto convertite in EUR durante l’anno
Dal giorno della conversione, la cripto diventa saldo fiat.
Ai fini del bollo: escludi dai saldi cripto e includi nei saldi fiat (ovviamente già in EUR o convertiti).
11.4 Regola dei 360 giorni (o 365) per la detenzione patrimoniale
Se vuoi/ devi proporzionare l’imposta ai giorni effettivi di possesso:
Per ogni asset/lotto ancora detenuto a fine periodo:
DataInizioDetenzione = data di acquisto/accredito (o 01/01 se precedente)
DataFineDetenzione = data di vendita/trasferimento o 31/12 se ancora in portafoglio
GiorniDetenuti = differenza in giorni (calendario)
Se GiorniDetenuti = 360 (o 365), l’asset è considerato detenuto l’intero anno.
Se < 360, applica una proporzione sul metodo prescelto:
Istantanea 31/12 (solo se richiesto il pro-rata):
ImpostaParziale = (Valore_31_12 × GiorniDetenuti / 360) × 0,002
Media nel tempo: la media giornaliera già riflette la durata di possesso; l’ulteriore pro-rata non serve, salvo diversa prassi.
> Nota pratica: molti software applicano semplicemente lo 0,2% sul 31/12 senza pro-rata; se vuoi aderire a una prassi specifica (es. TATAX), dichiarala esplicitamente nel thread.
---
12) Riconciliazioni e controlli qualità
Giacenze: somma [QtaResidua] per cripto = saldi finali (confronto con exchange).
Quantità: S CREDIT - S DEBIT = saldo netto.
Fee: somma fee per periodo e confronta con i report degli exchange.
Crypto?crypto: verifica che il CREDIT della ricevuta abbia costo = corrispettivo della ceduta (coerente con la tua politica fee).
---
13) Esempio numerico rapido
10/01: CREDIT BTC 0,4 @ 20?000€ = 8?000€; fee 20€ ? Costo 8?020€ (Opz. A) ? 20?050 €/BTC.
20/01: CREDIT BTC 0,3 @ 25?000€ = 7?500€; fee 15€ ? Costo 7?515€ ? 25?050 €/BTC.
25/01: DEBIT BTC 0,5 @ 30?000€ = 15?000€; fee 25€ ? (Opz. C) Ricavo netto 14?975€.
LIFO: consumo 0,3 (lotto 20/01) + 0,2 (lotto 10/01).
Riparto ricavo pro-quota:
0,3 ? 14?975×(0,3/0,5)= 8?985€; Costo 0,3×25?050= 7?515€ ? plus 1?470€ (5 gg)
0,2 ? 14?975×(0,2/0,5)= 5?990€; Costo 0,2×20?050= 4?010€ ? plus 1?980€ (15 gg)
Totale plus = 3?450€.
---
14) Checklist implementativa (per il programmatore)
1. Preparazione dati: creare [qryTransazioni] normalizzata e filtrata ([EscludiDalCalcolo]=FALSE, [RilevanteFiscale] flag da [tblTipoOperazione]).
2. Build lotti: popolare [tblLottiDisponibili] dai CREDIT (ordinati per [DataAcquisto]).
3. Loop DEBIT nel periodo: per ogni riga, scalare LIFO, scrivere in [tblRisultatiLIFO] gli abbinamenti con Ricavo/Costo/Plus/Giorni.
4. Riepiloghi: query di somma per transazione, cripto, totale periodo.
5. Bollo 0,2%:
Metodo 31/12: snapshot saldi (cripto+fiat) e prezzi 31/12 ? somma EUR ? ×0,002 (eventuale pro-rata 360 giorni se richiesto).
Metodo media: ledger giornaliero per asset ? valore medio EUR ? ×0,002.
6. Coerenza fee: applicare Opzione A oppure C in tutto il flusso.
7. Controlli: riconciliazioni su giacenze, quantità e fee.
---
15) Campi suggeriti (riassunto)
[qryTransazioni]: [IDTransazione], [DataOraTransazione], [Criptovaluta], [MovementType], [Quantita], [ControvaloreEUR], [CommissioniEUR], [TipoOperazione], [Exchange], [Note], [RilevanteFiscale], [EscludiDalCalcolo].
[tblLottiDisponibili]: [IDLotto], [IDTransazioneCREDIT], [Criptovaluta], [DataAcquisto], [QtaTotale], [QtaResidua], [CostoTotaleEUR], [CostoUnitarioEUR].
[tblRisultatiLIFO]: [IDRisultato], [IDTransazioneDEBIT], [IDLotto], [Criptovaluta], [DataAcquisto], [DataVendita], [GiorniDetenzione], [QtaAbbinata], [CostoAbbinatoEUR], [RicavoAbbinatoEUR], [PlusMinusAbbinataEUR].
[tblTipoOperazione]: [IDTipo], [DescrizioneTipo], [RilevanteFiscale] (TRUE/FALSE).