2015-07-08 26 views
12

Python panda ha una funzione pct_change che uso per calcolare i rendimenti per i prezzi delle azioni in un dataframe:ritorna logaritmiche a panda dataframe

ndf['Return']= ndf['TypicalPrice'].pct_change() 

Sto usando il seguente codice per ottenere rendimenti logaritmici, ma dà la esatte valori stessi come la funzione pct.change():

ndf['retlog']=np.log(ndf['TypicalPrice'].astype('float64')/ndf['TypicalPrice'].astype('float64').shift(1)) 
#np is for numpy 

risposta

22

Ecco un modo per calcolare il ritorno registro utilizzando .shift(). E il risultato è simile ma non uguale al rendimento lordo calcolato da pct_change(). Puoi caricare una copia dei tuoi dati di esempio (link alla condivisione della casella personale) per riprodurre l'incoerenza che hai visto?

import pandas as pd 
import numpy as np 

np.random.seed(0) 
df = pd.DataFrame(100 + np.random.randn(100).cumsum(), columns=['price']) 
df['pct_change'] = df.price.pct_change() 
df['log_ret'] = np.log(df.price) - np.log(df.price.shift(1)) 

Out[56]: 
     price pct_change log_ret 
0 101.7641   NaN  NaN 
1 102.1642  0.0039 0.0039 
2 103.1429  0.0096 0.0095 
3 105.3838  0.0217 0.0215 
4 107.2514  0.0177 0.0176 
5 106.2741  -0.0091 -0.0092 
6 107.2242  0.0089 0.0089 
7 107.0729  -0.0014 -0.0014 
..  ...   ...  ... 
92 101.6160  0.0021 0.0021 
93 102.5926  0.0096 0.0096 
94 102.9490  0.0035 0.0035 
95 103.6555  0.0069 0.0068 
96 103.6660  0.0001 0.0001 
97 105.4519  0.0172 0.0171 
98 105.5788  0.0012 0.0012 
99 105.9808  0.0038 0.0038 

[100 rows x 3 columns] 
+0

Sto ottenendo molti valori in pct_change() e log_ret esattamente lo stesso, e pochissimi valori leggermente diversi. Ci si potrebbe aspettare? – AmanArora

+2

@AmanArora Sì, è un comportamento previsto. log return e gross return sono molto vicini quando il tuo rendimento lordo è piccolo, diciamo meno dell'1%. Può essere provato matematicamente dall'espansione di Taylor di secondo ordine intorno a 0. –

+1

@AmanArora BTW, log return ha la proprietà desiderata che sia additivo nel tempo (ma non additivo su asset diversi), mentre il rendimento lordo è più appropriato quando si calcola un rendimento medio ponderato del portafoglio (cioè additivo su asset differenti ma non additivo col tempo). –

5

I risultati potrebbero sembrare simile, ma che è solo a causa della Taylor expansion for the logarithm. Dal log (1 + x) ~ x, i risultati possono essere simili.

Tuttavia,

Sto usando il seguente codice per ottenere rendimenti logaritmici, ma dà i valori esattamente lo stesso come la funzione pct.change().

non è del tutto corretto.

import pandas as pd 

df = pd.DataFrame({'p': range(10)}) 

df['pct_change'] = df.pct_change() 
df['log_stuff'] = \ 
    np.log(df['p'].astype('float64')/df['p'].astype('float64').shift(1)) 
df[['pct_change', 'log_stuff']].plot(); 

enter image description here

22

rendimenti log sono semplicemente il logaritmo naturale di 1 più il ritorno aritmetica. Che ne dici di questo?

df['pct_change'] = df.price.pct_change() 
df['log_return'] = np.log(1 + df.pct_change) 
+0

Questa è un'ottima risposta – user3341078

10

Singola riga e solo una volta i calcoli di calcolo. Prima converti in log-space, quindi prendi il diff di 1 periodo.

np.log(df.price).diff() 
0

@ poulter7: Non posso commentare le altre risposte, in modo da inserire come nuova risposta: attenzione con

np.log(df.price).diff() 

come questo non riuscirà per gli indici che possono diventare negativi, così come fattori di rischio, ad es tassi d'interesse negativi. In questi casi

np.log(df.price/df.price.shift(1)).dropna() 

è preferibile e in base alla mia esperienza generalmente l'approccio più sicuro. Valuta anche il logaritmo solo una volta.

Se si utilizza +1 o -1 dipende dall'ordinamento delle serie temporali. Usa -1 per la discesa e +1 per le date crescenti: in entrambi i casi lo spostamento fornisce il valore della data precedente.