Estoy tratando de escribir un R script que tome las calls y puts de 25d junto con ATM y cree un vol. smile.
He intentado utilizar el método propuesto por Castagna y Mercurio para calcular la volatilidad de la vanna-volga. La expresión propuesta, para un Call europeo es:
C(K) = CBS(K)+ w(K1) [CMkt(K1)-CBS(K1)]+w(K3) [CMkt(K3)-CBS(K3)]
donde w1 y w3 se calculan según el código siguiente.
BSoption <- function(type, S, X, t, r, rf, v)
{
d1 <- (log(S/X) + (r-rf + 0.5 * v^2) * t)/(v * sqrt(t))
d2 <- d1 - v*sqrt(t)
if (type == "c"){
pnorm(d1)*S*exp(-rf*t) - pnorm(d2)*X*exp(-r*t)
} else {
pnorm(-d2)*X*exp(-r*t) - pnorm(-d1)*S*exp(-rf*t)
}
}
vega <- function(S, X, t, r, rf, v)
{
d1 <- (log(S/X) + (r -rf + 0.5 * v^2) * t)/(v * sqrt(t))
Np <- (exp(-d1^2/2))/ sqrt(2 * pi)
(S * exp(-rf*t)*sqrt(t) * Np)/100
}
implied.vol <-
function(type, S, X, t, r, rf, market){
sig <- 0.20
sig.up <- 1
sig.down <- 0.001
count <- 0
err <- BSoption(type, S, X, t, r, rf, sig) - market
## repeat until error is sufficiently small or counter hits 1000
while(abs(err) > 0.00001 && count<1000){
if(err < 0){
sig.down <- sig
sig <- (sig.up + sig)/2
}else{
sig.up <- sig
sig <- (sig.down + sig)/2
}
err <- BSoption(type, S, X, t, r, rf, sig) - market
count <- count + 1
}
## return NA if counter hit 1000
if(count==1000){
return(NA)
}else{
return(sig)
}
}
S <- 0.906
X <- seq(0.7,1.2,0.01)
t <- 1
r <- 0.0507
rf <- 0.047#-log(0.9945049)/t
ATMcost <- BSoption("c",S,XATM,t,r,rf,vATM)
v25p <- 0.13575#vv.inputs$Vol[vv.inputs$Skew == -0.25]
vATM <- 0.132#vv.inputs$Vol[vv.inputs$Skew == 0.0]
v25c <- 0.13425#vv.inputs$Vol[vv.inputs$Skew == 0.25]
X25p <- 0.8350575#BSStrikeFromDelta("p",S,v25p,t,r,rf,0.25)
XATM <- S
X25c <- 1.000846#BSStrikeFromDelta("c",S,t,r,v25c,rf,0.25)
w1 <- (vega(S,X,t,r,rf,vATM)/vega(S,X25p,t,r,rf,v25p))*((log(XATM/X)*log(X25c/X))/(log(XATM/X25p)*log(X25c/X25p)))
w2 <- (vega(S,X,t,r,rf,vATM)/vega(S,XATM,t,r,rf,vATM))*((log(X/X25p)*log(X25c/X))/(log(XATM/X25p)*log(X25c/XATM)))
w3 <- (vega(S,X,t,r,rf,vATM)/vega(S,X25c,t,r,rf,v25c))*((log(X/X25p)*log(X/XATM))/(log(X25c/X25p)*log(X25c/XATM)))
VV.price <- ATMcost + w1*(BSoption("c",S,X25p,t,r,rf,v25p)-BSoption("c",S,X25p,t,r,rf,vATM)) + w3*(BSoption("c",S,X25c,t,r,rf,v25c)-BSoption("c",S,X25c,t,r,rf,vATM))
VV.vol <- 0
for(i in 1:length(X)){
VV.vol[i] <- implied.vol("c",S,X[i],t,r,rf,VV.price[i])
}
plot(X,VV.price)
plot(X,VV.vol)
Como puede ver, calculo el precio vanna-volga de la opción, que es consistente con las comillas dadas pero, cuando trazo la "sonrisa" de la volatilidad, en realidad no es una sonrisa en absoluto y no estoy seguro de dónde me estoy equivocando.
Cualquier ayuda es muy apreciada.