Utilizzare gli Analyzers

Il Backtesting di una Strategia di Trading Algoritmico – Parte I

Questo articolo continua la serie sul trading quantitativo, che è iniziato con il tutorial introduttivo e l’articolo sull’identificazione di una strategia. Entrambi questi articoli sono molti lunghi e dettagliati, quindi continuerò su questo tema e voglio fornire ulteriori dettagli relativi al backtesting di una strategia.

Il backtesting algoritmico richiede competenze in molte aree, tra cui psicologia, la matematica, la statistica, lo sviluppo software e la conoscenza della microstruttura del mercato (o exchange). Non è possibile coprire tutti questi argomenti in un solo articolo, quindi  dividerò la trattazione in due o tre parti. Si inizia definendo cosa si intende per backtesting per poi descrivere le basi del suo funzionamento. Quindi si evidenziano i bias, già discussi nella Guida introduttiva al Trading Algoritmico. Successivamente si confronta i vari software di backtest disponibili.

Negli articoli successivi esamineremo i dettagli delle implementazioni della strategia che sono spesso menzionati a malapena o del tutto ignorati. Si descrive anche come rendere più realistico il processo di backtest includendo le imperfezioni di un trading exchange. Quindi discuteremo i costi di transazione e come modellarli correttamente nel settaggio di backtest. Concluderemo con una discussione sull’esecuzione del backtesting e forniremo infine un esempio di una semplice strategia quantitativa, nota come mean-reverting pairs trade.

Iniziamo discutendo di cosa sia il backtesting e perché dovremmo prevederlo nel trading algoritmico.

Che cosa è il backtesting?

Il trading algoritmico si distingue dagli altri tipi di investimento perché si può fornire in modo più affidabile le aspettative sulle prestazioni future dell’attività di trading, derivanti dalle performance passate, come conseguenza dell’abbondante disponibilità di dati. Il processo con cui viene effettuato questo è noto come backtesting.

In termini semplici, il backtesting viene eseguito esponendo lo specifico algoritmo di una strategia a un flusso di dati finanziari storici, che restiuisce una serie di segnali di trading. Ogni trade (che qui intendiamo come un “round-trip” di due segnali) è associato ad un utile o ad una perdita. L’accumulo di questo profitto / perdita per tutta la durata del backtest della strategia porterà ad un profitto e una perdita totale (noto anche come “P & L” o “PnL”). Questa è l’essenza dell’idea, anche se ovviamente il “diavolo è sempre nei dettagli”!

Quali sono le motivazioni principali per cui si effettua il backtest di una strategia algoritmica?

  • Filtraggio – Come introdotto nell’articolo sull’identificazione della strategia, l’obiettivo della fase iniziale della ricerca consiste nell’impostare una pipeline strategica e quindi filtrare qualsiasi strategia che non soddisfacesse determinati criteri. Il backtesting ci fornisce un altro meccanismo di filtraggio, in quanto possiamo eliminare le strategie che non soddisfano i criteri in termini di prestazioni.
  • Modellazione – Backtesting ci consente di testare (in tutta sicurezza) i nuovi modelli di determinati fenomeni di mercato, i costi di transazione, il routing degli ordini, la latenza, la liquidità o altre inefficienze del mercato.
  • Ottimizzazione – Sebbene l’ottimizzazione della strategia sia ricca di bias, il backtesting ci consente di aumentare le prestazioni di una strategia modificando la quantità o i valori dei parametri associati a tale strategia e ricalcolandone le prestazioni.
  • Verifica – Le strategie vengono spesso acquistate esternamente, tramite la nostra pipeline strategica. Il backtesting di una strategia garantisce che non sia stato implementata in modo errato. Anche se raramente avremo accesso ai segnali generati da strategie esterne, avremo spesso accesso alle metriche prestazionali come il SharpeRatio e il Drawdown. Quindi possiamo confrontarli con la nostra implementazione.

 

Il backtesting offre una serie di vantaggi per il trading algoritmico. Tuttavia, non è sempre possibile eseguire direttamente il backtest di una strategia. In generale, con l’aumentare della frequenza della strategia, diventa più difficile modellare correttamente gli effetti della microstruttura del mercato e degli exchange. Ciò porta a backtest meno affidabili e quindi a una valutazione più complessa della strategia scelta. Questo è un particolare problema dove il sistema di esecuzione è la chiave per le prestazioni della strategia, come con algoritmi a frequenza ultraelevata.

