Nutzen, was man schon weiß
Beim Simulieren eines Calls simuliert man auch den Aktienkurs bei Verfall S_T, dessen wahren Mittelwert S0 * exp(r * T) man genau kennt. In der Stichprobe kam der Mittelwert von S_T etwas daneben heraus, sagen wir zu hoch. Da Call-Auszahlung und S_T zusammen laufen, ist auch der Stichprobenmittelwert des Calls wahrscheinlich zu hoch. Eine Kontrollvariable nutzt das: Sie zieht von der Schätzung der gesuchten Größe ein Vielfaches des beobachteten Fehlers der bekannten Größe ab.
import numpy as np
rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z) # terminal prices
call = np.maximum(s_t - 100.0, 0.0) # the payoff we want
known = 100.0 * np.exp(0.05) # E[S_T], exactly
print(round(float(s_t.mean()), 3), round(known, 3)) # the sample mean of S_T vs its true mean
print(round(float(s_t.mean() - known), 3)) # the observed error of the controlDas beste Vielfache
Wie viel vom Fehler der Kontrolle sollte man abziehen? Das Vielfache b, das die Varianz von payoff - b * control minimiert, ist b = cov(payoff, control) / var(control), genau die Steigung der Regression der Auszahlung auf die Kontrolle (dieselben Summen wie das Beta im CAPM-Thema). Die kontrollierte Schätzung ist mean(payoff) - b * (mean(control) - known_mean). Sie ist unverzerrt, weil der abgezogene Term den Erwartungswert null hat.
import numpy as np
def control_coefficient(payoff, control):
dev = control - control.mean()
return float(np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2))
rng = np.random.default_rng(1)
z = rng.standard_normal(2000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
call = np.maximum(s_t - 100.0, 0.0)
known = 100.0 * np.exp(0.05)
b = control_coefficient(call, s_t)
controlled = call.mean() - b * (s_t.mean() - known)
print(round(b, 4), round(float(call.mean()), 4), round(float(controlled), 4)) # the plain mean and the corrected one# A payoff that is exactly proportional to the control is estimated without any error
import numpy as np
x = np.random.default_rng(2).standard_normal(50) + 5.0 # the control, known mean 5.0
y = 2.0 * x # the payoff
dev = x - x.mean()
b = np.sum(dev * (y - y.mean())) / np.sum(dev ** 2)
print(round(float(b), 6), round(float(y.mean() - b * (x.mean() - 5.0)), 6)) # 2.0 and exactly 10.0Wie viel Fehler gespart wird
Die angepassten Stichproben payoff - b * control tragen das Rauschen, der Standardfehler der kontrollierten Schätzung ist also ihre Standardabweichung (ddof=1) durch sqrt(n). Bei Korrelation rho zwischen Auszahlung und Kontrolle sinkt die Varianz um den Faktor 1 - rho^2: Eine Korrelation von 0,9 beseitigt 81 %, 0,99 beseitigt 98 %. Die Kontrolle kostet keine zusätzliche Simulation, nur ein paar Zeilen mehr.
import numpy as np
def control_variate_error(payoff, control):
dev = control - control.mean()
b = np.sum(dev * (payoff - payoff.mean())) / np.sum(dev ** 2)
return float((payoff - b * control).std(ddof=1) / np.sqrt(len(payoff)))
rng = np.random.default_rng(1)
z = rng.standard_normal(20000)
s_t = 100.0 * np.exp((0.05 - 0.5 * 0.2 ** 2) + 0.2 * z)
for strike in (80.0, 100.0, 120.0):
call = np.maximum(s_t - strike, 0.0)
plain = float(call.std(ddof=1) / np.sqrt(len(call)))
print(strike, round(plain, 4), round(control_variate_error(call, s_t), 4), round(plain / control_variate_error(call, s_t), 2))b nahe 0 und nichts gewonnen), und ihr exakter Mittelwert muss bekannt sein (sonst ist die Korrektur geraten). Gute Kontrollen für den arithmetischen Durchschnitt einer asiatischen Option sind der geometrische Durchschnitt, dessen Preis eine Formel hat, oder der Endkurs selbst. Man kann mehrere Kontrollen gleichzeitig nutzen, die Koeffizienten stammen dann aus einer multiplen Regression.- Eine Kontrollvariable ist eine simulierte Größe mit bekanntem Mittelwert; von der Schätzung zieht man ein Vielfaches ihres beobachteten Fehlers ab:
mean(Y) - b * (mean(X) - E[X]). - Das beste Vielfache ist die Regressionssteigung
b = cov(Y, X) / var(X); der Fehler ist die Standardabweichung vonY - b * Xdurchsqrt(n). - Die Varianz sinkt um den Faktor
1 - rho^2; eine gute Kontrolle ist stark mit der Auszahlung korreliert, hat einen exakt bekannten Mittelwert und kostet keine zusätzliche Simulation.
Als Nächstes: scikit-learn-Pipelines für Renditen, Vorhersagemodelle auf Renditedaten anpassen und bewerten.
Lab: Was bewertet wird
- Mit
control_coefficientdas richtige Vielfache wählen25 Pkt. - Mit
control_variate_estimatedie Schätzung korrigieren25 Pkt. - Mit
control_variate_errorden Fehlerbalken verkleinern25 Pkt. - Mit
error_reductionden Gewinn beziffern25 Pkt.