Analisi delle performance degli asset con Python

Analisi delle performance degli asset con Python – parte 2

Sommario

Questo articolo è la seconda parte della mini-serie che descrive come implementare l’analisi delle performance degli asset con Python usando i metodi  resi disponibili dal pacchetto “ffn – Financial Functions“.

Nel precedente articolo abbiamo introdotto i concetti basi della libreria e descritto l’oggetto PerformanceStats di FFN. In questo articolo ci concentriamo sull’oggetto GroupStats. Il PerformanceStats si usa con una singola serie di dati, mentre il GroupStats può usare un dataframe composto da più colonne che rappresentano contemporaneamente diverse serie di prezzi/equity.

Analisi di un gruppo di serie dati

Creiamo ora alcuni nuovi dati. In questo esempio prevediamo un DataFrame con 4 colonne di dati, ciascuna delle quali rappresenta una “curva equity” di una strategia di trading (o del prezzo di  asset) e visualizziamo le prime 5 righe di tali dati.

				
					import pandas as pd
import numpy as np

np.random.seed(1)
num_days = 1000
index = pd.date_range('01/01/2010', periods=num_days, freq='D')
data1 = pd.DataFrame((np.random.randn(num_days) + np.random.uniform(low=0.0, high=0.2, size=num_days)),index=index,columns=['Data1'])
data2 = pd.DataFrame((np.random.randn(num_days) + np.random.uniform(low=0.0, high=0.2, size=num_days)),index=index,columns=['Data2'])
data3 = pd.DataFrame((np.random.randn(num_days) + np.random.uniform(low=0.0, high=0.2, size=num_days)),index=index,columns=['Data3'])
data4 = pd.DataFrame((np.random.randn(num_days) + np.random.uniform(low=0.0, high=0.2, size=num_days)),index=index,columns=['Data4'])

data = pd.concat([data1,data2,data3,data4],axis=1)
data = data.cumsum() + 100
data.iloc[0] = 100
print(data.head())
				
			
Analisi delle performance degli asset con Python
Il primo step è identico a quanto descritto per una singola serie di rendimenti nella prima parte di questo tutorial. Prendiamo l’oggetto data e lo trasformiamo in un oggetto di ffn, in questo caso in un oggetto GroupStats e lo assegniamo ad una variabile.
				
					import ffn

perf = data.calc_stats()
				
			
Se stampiamo il tipo della variabile che abbiamo appena creato possiamo vedere che è un oggetto ffn.core.GroupStats. Ricordiamoci che nel caso di una singola serie di rendimenti abbiamo creato un oggetto ffn.core.PerformanceStats.
				
					print(type(perf))
				
			
				
					<classe 'ffn.core.GroupStats'>
				
			

Possiamo quindi visualizzare il grafico dei rendimenti di questo gruppo di serie

				
					perf.plot()
				
			
Analisi delle performance degli asset con Python

Analisi degli asset azionari

Vediamo ora come applicare queste funzioni ad un dataframe pandas che contiene le serie di prezzi  storici di titoli azionari che scarichiamo da Yahoo Finance

				
					import yfinance as yf

stocks = ['AAPL', 'AMZN', 'MSFT', 'NFLX']

data = yf.download(stocks, start='2010-01-01', end='2020-01-01')['Adj Close']
data.sort_index(ascending=True, inplace=True)
perf = data.calc_stats()
				
			

Se visualizziamo il grafico dei prezzi notiamo che sono automaticamente normalizzati ad un valore iniziale pari a 100 in modo da renderli più comparabili.

				
					perf.plot()
				
			
Analisi delle performance degli asset con Python

Iniziamo ad usare i dati storici dei prezzi dei titoli azionari appena scaricati per elaborare le statistiche e procedere ad analisi dettagliate. Ad esempio possiamo visualizzare le statistiche per tutti i titoli contemporaneamente tramite la stessa funzione, come descritto per una singola serie.

				
					perf.display()
				
			
				
					Stat                 AAPL        AMZN        MSFT        NFLX
-------------------  ----------  ----------  ----------  ----------
Start                2010-01-04  2010-01-04  2010-01-04  2010-01-04
End                  2019-12-31  2019-12-31  2019-12-31  2019-12-31
Risk-free rate       0.00%       0.00%       0.00%       0.00%

Total Return         1003.89%    1280.01%    547.35%     4135.21%
Daily Sharpe         1.06        1.00        0.94        0.98
Daily Sortino        1.77        1.72        1.59        1.73
CAGR                 27.18%      30.06%      20.56%      45.51%
Max Drawdown         -43.80%     -34.10%     -26.37%     -81.99%
Calmar Ratio         0.62        0.88        0.78        0.56

MTD                  9.88%       2.61%       4.17%       2.83%
3m                   31.50%      6.45%       13.81%      20.91%
6m                   49.38%      -2.42%      18.52%      -11.91%
YTD                  88.96%      23.03%      57.56%      20.89%
1Y                   88.96%      23.03%      57.56%      20.89%
3Y (ann.)            38.48%      34.98%      38.70%      36.55%
5Y (ann.)            23.70%      42.88%      30.48%      45.99%
10Y (ann.)           27.18%      30.06%      20.56%      45.51%
Since Incep. (ann.)  27.18%      30.06%      20.56%      45.51%
Daily Sharpe         1.06        1.00        0.94        0.98

