4つの数で表すスマイル
金利やFXのオプションは多数の権利行使価格で取引され、デスクには、気配のボラティリティを補間・外挿するための、滑らかで裁定を意識した方法が必要です。SABR(Hagan、Kumar、Lesniewski、Woodward、2002)は市場標準です。フォワード F を、それ自身の確率的ボラティリティ alpha とともにモデル化します:dF = alpha F^beta dW、d alpha = nu alpha dZ、ショック間の相関は rho です。1つの満期のスマイルは4つのパラメータで決まります。alpha は全体の水準、beta はボラティリティが価格水準にどう依存するか(0 は正規、1 は対数正規)、rho は傾き(スキュー)、nu は曲率(両端がどれだけ上がるか)です。
# The four parameters of one expiry, for a rate forward of 3%
f, t = 0.03, 1.0 # forward rate and expiry in years
alpha, beta, rho, nu = 0.035, 0.5, -0.3, 0.4
print(round(alpha / f ** (1 - beta), 4)) # 0.2021 alpha / f^(1-beta) is roughly the at-the-money volatility (before the correction)Hagan の式
Hagan の漸近展開は、シミュレーションなしでブラックのインプライド・ボラティリティを与えます。アットザマネー(K = F)では alpha / F^(1-beta) に時間補正 1 + (...) * T を掛けたものです。括弧の中は3つの効果を合わせています。バックボーンの beta による曲がり、rho * nu のスキュー項、nu^2 のスマイル項です。アットザマネーから離れると、同じ補正にさらに2つの因子が掛かります。対数マネーネス L = ln(F/K) を含む分母と、比 z / chi(z) です。z = (nu/alpha) (FK)^((1-beta)/2) L、chi(z) = ln((sqrt(1 - 2 rho z + z^2) + z - rho) / (1 - rho)) です。z が 0 に近づくと比は 1 に近づき、式はアットザマネーの値と滑らかにつながりますが、0 / 0 を直接計算すると失敗するので、ごく小さな z は極限として扱います。
# The pieces of Hagan's formula: the time correction, the at-the-money volatility and z / chi(z)
import math
def sabr_correction(f, k, t, alpha, beta, rho, nu):
fk = f * k
return 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * fk ** ((1 - beta) / 2)) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
def sabr_atm_vol(f, t, alpha, beta, rho, nu):
return alpha / f ** (1 - beta) * sabr_correction(f, f, t, alpha, beta, rho, nu)
def z_over_chi(z, rho):
if abs(z) < 1e-7:
return 1.0
return z / math.log((math.sqrt(1 - 2 * rho * z + z ** 2) + z - rho) / (1 - rho))
print(round(sabr_atm_vol(0.03, 1.0, 0.035, 0.5, -0.3, 0.4), 6)) # 0.203877 the at-the-money volatility
print(round(z_over_chi(0.5, -0.3), 6), z_over_chi(0.0, -0.3)) # 1.103683 1.0 near 1, and exactly 1.0 at z = 0スマイルを読み、フィットさせる
権利行使価格に対してインプライド・ボラティリティをプロットすると、各パラメータの特徴がはっきり見えます。負の rho は低い権利行使価格を持ち上げ、高いものを下げます(右下がりのスキュー。株式や多くの金利に典型的)。rho = 0 なら左右対称のスマイルになります。nu が大きいと両端が上がります。beta はバックボーンを動かし、フォワードが動いたときにアットザマネーのボラティリティがどれだけ変わるかを決めます。実務では beta を慣習や過去データで固定し、残りを各満期の気配ボラティリティに較正します(次のトピック)。しばしばアットザマネーの気配から alpha を解いて、ぴったり合わせます。注意点が2つあります。この式は近似であり、長い満期や非常に低い権利行使価格では精度が落ち、負の確率密度を含意することがあります。
# The smile for three values of rho: a negative rho lifts the low strikes (downward skew)
import math
def sabr_vol(f, k, t, alpha, beta, rho, nu):
fk = f * k
log = math.log(f / k)
mid = fk ** ((1 - beta) / 2)
z = nu / alpha * mid * log
ratio = 1.0 if abs(z) < 1e-7 else z / math.log((math.sqrt(1 - 2 * rho * z + z ** 2) + z - rho) / (1 - rho))
denominator = mid * (1 + (1 - beta) ** 2 / 24 * log ** 2 + (1 - beta) ** 4 / 1920 * log ** 4)
bracket = 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * mid) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
return alpha / denominator * ratio * bracket
for rho in (-0.5, 0.0, 0.5):
print(rho, [round(sabr_vol(0.03, k, 1.0, 0.035, 0.5, rho, 0.4), 4) for k in (0.02, 0.03, 0.04)])
# one line per rho: the first value (low strike) is the highest when rho is negative and the lowest when rho is positive# A free sanity check: with beta = 1 and nu = 0 SABR is Black-Scholes, so the at-the-money volatility is alpha at every expiry
def atm(f, t, alpha, beta, rho, nu):
fk = f * f
bracket = 1 + ((1 - beta) ** 2 / 24 * alpha ** 2 / fk ** (1 - beta) + rho * beta * nu * alpha / (4 * fk ** ((1 - beta) / 2)) + (2 - 3 * rho ** 2) * nu ** 2 / 24) * t
return alpha / f ** (1 - beta) * bracket
print(atm(100.0, 0.5, 0.2, 1.0, -0.3, 0.0), atm(100.0, 5.0, 0.2, 1.0, -0.3, 0.0)) # 0.2 0.2rho は -1 と 1 の厳密に内側、nu は極端に大きくしない)、各満期を別々に、時間方向に滑らかになるように再較正します。金利が低い、あるいは負の場合は、ゼロ付近で破綻しない式の正規(バシュリエ)版を使います。- SABR は4つのパラメータで各満期のスマイルを与える。alpha(水準)、beta(バックボーン)、rho(スキュー)、nu(曲率)
- Hagan の式 = 前置因子 x
z / chi(z)x 時間補正。アットザマネーではalpha / F^(1-beta)に補正を掛けたものになり、zが 0 に近づくとz / chi(z)は 1 に近づく - 負の rho はスマイルを下に傾け、大きな nu は両端を上げる。各満期を別々に較正し、両端の裁定を確認し、ゼロ金利近くでは正規版を使う
次はモデルの較正です。モデルのパラメータを市場価格に合わせます。
ラボ:採点される内容
sabr_correctionで時間補正を加える25点sabr_atm_volでアットザマネーを読む25点z_over_chiの 0 / 0 を処理する25点sabr_implied_volでスマイルを描く25点