LSTM & le false promesse

Di recente mi sono imbattuto in un articolo che mostra come l’applicazione si tecniche di ML basate su LSTM possano generare risultati migliori rispetto a una strategia B&H. La prima osservazione è che il singolo titolo non fa testo, occorre avere un paniere sufficientemente ampio per dimostrare che un algoritmo di ML sia efficace.

Subito dopo ho voluto provare l’algoritmo, conscio dei risultati scadenti che ho sempre ottenuto tramite LSTM mi sono chiesto quali fossero gli elementi che rendono quest’implementazione LSTM così efficace, anche solo per un singolo caso. Soprattutto perché risultati così buoni li ho ottenuti solo con ‘lookahead bias’ ossia i dati che alimentano il calcolo contengono informazioni sullo stato futuro.

Questo ovviamente è possibile solo per errori o sviste di programmazione. Quindi mi sono messo a caccia della chiave vincente o dell’errore. Devo essere sincero il codice è di buona qualità e trovare la chiave di volta non è stato semplice. Le serie temporali sono sempre ostiche, basta uno shift sbagliato e salta tutto, in questo caso non c’è stato bisogno di uno shift per fare la magia, che si verifica nel punto in cui viene preparato il dataset di test e il risultato. Precisamente il passaggio magico (o incriminato che dir si voglia) è quello indicato con In [17]

scaler=MinMaxScaler(feature_range=(0,1))
dg=pd.DataFrame(scaler.fit_transform(dfm[["High","Low","Open","Close","Volume","fd_cm_open",\
                                          "mv_avg_12","mv_avg_24","fd_nm_open"]].values))
dg0=dg[[0,1,2,3,4,5,6,7]]


window=4
dfw=create_window(dg0,window)

X_dfw=np.reshape(dfw.values,(dfw.shape[0],window+1,8))
print(X_dfw.shape)
print(dfw.iloc[:4,:])
print(X_dfw[0,:,:])

y_dfw=np.array(dg[8][window:])

Guardando nel dettaglio come vengono costruiti i vari campi scopriamo che i valori in ingresso per High, Low, Open, Close sono il valore medio del mese corrente, ossia dal primo giorno del mese all’ultimo giorno del mese e che il valore di cui si vuole fare la previsione è il primo valore del mese successivo. Va da se che la previsione è falsata dai valori medi del mese corrente.

L’errore è indotto dal fatto che l’algoritmo lavora sul primo giorno mese. Intuitivamente se a gennaio stimo il mese di febbraio, un conto è stimare il valore del primo giorno di febbraio, un conto è stimare il valore l’ultimo giorno di febbraio. Una correzione veloce consiste nel shiftare i due valore relativi all’apertura del mese corrente e del prossimo mese di -1. E’ quindi sufficiente inserire questo blocco di codice

#run once
dfm["fd_nm_open"] = dfm["fd_nm_open"].shift(-1)
dfm["fd_cm_open"] = dfm["fd_cm_open"].shift(-1)
dfm=dfm.dropna()

E quindi la verifica visiva che stiamo guardando i dati giusti

print(dfm[["High","Low","Open","Close","Volume","fd_cm_open", "mv_avg_12","mv_avg_24","fd_nm_open"]].head(1))
print(df.loc['1975-02'].mean())
print(df.loc['1975-02'].iloc[0].loc['Close'])
print(df.loc['1975-03'].iloc[0].loc['Close'])

Il risultato è il seguente:

                                High        Low  Open      Close  \
Date                                                               
1975-01-31 00:00:00-05:00  73.546817  71.442273   0.0  72.564091   

                                 Volume  fd_cm_open  mv_avg_12  mv_avg_24  \
Date                                                                        
1975-01-31 00:00:00-05:00  1.966136e+07       77.82   82.84377  95.136477   

                           fd_nm_open  
Date                                   
1975-01-31 00:00:00-05:00   83.029999  
Open      0.000000e+00
High      8.098842e+01
Low       7.889211e+01
Close     8.009684e+01
Volume    2.229684e+07
dtype: float64
77.81999969482422
83.02999877929688

il campo fd_cm_open per il 31 gennaio 1975 contiene il valore di apertura del mese di febbraio, mentre il campo fd_nm_open contiene il valore di apertura del mese di marzo. In pratica posizionandoci il primo giorno di febbraio ci stiamo chiedendo se il primo marzo avremo guadagnato o perso. Per farlo utilizziamo la madia 12 e 24 calcolate sulla media mensile compreso il mese di Gennaio. Ora facciamo girare l’algoritmo con il solito fit e …. vediamo se il risultato rimane positivo.

Atteso il tempo per completare il training ecco a confronto i grafici prima e dopo.

Versione originale
Versione corretta
Versione originale
Versione corretta

Il risultato ottenuto adesso è in linea con le mie aspettative. Non ci sono dati sufficiente per un training che possa generare i risultati così positivi come quelli presentati nell’articolo.

Valgono sempre le considerazioni di base per tutti gli algoritmi che si trovano in giro, se fossero efficaci non verrebbero pubblicati ma sfruttati dal creatore e pubblicati sono quando hanno terminato la loro efficacia. Ossia, non è tutto oro ciò che lucica.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.

WP to LinkedIn Auto Publish Powered By : XYZScripts.com