Daily Sortino        1.77        1.72        1.59        1.73
Daily Mean (ann.)    27.39%      31.09%      21.30%      51.00%
Daily Vol (ann.)     25.75%      30.98%      22.72%      52.08%
Daily Skew           -0.18       0.41        0.07        0.92
Daily Kurt           4.42        7.94        6.30        23.70
Best Day             8.87%       15.75%      10.45%      42.22%
Worst Day            -12.36%     -12.66%     -11.40%     -34.90%

Monthly Sharpe       1.12        1.11        1.05        0.89
Monthly Sortino      2.25        2.43        2.11        1.98
Monthly Mean (ann.)  28.85%      31.26%      22.11%      53.37%
Monthly Vol (ann.)   25.78%      28.17%      21.04%      59.94%
Monthly Skew         -0.20       0.23        0.04        0.99
Monthly Kurt         -0.04       0.46        0.69        4.56
Best Month           20.04%      25.82%      19.63%      78.46%
Worst Month          -18.12%     -20.22%     -15.14%     -51.80%
Yearly Sharpe        0.93        0.85        1.31        0.56

Yearly Sortino       14.18       4.75        16.98       2.89
Yearly Mean          27.59%      34.89%      25.56%      57.94%
Yearly Vol           29.65%      41.09%      19.51%      103.90%
Yearly Skew          1.03        0.77        0.14        1.73
Yearly Kurt          1.20        1.16        -0.49       3.61
Best Year            88.96%      117.78%     57.56%      297.63%
Worst Year           -5.39%      -22.18%     -4.52%      -60.56%

Avg. Drawdown        -3.93%      -4.70%      -3.03%      -6.33%
Avg. Drawdown Days   31.29       29.56       26.50       31.47
Avg. Up Month        7.12%       7.38%       5.20%       13.26%
Avg. Down Month      -4.83%      -5.53%      -4.54%      -11.13%
Win Year %           77.78%      77.78%      88.89%      77.78%
Win 12m %            76.15%      92.66%      88.99%      75.23%

				
			
È possibile accedere a queste informazioni attraverso un normale dataframe Pandas usando la funzione stats, quindi possibile essere indicizzato come qualsiasi dataframe.
				
					print(perf.stats)
				
			
Analisi delle performance degli asset con Python

E può essere indicizzato, ad esempio, come segue.

				
					print(perf.stats.loc['cagr'])
				
			
				
					AAPL    0.271807
AMZN    0.300556
MSFT     0.20563
NFLX    0.455084
Name: cagr, dtype: object
				
			

Fino ad ora abbiamo visto come l’oggetto GroupStats generi output molto simile all’oggetto PerformanceStats. Descriviamo quindi alcune , quindi alcune funzionalità specifiche di GroupStats.

Iniziamo creando un DataFrame contenente una serie di rendimenti logaritmici per ciascuna delle equity dei prezzi delle azioni nel nostro DataFrame data.

				
					returns = data.to_log_returns().dropna()
print(returns.head())
				
			
Analisi-Performance-FFN-Group-Return-Logs

Possiamo creare rapidamente un multiplot degli istogrammi dei rendimenti logaritmici di ogni serie insieme allo screting di un dataframe contenente anche la matrice di correlazione dei titoli.

				
					ax = returns.hist(figsize=(20, 10),bins=30)
				
			
Analisi-Performance-FFN-Group-Istogramma
				
					print(returns.corr().as_format('.2f'))
				
			
Analisi-Performance-FFN-Group-Corr

Funzionalità avanzate

Se vogliamo qualcosa di visivamente più accattivante rispetto allla stampa del dataframe, possiamo facilmente creare una heatmap della matrice di correlazione.

				
					returns.plot_corr_heatmap()
				
			
Analisi-Performance-FFN-Group-Corr-Heatmap

Questa heatmap mostra risultati un po’ più rilevanti rispetto ai precedenti dati generati casualmente. Continuiamo a usare i dati scaricati da Yahoo Finance per generare rapidamente il “portafoglio ottimale” basato sui classici metodi di  Mean/Variance Optimisation di Markowitz.

				
					print(returns.calc_mean_var_weights().as_format('.2%'))
				
			
				
					AAPL    41.14%
AMZN    19.40%
MSFT    25.13%
NFLX    14.32%
dtype: object
				
			

E’ possibile creare una completa matrice di grafici a dispersione con un semplice funzione.

				
					perf.plot_scatter_matrix()
				
			
Analisi-Performance-FFN-Group-Scatter-Matrix

Possiamo anche visualizzare contemporaneamente le serie dei drawdown per tutti gli asset con la seguente funzione.

				
					ffn.to_drawdown_series(data).plot(figsize=(15,10))
				
			
Analisi-Performance-FFN-Group-Drawdown

Ci sono ulteriori funzionalità disponibili dal pacchetto FFN, ma lascerò a voi tutti la possibilità di approfondire e testare le altre parti della libreria.

Codice completo

In questo articolo abbiamo descritto come implementare l’analisi delle performance degli asset con Python. Per il codice completo riportato in questo articolo, si può consultare il seguente repository di github:
https://github.com/datatrading-info/AnalisiDatiFinanziari

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