Sfortunatamente, i backtest sono pieni di bias di tutti i tipi. Abbiamo toccato alcuni di questi problemi negli articoli precedenti, ma ora li discuteremo in modo approfondito.

 

I Bias che influenzano il Backtesting di una Strategia

Esistono numerosi bias che possono influire sulle prestazioni del backtesting di una strategia. Sfortunatamente, questi bias tendono a gonfiare la performance piuttosto che a diminuirla. Pertanto, si dovrebbe sempre considerare un backtest come un ideale limite superiore delle performance effettive della strategia. È quasi impossibile eliminare i bias dal trading algoritmico, quindi è compito dell’algotrader cercare di minimizzarli il più possibile in modo da prendere le decisioni corrette.

Ci sono quattro principali tipoliga di bias a cui prestare estrema attenzione: Optimisation BiasLook-Ahead BiasSurvivorship Biasand Psychological Tolerance Bias.

Optimisation Bias

Questo è probabilmente il più insidioso di tutti i bias a cui il backtesting è soggetto. Si tratta di adeguare o introdurre parametri aggiuntivi fino a quando la performance della strategia sul set di dati storico diventano interessanti. Tuttavia, una volta live, le prestazioni della strategia possono essere notevolmente diverse. Un altro nome per questo bias è “curve fitting” o “data-snooping bias”.

Il bias di ottimizzazione è difficile da eliminare in quanto le strategie algoritmiche spesso implicano molti parametri. In questo caso, i “Parametri” possono essere i criteri di ingresso / uscita, i periodi di osservazione, i periodi di calcolo della media (ovvero il parametro di livellamento della media mobile) o la frequenza di misurazione della volatilità. Il bias di ottimizzazione può essere ridotto al minimo mantenendo il numero di parametri al minimo e aumentando la quantità di dati nel set di allenamento. In effetti, si deve anche fare attenzione a questi ultimi poiché i dati storici più vecchi possono essere soggetti a un regime precedente (come un obbligo normativo) e quindi potrebbero non essere rilevanti per l’attuale strategia.

Un metodo per attenuare questo bias consiste nell’eseguire una sensitivity analysis. Questa analisi consiste nel variare i parametri in modo incrementale e tracciare una “superficie” di prestazioni. In particolare, il ragionamento fondamentale per le scelte dei parametri dovrebbe, insieme a tutti gli altri fattori considerati, portare ad una superficie dei parametri più liscia. Se si dispone di una superficie di prestazione molto nervosa, spesso significa che un parametro non riflette un fenomeno ed è un artefatto dei dati del test. Esiste una vasta letteratura sugli algoritmi di ottimizzazione multidimensionale ed è un’area di ricerca molto attiva. Non mi soffermerò su di esso in questo articolo, ma tienilo a mente quando trovi una strategia con un fantastico backtest!

Look-Ahead Bias

Il bias di previsione viene introdotto in un sistema di backtesting quando i dati futuri vengono accidentalmente inclusi in un punto della simulazione in cui tali dati non sarebbero stati effettivamente disponibili. Se stiamo eseguendo il backtest in ordine cronologico e raggiungiamo il punto temporale N, il bias di look-ahead si verifica quando sono utilizzati i dati relativi a qualsiasi instante N + k, dove k > 0. Gli errori del bias di previsione possono essere incredibilmente insidiosi. Ecco tre esempi di come si può introdurre un bias di previsione:

  • Bug tecnici: gli array / i vettori nel codice hanno spesso iteratori o variabili dell’indice. Offset errati di questi indici possono portare a una distorsione look-ahead, incorporando dati a N + k per k>0.
  • Calcolo dei parametri – Un altro esempio comune di bias di previsione si verifica quando si calcolano i parametri ottimali di una strategia, ad esempio con le regressioni lineari tra due serie temporali. Se l’intera serie di dati (compresi i dati futuri) viene utilizzata per calcolare i coefficienti di regressione, e quindi applicata retroattivamente a una strategia di trading a fini di ottimizzazione, i dati futuri verranno incorporati e si verificherà un bias di previsione.
  • Maxima / Minima – Alcune strategie di trading fanno uso di valori estremi in un determinato periodo di tempo, come l’incorporazione dei prezzi massimi o minimi nei dati OHLC. Tuttavia, poiché questi valori massimi / minimi possono essere calcolati solo alla fine del periodo di tempo di riferimento, viene introdotto un bias di previsione se questi valori vengono utilizzati durante il periodo corrente. È sempre necessario ritardare i valori di almeno un punto per farne uso in qualsiasi strategia di trading.

 

