Deux autres façons dont le prix bouge
Delta, gamma et véga couvrent l'action et sa volatilité. Il reste deux entrées de la formule de Black–Scholes : la durée avant l'échéance et le taux d'intérêt. Le thêta est la variation de la valeur d'une option quand le temps passe (le t de la formule diminue chaque jour), et le rho est la variation quand les taux bougent. Le thêta est souvent celui que l'on ressent chaque jour : une option longue est un actif qui s'érode, et la prime perdue chaque jour est le prix de la convexité détenue.
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
def d1(spot, strike, rate, sigma, t):
return (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
def d2(spot, strike, rate, sigma, t):
return d1(spot, strike, rate, sigma, t) - sigma * math.sqrt(t)
def call_theta(spot, strike, rate, sigma, t):
decay = -spot * norm_pdf(d1(spot, strike, rate, sigma, t)) * sigma / (2 * math.sqrt(t))
carry = -rate * strike * math.exp(-rate * t) * norm_cdf(d2(spot, strike, rate, sigma, t))
return decay + carry
theta = call_theta(100, 100, 0.05, 0.2, 1)
print(round(theta, 4)) # -6.414 per year
print(round(theta / 365, 4)) # -0.0176 per calendar dayThêta : pourquoi le temps fait mal
Le premier terme du thêta, -S * pdf(d1) * sigma / (2 * sqrt(T)), est l'érosion de la *valeur de l'option* : avec moins de temps, il y a moins de chances d'un grand mouvement. Le second, -r * K * exp(-rT) * N(d2), est l'intérêt sur le prix d'exercice qu'on n'a pas encore à payer, ce qui est un gain pour l'acheteur du call. Les deux sont négatifs pour un call, donc le thêta aussi, et la perte n'est pas régulière : elle s'accélère à l'approche de l'échéance, plus vite pour les options à la monnaie. Les opérateurs le cotent par jour calendaire, theta / 365.
# Theta per day for the same option as expiry approaches: the decay speeds up
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def norm_pdf(x):
return math.exp(-0.5 * x * x) / math.sqrt(2 * math.pi)
def call_theta(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
d_2 = d_1 - sigma * math.sqrt(t)
return -spot * norm_pdf(d_1) * sigma / (2 * math.sqrt(t)) - rate * strike * math.exp(-rate * t) * norm_cdf(d_2)
for days in (360, 90, 30, 7):
per_day = call_theta(100, 100, 0.05, 0.2, days / 365) / 365
print(days, "days left:", round(per_day, 4)) # 360: -0.0177, 90: -0.0288, 30: -0.045, 7: -0.0858Rho : le taux
Le rho vaut K * T * exp(-rT) * N(d2) : positif pour un call, car un taux plus élevé réduit la valeur actuelle du prix d'exercice à payer. Un put a le signe opposé. C'est la plus petite des lettres grecques pour les options de courte durée, et elle compte pour les longues (LEAPS, warrants longs). On le cote pour un point de pourcentage de taux, rho / 100, comme le véga par point de volatilité.
# Rho of the one-year call at several rates: it grows with the rate and with the time left
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def call_rho(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
return strike * t * math.exp(-rate * t) * norm_cdf(d_1 - sigma * math.sqrt(t))
for rate in (0.0, 0.05, 0.10):
print("rate", rate, "rho per point:", round(call_rho(100, 100, rate, 0.2, 1) / 100, 4)) # 0.0: 0.4602, 0.05: 0.5323, 0.1: 0.5931
print("two years, 5%:", round(call_rho(100, 100, 0.05, 0.2, 2) / 100, 4)) # 1.0568# Check theta and rho by bumping the inputs: they are slopes of the price
import math
def norm_cdf(x):
return 0.5 * (1 + math.erf(x / math.sqrt(2)))
def bs_call(spot, strike, rate, sigma, t):
d_1 = (math.log(spot / strike) + (rate + 0.5 * sigma ** 2) * t) / (sigma * math.sqrt(t))
return spot * norm_cdf(d_1) - strike * math.exp(-rate * t) * norm_cdf(d_1 - sigma * math.sqrt(t))
h = 1e-5
theta = -(bs_call(100, 100, 0.05, 0.2, 1 + h) - bs_call(100, 100, 0.05, 0.2, 1 - h)) / (2 * h)
rho = (bs_call(100, 100, 0.05 + h, 0.2, 1) - bs_call(100, 100, 0.05 - h, 0.2, 1)) / (2 * h)
print(round(theta, 4), round(rho, 4)) # -6.414 53.2325theta ~ -0.5 * sigma^2 * S^2 * gamma (à taux nul). Un opérateur long gamma parie donc que l'action bougera plus que la volatilité déjà intégrée au prix.- Le thêta est la valeur perdue avec le temps : négatif pour un call long, plus rapide près de l'échéance et à la monnaie ; on le cote
theta / 365par jour. - Le rho est la sensibilité au taux d'intérêt : positif pour les calls, négatif pour les puts, maximal pour les longues échéances ; on le cote
rho / 100par point. - Ce sont deux pentes du prix : une petite perturbation de
tou deratepermet de vérifier toute formule.
À suivre : la volatilité implicite, utiliser la formule à l'envers pour lire la volatilité du marché dans le prix d'une option.
Lab : ce qui est noté
- Chiffrer l'écoulement du temps avec
call_theta25 pts - Exprimer l'érosion quotidienne avec
theta_per_day25 pts - Mesurer la sensibilité aux taux d'intérêt avec
call_rho25 pts - Exprimer le rho par point de pourcentage avec
rho_per_point25 pts