Der Logarithmus des Preisverhältnisses
Eine Log-Rendite ist der natürliche Logarithmus des Verhältnisses zweier Preise. Statt P_t / P_{t-1} - 1 berechnet man ln(P_t / P_{t-1}). Bei kleinen Bewegungen sind beide fast gleich (ein Anstieg von 2 % ergibt 0,0198 als Logarithmus), doch die logarithmische Variante hat Eigenschaften, die sie zur Standardwahl für Statistik und Modellierung machen. In pandas bilden Sie mit np.log den Logarithmus der ganzen Preis-Series und wenden diff an: Logarithmen zu subtrahieren heißt, Preise zu dividieren.
import numpy as np
import pandas as pd
prices = pd.Series([100.0, 102.0, 100.98, 103.0], index=["Mon", "Tue", "Wed", "Thu"])
log_ret = np.log(prices).diff()
print(log_ret.round(4))
# Mon NaN
# Tue 0.0198
# Wed -0.0101
# Thu 0.0198
# dtype: float64
print(prices.pct_change().round(4).tolist()) # [nan, 0.02, -0.01, 0.02] the simple returns, for comparisonLog-Renditen addieren sich über die Zeit
Das ist der Hauptgrund, sie zu verwenden. Da ln(a) - ln(c) = (ln(a) - ln(b)) + (ln(b) - ln(c)) gilt, ist die Log-Rendite über mehrere Perioden einfach die Summe der Log-Renditen der Perioden, ohne Verkettung. Die Zweitagesrendite ist die Summe zweier Tagesrenditen, die Monatsrendite die Summe der Tagesrenditen, und exp(total) - 1 macht das Ergebnis wieder zu einer einfachen Rendite. Log-Renditen sind außerdem symmetrisch: Ein Preis, der sich verdoppelt und dann halbiert, hat Log-Renditen von +0,6931 und -0,6931, die sich aufheben, während die einfachen Renditen +100 % und -50 % betrugen.
# The sum of the daily log returns is the log return over the whole period
print(round(log_ret.sum(), 6)) # 0.029559
print(round(np.log(prices.iloc[-1] / prices.iloc[0]), 6)) # 0.029559 end price over start price
# exp(total) - 1 is the simple return of the whole period
print(round(np.exp(log_ret.sum()) - 1, 6)) # 0.03# Symmetry: the price doubles, then halves
doubling = pd.Series([100.0, 200.0, 100.0])
print(doubling.pct_change().tolist()) # [nan, 1.0, -0.5]
print(np.log(doubling).diff().round(4).tolist()) # [nan, 0.6931, -0.6931]Umrechnen und Bewegungen über mehrere Tage
Um zur einfachen Rendite zurückzukehren, nutzen Sie np.exp(r) - 1 (oder np.expm1(r), genauer bei winzigen Werten). Beide stimmen bei kleinen Bewegungen gut überein und weichen bei großen ab: Eine einfache Rendite von +50 % ist als Logarithmus 0,4055. np.log und np.exp arbeiten auf einer ganzen Series, es gibt also keine Schleife. Um eine Bewegung über mehrere Tage zu messen, nimmt diff eine Zahl von Perioden: np.log(prices).diff(5) ist die Log-Rendite über fünf Tage und entspricht der Summe von fünf täglichen Log-Renditen.
# Small moves agree with the simple return, big moves do not
for simple in [0.01, 0.1, 0.5, -0.5]:
print(simple, round(np.log1p(simple), 4)) # log1p(r) is ln(1 + r)
# 0.01 0.01
# 0.1 0.0953
# 0.5 0.4055
# -0.5 -0.6931
# Back to simple returns, on the whole Series at once
print((np.exp(log_ret) - 1).round(4).tolist()) # [nan, 0.02, -0.01, 0.02]
# The log return over 2 days: diff takes a number of periods
print(np.log(prices).diff(2).round(4).tolist()) # [nan, nan, 0.0098, 0.0098]- Eine Log-Rendite ist
ln(Preis / Vorgängerpreis):np.log(prices).diff(); der erste Eintrag istNaN. - Über die Zeit addieren sie sich einfach:
log_ret.sum(), undnp.exp(total) - 1ergibt die einfache Rendite. diff(k)liefert die Bewegung überkPerioden; über Werte hinweg gewichten Sie die einfachen Renditen, nicht die logarithmischen.
Als Nächstes: DatetimeIndex und zeitbasierte Indizierung, um einer Preisreihe echte Datumswerte zu geben und sie nach Monat oder Wochentag zu schneiden.
Lab: Was bewertet wird
- Mit
log_returnsPreise in Log-Renditen umwandeln25 Pkt. - Mit
simple_from_logLog-Renditen in einfache Renditen zurückrechnen25 Pkt. - Mit
total_log_returndie Log-Renditen der Perioden addieren25 Pkt. - Mit
multi_day_log_returndie Bewegung über mehrere Tage messen25 Pkt.