Come nel caso dell’ottimizzazione, bisogna essere estremamente cauti per evitare la sua introduzione. Spesso è la ragione principale per cui le strategie di trading sottoperformano significativamente i loro backtests nel “trading dal vivo”.

Survivorship Bias

Il bias di sopravvivenza è un fenomeno particolarmente pericoloso e può portare a prestazioni notevolmente gonfiate per determinati tipi di strategie. Si verifica quando le strategie vengono testate su set di dati che non includono l’intero universo di asset precedenti che potrebbero essere stati scelti in un determinato momento, ma considerano solo quelli che sono “sopravvissuti” fino al tempo corrente.

Ad esempio, si consideri di testare una strategia su una selezione casuale di azioni prima e dopo il crollo del mercato del 2001. Alcuni titoli tecnologici sono andati in bancarotta, mentre altri sono riusciti a rimanere a galla e persino a prosperare. Se avessimo limitato questa strategia solo alle azioni che hanno superato il periodo di abbattimento del mercato, avremmo introdotto un bias di sopravvivenza perché si effettua il backtesting solamente per le azioni che hanno già dimostrato il loro successo. In realtà, questo è solo un altro caso specifico di distorsione previsionale, poiché le informazioni future vengono incorporate nell’analisi passata.

Esistono due modi principali per mitigare i bias di sopravvivenza nei backtests delle strategie:

  • Set di dati senza bias di sopravvivenza – Nel caso di dati azionari è possibile acquistare set di dati che includono entità rimosse, sebbene non siano a buon mercato e tendano ad essere utilizzate solo da aziende istituzionali. In particolare, i dati di Yahoo Finance NON sono privi di bias, ciò nonostante vengono comunemente usato da molti algotrader retail. Si può anche operare su strumenti che non sono inclini al biasdi sopravvivenza, come certe materie prime (e i loro futures derivati​).
  • Usare dati recenti – Nel caso di titoli azionari, l’utilizzo di un set di dati più recente riduce la possibilità che la selezione di azioni scelta sia ponderata ai soli “sopravvissuti”, semplicemente perché vi è meno probabilità di un delisting delle azioni in brevi periodi. Si può anche iniziare a costruire un personale set di dati libero da bias di sopravvivenza, raccogliendo dati dal tempo corrente in poi. Dopo 3-4 anni, avrai un solido set di dati senza bias con cui testare altre strategie.

 

Considereremo ora alcuni fenomeni psicologici che possono influenzare le prestazioni del trading.

Psychological Tolerance Bias

Questo particolare fenomeno non è spesso discusso nel contesto del trading quantitativo. Tuttavia, è ampiamente discusso in merito a metodi di trading più discrezionali. Ha vari nomi, ma ho deciso di chiamarlo “bias di tolleranza psicologica” perché cattura l’essenza del problema. Quando si creano backtests su un periodo di 5 o più anni, è facile guardare una curva equity tendente al rialzo, calcolare il rendimento annuale composto, il SharpeRatio e persino le caratteristiche del drawdown e essere soddisfatti dei risultati. Ad esempio, la strategia potrebbe avere un drawdown relativo massimo del 25% e una durata massima di drawdown di 4 mesi. Questo non sarebbe atipico per una strategia di momentum. È facile convincersi che si possa tollerare tali periodi di perdite perché il quadro generale è roseo. Tuttavia, in pratica, è molto più difficile!

Se i prelievi storici del 25% o più si verificano nei backtests, allora con ogni probabilità vedrai periodi di drawdown simile nel trading dal vivo. Questi periodi di abbattimento sono psicologicamente difficili da sopportare. Ho osservato in prima persona che cosa può comportare un drawdown esteso, e non è piacevole – anche se i backtests suggeriscono che tali periodi si verificheranno. Il motivo per cui l’ho definito un “bias” è che spesso una strategia che altrimenti avrebbe successo viene fermata durante i periodi di drawdown esteso e quindi porterà ad una sottoperformance significativa rispetto al backtest. Pertanto, anche se la strategia è di natura algoritmica, i fattori psicologici possono ancora avere una forte influenza sulla redditività. L’obiettivo è quello di garantire che se si verificano drawdown di una certa percentuale e durata durante il backtesting, allora ci si dovrebbe aspettare che si verifichino anche nel live trading e sarà necessario perseverare per raggiungere nuovamente la redditività.

 

