Usar lo que ya se sabe
Al simular un call también simulas el precio de la acción al vencimiento S_T, cuya media verdadera S0 * exp(r * T) conoces exactamente. En tu muestra el promedio de S_T salió algo desviado, digamos demasiado alto. Como el pago del call y S_T se mueven juntos, la media muestral del call probablemente también es demasiado alta. Una variable de control aprovecha esto: resta de la estimación de lo que quieres un múltiplo del error observado en la cantidad que conoces.
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 controlEl mejor múltiplo
¿Qué parte del error del control hay que restar? El múltiplo b que minimiza la varianza de payoff - b * control es b = cov(payoff, control) / var(control), exactamente la pendiente de la regresión del pago sobre el control (las mismas sumas que la beta del tema CAPM). La estimación controlada es mean(payoff) - b * (mean(control) - known_mean). Es insesgada, porque el término restado tiene esperanza cero.
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.0Cuánto error se ahorra
Las muestras ajustadas payoff - b * control son las que llevan el ruido, así que el error estándar de la estimación controlada es su desviación típica (ddof=1) dividida por sqrt(n). Con correlación rho entre pago y control, la varianza cae en un factor 1 - rho^2: una correlación de 0,9 elimina el 81 %, y 0,99 el 98 %. El control no cuesta simulación extra, solo unas líneas más.
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 es casi 0 y no se gana nada) y su media exacta debe ser conocida (si no, la corrección es una conjetura). Buenos controles para el promedio aritmético de una asiática son el promedio geométrico, cuyo precio tiene fórmula, o el propio precio terminal. Pueden usarse varios controles a la vez, y los coeficientes salen entonces de una regresión múltiple.- Una variable de control es una cantidad simulada de media conocida; se resta de la estimación un múltiplo de su error observado:
mean(Y) - b * (mean(X) - E[X]). - El mejor múltiplo es la pendiente de regresión
b = cov(Y, X) / var(X); el error es la desviación típica deY - b * Xentresqrt(n). - La varianza baja en
1 - rho^2; un buen control está muy correlacionado con el pago y tiene media exactamente conocida, y no cuesta simulación extra.
A continuación: los pipelines de scikit-learn para rendimientos, ajustar y evaluar modelos predictivos sobre rendimientos.
Lab: qué se califica
- Elegir el múltiplo correcto con
control_coefficient25 pts - Corregir la estimación con
control_variate_estimate25 pts - Reducir la barra de error con
control_variate_error25 pts - Contar la ganancia con
error_reduction25 pts