Eine Verlustgrenze mit Konfidenzniveau
Der Value at Risk antwortet: Wie viel kann ich an einem schlechten Tag verlieren, aber nicht am schlechtesten? Ein 1-Tages-VaR mit 95 % von 2 % sagt, dass der Verlust an 95 von 100 Tagen 2 % nicht übersteigen sollte. Die historische Methode braucht kein Modell. Man nimmt die vergangenen Renditen, sortiert sie und liest den Verlust am 5. Perzentil ab: Der VaR ist minus dieses Quantil. Aufseher und Risikolimits nutzen ihn überall, weil er eine einzige Zahl ist, die ein Manager mit einem Limit vergleichen kann.
import numpy as np
rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500) # two years of daily returns
var_95 = -np.quantile(returns, 0.05) # minus the 5th percentile
var_99 = -np.quantile(returns, 0.01)
print(round(float(var_95), 5), round(float(var_99), 5)) # 0.01928 0.027 the 99% loss limit is largerEinen VaR testen: die Überschreitungen
Ein VaR ist eine Prognose, kann also überprüft werden. Eine Überschreitung ist ein Tag, an dem der Verlust den VaR überstieg, return < -VaR. Bei einem 95-%-VaR erwartet man etwa 5 % der Tage als Überschreitungen: viel mehr heißt, das Modell unterschätzt das Risiko, viel weniger, dass es zu vorsichtig ist. Aufseher zählen Überschreitungen über 250 Tage genau deshalb. Beachten Sie die strikte Ungleichung: Ein Verlust gleich dem VaR ist keine Überschreitung.
import numpy as np
rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500)
var_95 = -np.quantile(returns, 0.05)
exceptions = int(np.sum(returns < -var_95))
print(exceptions, "exceptions in", len(returns), "days; expected about", int(0.05 * len(returns))) # 25 25Längere Horizonte, und wie es geschah
Oft wird ein 10-Tages-VaR verlangt. Bei unabhängigen Tagesrenditen wächst die Volatilität mit der Wurzel der Zeit, daher skaliert die Wurzel-aus-Zeit-Regel: VaR_T = VaR_1 * sqrt(T). Sie ist eine Näherung, schwächer bei dicken Rändern und autokorrelierten Renditen. Ehrliche Backtests achten auch auf die Zeit: Der an Tag t verwendete VaR darf nur Renditen vor Tag t nutzen, dieselbe Disziplin wie beim Vermeiden von Look-ahead. Ein rollierender VaR macht das mit einem Fenster der letzten n Tage.
# The square-root-of-time rule for several horizons
import math
one_day = 0.0186
for days in (1, 5, 10, 20):
print(days, round(one_day * math.sqrt(days), 4)) # 1: 0.0186, 5: 0.0416, 10: 0.0588, 20: 0.0832import numpy as np
def historical_var(returns, confidence):
return float(-np.quantile(returns, 1 - confidence))
def rolling_var(returns, window, confidence):
out = np.full(len(returns), np.nan)
for t in range(window, len(returns)):
out[t] = historical_var(returns[t - window:t], confidence) # the days BEFORE day t
return out
rng = np.random.default_rng(3)
returns = rng.normal(0.0004, 0.012, size=500)
rolling = rolling_var(returns, 250, 0.99)
print(np.isnan(rolling[:250]).all(), round(float(rolling[250]), 5), round(float(rolling[-1]), 5))
exceptions = int(np.sum(returns[250:] < -rolling[250:]))
print(exceptions, "exceptions in", len(returns) - 250, "days (about 2 expected at 99%)")
print(round(historical_var(returns, 0.99) * np.sqrt(10), 5)) # a 10-day figure by the square-root rule- Der historische VaR ist minus das
(1 - confidence)-Quantil vergangener Renditen (np.quantile): ein positiver Verlustanteil ohne Modell. - Testen Sie durch Zählen der Überschreitungen (
return < -VaR): etwa1 - confidenceder Tage; mehr heißt, der VaR ist zu niedrig. - Skalieren Sie mit
var * sqrt(days)auf einen Horizont; ein rollierendes Fenster nutzt nur frühere Tage; der VaR liefert eine Schwelle, nicht die Größe der Verluste darüber.
Als Nächstes: parametrischer VaR, dieselbe Schwelle aus einer Normalverteilung statt aus der Rohhistorie berechnen.
Lab: Was bewertet wird
- Mit
historical_varden Verlust aus der Historie ablesen25 Pkt. - Mit
var_exceptionsdie Überschreitungen zählen25 Pkt. - Mit
scale_varden Horizont dehnen25 Pkt. - Mit
rolling_varso schätzen, wie es geschah25 Pkt.