Pacchetti Software per il Backtesting

Lo spazio delle soluzioni software per il backtesting della strategia è molto vasto. Le soluzioni vanno da sofisticati software a livello istituzionale completamente integrati a linguaggi di programmazione come C ++, Python e R, dove quasi tutto deve essere scritto da zero (o con idonei “plug-in”). Come algotrader siamo interessati ad un equilibrio tra il “possedere” il nostro stack tecnologico di trading rispetto alla velocità e all’affidabilità della nostra metodologia di sviluppo. Ecco le considerazioni chiave per la scelta del software:

  • Abilità di programmazione – La scelta dell’ambiente dipenderà in gran parte dalla tua capacità di programmare il software. Direi che avere il controllo dello stack totale avrà un effetto maggiore sul P&L a lungo termine rispetto all’esternalizzazione del software tramite un fornitore. Ciò è dovuto al basso rischio di avere bug esterni o idiosincrasie che non è possibile risolvere nel software del fornitore, che altrimenti sarebbe facilmente risolvibile se si avesse più controllo sul proprio “stack tecnologico”. Desiderate anche un ambiente in grado di trovare il giusto equilibrio tra produttività, disponibilità delle librerie e velocità di esecuzione. Di seguito faccio la mia raccomandazione personale.
  • Funzionalità di esecuzione / Integrazione con il broker – Alcuni software di backtesting, come Tradestation, si collegano direttamente con una società di intermediazione. Non sono un fan di questo approccio poiché ridurre i costi di transazione è spesso un fattore fondamentale per ottenere un SharpeRatio più elevato. Se sei legato a un particolare broker (e Tradestation “obliga” a farlo), allora avrai più difficoltà a passare ad un nuovo software (o ad un nuovo broker) nel caso fosse necessario. Interactive Brokers fornisce una robusta API, sebbene con un’interfaccia leggermente ottusa.
  • Personalizzazione – Un ambiente come MATLAB o Python offre una grande flessibilità quando si creano strategie algoritmiche in quanto forniscono fantastiche librerie per quasi tutte le operazioni matematiche immaginabili, ma consentono anche un’ampia personalizzazione, ove necessario.
  • Complessità della strategia – Alcuni software non sono tagliati per il crunch numerico o per la complessità matematica. Excel è uno di questi software. Mentre è buono per le strategie più semplici, non può davvero far fronte a numerose risorse o algoritmi più complicati.
  • Minimizzazione del bias – un particolare software o set di dati si presta maggiormente ai bias di trading? Nel caso si desideri creare personalmente tutte le funzionalità, È necessario assicurarsi che non si introducano bug che possono causare bias.
  • Velocità di sviluppo – non è necessario passare mesi e mesi a implementare un motore di backtest. La prototipazione dovrebbe richiedere solo alcune settimane. Assicurati che il tuo software non stia ostacolando i tuoi progressi, solo per afferrare qualche punto percentuale extra nella velocità di esecuzione. C ++ è il must in questo ambito.
  • Velocità di esecuzione – Se la tua strategia dipende completamente dalla velocità di esecuzione (come nel  HFT / UHFT), sarà necessario un linguaggio come C o C++. Tuttavia, in questi ambiti siamo al limite dell’ottimizzazione del kernel Linux e dell’utilizzo FPGA, che è al di fuori dello scopo di questo articolo!
  • Costo – molti degli ambienti software con cui è possibile programmare strategie di trading algoritmico sono completamente gratuiti e open source. In effetti, molti hedge fund fanno uso di software open source per tutti i loro stack di trading algoritmico. Inoltre, Excel e MATLAB sono entrambi relativamente economici e ci sono anche alternative gratuite.

 

Ora che abbiamo elencato i criteri con i quali dobbiamo scegliere la nostra infrastruttura software, voglio esaminare alcuni dei pacchetti più popolari e confrontarli tra loro:

Nota: includo solamente i software disponibili per la maggior parte dei professionisti retail e degli sviluppatori di software. Sono disponibili altri software,  come gli strumenti usati a  livello più istituzionale, ma ritengo che questi siano troppo costosi per essere effettivamente utilizzati in un ambiente retail e non ho  esperienza diretta con questi software.

 
MS ExcelDescrizione: WYSIWYG (what-you-see-is-what-you-get) software di spreadsheet. Estremamente diffuso nel settore finanziario. Dati e algoritmo sono strettamente accoppiati.
Esecuzione: Sì, Excel può essere collegato alla maggior parte dei broker.
Personalizzazione: Le macro VBA permettono funzionalità più avanzate a scapito della complessità di implementazione.
Complessità della Strategia: Strumenti statistici avanzati sono più difficili da implementate, così come le strategie che operano su molti asset.
Minimizzazione dei Bias: Il bias Look-ahead è facile da rilevare tramite funzionalità di evidenziazione delle celle (presupponendo che non sia presente VBA).
Velocità di Sviluppo: Le strategie base sono implementate rapidamente.
Velocità di Esecuzione: Bassa velocità di esecuzione – adatto solo per strategie a bassa frequenza.
Costo: Economico o gratuito (a seconda della licenza).
Alternative: OpenOffice
 
MATLABDescrizione: Ambiente di programmazione originariamente progettato per matematica computazionale, fisica e ingegneria. Molto adatto per le operazioni vettorializzate e quelle che coinvolgono l’algebra lineare numerica. Fornisce una vasta gamma di plugin per il trading quantitativo. In uso in molti hedge fund quantitativi.
Esecuzione: Nessuna capacità di esecuzione nativa, MATLAB richiede un sistema di esecuzione separato.
Personalizzazione: Vasta gamma di plug-in per quasi tutte le aree della matematica computazionale.
Complessità della Strategia: Complessità strategica: molti metodi statistici avanzati già disponibili e ben testati.
Minimizzazione dei Bias: i bias di look-ahead sono più difficili da individuare e richiedeno test approfonditi.
Velocità di sviluppo: brevi script possono facilmente generare sofisticati backtest.

Velocità di esecuzione:
MATLAB è altamente ottimizzato per supponendo un algoritmi vettorizzati / parallelizzati. Scarse prestazioni nei cicli iterati tradizionali.
Costo: circa 1,000$ per una licenza.
Alternative: Octave, SciLab
 
PythonDescrizione:
linguaggio di alto livello progettato per avere una semplicità e rapidità di sviluppo. Ampia gamma di librerie per quasi tutte le attività di coding immaginabili. Sta ottenendo sempre maggiori apprezzamenti ed utilizzi da parte dei hedge fund e banche d’investmento. Non veloce come C/C++ relativamente alla velocità di esecuzione.
Esecuzione: esistono plugin Python per i principali broker, come Interactive Brokers. Quindi il backtest e il sistema di esecuzione possono essere parte dello stesso “stack tecnologico”.
Personalizzazione: Python ha una grandissima comunity di sviluppatori ed è un linguaggio maturo. Ciò garantisce un elevato numero di librerie plugin disponibili. NumPy / SciPy forniscono veloci strumenti di calcolo scientifico e di analisi statistica, essenzialiper il trading quantistico.
Complessità della Strategia: esistono molti plug-in per i principali algoritmi, ma non ha una comunità di algotrader abbastanza grande come quella presente per MATLAB.
Minimizzazione dei Bias: soffre degli stessi problemi di minimizzazione dei bias di qualsiasi altro linguaggio di alto livello. Devi essere estremamente attento ai test.
Velocità di sviluppo: il principale vantaggio di Pythons è la velocità di sviluppo, grazie a robuste funzionalità integrate per il testing.
Velocità di Esecuzione: Non è abbastanza veloce come il C++, ma i componenti per il calcolo scientifico sono ottimizzati e Python può utilizzare con il codice C nativo grazie a specifici plugin
Costo: Gratis/Open Source
Alternative: Ruby, Erlang, Haskell
 
RDescrizione: Ambiente progettato per i metodi statistici avanzati e l’analisi di serie temporali. Vasta gamma di strumenti statistici specifici, econometrici e nativi. Grande comunity di sviluppatori.
Esecuzione: R possiede plugin per alcuni broker, in particolare per Interactive Brokers. Quindi un sistema end-to-end può essere scritto interamente in R.
Personalizzazione: R può essere personalizzato con qualsiasi pacchetto, ma i suoi punti di forza sono in ambito statistico / econometrico.
Complessità della Strategia: utile soprattutto se si eseguono strategie econometriche, statistiche o di apprendimento automatico grazie alle librerie disponibili.
Minimizzazione dei Bias: le possibilità di aver bias è simile a quella di qualsiasi linguaggio ad alto livello, come Python o C++. E’ quindi necessario svolgere dei test.
Velocità di Sviluppo: Con R si possono scrivere rapidamente strategie basate su metodi statistici.
Velocità di esecuzione: R è più lento di C ++, ma è relativamente ottimizzato per le operazioni vettorializzate (come con MATLAB).
Costo: Gratis/Open Source
Alternative: SPSS, Stata
 
C++Descrizione: linguaggio maturo e di alto livello progettato per avere un’elevata velocità di esecuzione. Vasta gamma di librerie quantitative e numeriche. Debug più difficile da eseguire e spesso richiede più tempo di implementazione rispetto a Python o MATLAB. Estremamente prevalente sia in lato di acquisto che di vendita.
Esecuzione: la maggior parte delle API dei broker sono scritte in C ++ e Java. Quindi esistono molti plugin.
Personalizzazione C / C ++ consente l’accesso diretto alla memoria sottostante, quindi è possibile implementare strategie di altissima frequenza.
Complessità della Strategia: C++ STL offre un’ampia gamma di algoritmi ottimizzati. Quasi ogni specifico algoritmo matematico ha un’implementazione C / C++ gratuita e open-source sul web.
Minimizzazione dei Bias: il bias di Look-ahead può essere difficile da eliminare, ma non più difficile di altri linguaggi di alto livello. Possiede buoni strumenti di debug, ma bisogna stare attenti quando si ha a che fare con la memoria sottostante.
Velocità di Sviluppo:C++ è piuttosto lento rispetto a Python o MATLAB per lo stesso algoritmo. Più linee di codice (LOC) spesso portano a una maggiore probabilità di errori.
Velocità di Esecuzione: C/C++ ha una velocità di esecuzione estremamente elevata e può essere ottimizzato per specifiche architetture hardware. Questa è la ragione principale per utilizzarlo.
Costo:Costo: vari compilatori: Su Linux / GCC è gratuito, mentre MS Visual Studio ha diverse tipi di licenze.
Alternative: C#, Java, Scala

 

Diverse strategie richiedono quindi diversi pacchetti software. Le strategie HFT e UHFT sono scritte in C / C ++ (dato che spesso eseguite su GPU e FPGA), mentre le strategie direzionali a bassa frequenza sono facili da implementare in TradeStation, a causa della natura “tutto in uno” del software / broker.

La mia personale scelta è Python in quanto fornisce il giusto grado di personalizzazione, velocità di sviluppo, capacità di test e velocità di esecuzione per le mie esigenze e strategie. Se ho bisogno di qualcosa di più veloce, posso “entrare” in C++ direttamente dai miei programmi Python. Un metodo scelto da molti trader algoritmici consiste nel prototipare le loro strategie in Python e quindi convertire le sezioni di esecuzione più lente in C ++ in modo iterativo. Eventualmente l’intero algoritmo può essere scritto

Nei prossimi articoli sul backtesting descriverò alcune criticità relative all’implementazione di un sistema di backtesting per il trading algoritmico. Si evidenzierà come effettuare la misurazione delle prestazioni della strategia e si illustrerà una strategia esemplificativa.

 

Leggi il secondo articolo di questa serie: Il Backtesting di una Strategia di Trading Algoritmico – Parte II

 

Gli altri articoli di questa serie

Benvenuto su DataTrading!

Sono Gianluca, ingegnere software e data scientist. Sono appassionato di coding, finanza e trading. Leggi la mia storia.

Ho creato DataTrading per aiutare le altre persone ad utilizzare nuovi approcci e nuovi strumenti, ed applicarli correttamente al mondo del trading.

DataTrading vuole essere un punto di ritrovo per scambiare esperienze, opinioni ed idee.

SCRIVIMI SU TELEGRAM

Per informazioni, suggerimenti, collaborazioni...

Torna in alto
Scroll to Top