Dear R-users I am trying to find a value for the risk free rate minimizing the difference between a BS call value with impl. volatilities minus the market price of a call (assuming this is just the average bid ask price) Here is my data: http://r.789695.n4.nabble.com/file/n3747509/S%26P_500_calls%2C_jan-jun_2010.csv S%26P_500_calls%2C_jan-jun_2010.csv S0 <- 1136.03 q <- 0.02145608 S0 <- spot[10,6] S0 strike <- marketdata[1:460,9] T <- marketdata[1:460,17]/365 #Notice the T is measured in years now implvol <- marketdata[1:460,12] ask <- marketdata[1:460,10] bid <- marketdata[1:460,11] mid_bidask <- (bid + ask) /2 r <- 0.020 And my code: BS_Call <- function(S0, K, T, r, sigma, q) # Which works fine { sig <- sigma * sqrt(T) d1 <- (log (S0/K) + (r - q + sigma^2/2) * T ) / sig d2 <- d1 - sig Presentvalue <- exp(-r*T) return (S0 * exp(-q*T) * pnorm(d1) - K*Presentvalue*pnorm(d2)) } #I now define the function I later want to minimize with respect to r difference <- function (S0, K, T, r, sigma, q, mid) { return(BS_Call(S0, strike, T, r, sigma, q)- mid_bidask)) } # which gives 460 values as it should, as T = 460 f <- function(x) difference(S0, strike, T, x, implvol, q, mid_bidask) # If I now run nlminb(start=r, f) $par [1] -0.9800001 $objective [1] -395.85 $convergence [1] 0 $iterations [1] 2 $evaluations function gradient 3 4 $message [1] "relative convergence (4)" # But the risk free interest rate should not be negative, and the objective function gives an negative values when in should be minizimed to 0. # I then try adding the following to nlminb, as I understand it to set the objective function to non-negative nlminb(start=r, f, control = list(rel.tol=1e-20)) $par [1] 0.02 $objective [1] 0 $convergence [1] 1 $iterations [1] 0 $evaluations function gradient 0 0 $message [1] "'control' component 'rel.tol' = 1e-20, is out of range" #which always gives me the initial value I have tried to read other relevant R help posts, but nothing I do seems to work. Is there anyone who can help me with what I am doing wrong? I have also try summing the difference function, but the same errors occur. Thanks Rikke -- View this message in context: http://r.789695.n4.nabble.com/Calibrating-the-risk-free-interest-rate-using-nlminb-tp3747509p3747509.html Sent from the R help mailing list archive at Nabble.com.
Calibrating the risk free interest rate using nlminb
5 messages · Newbie, Berend Hasselman
Newbie wrote:
Dear R-users I am trying to find a value for the risk free rate minimizing the difference between a BS call value with impl. volatilities minus the market price of a call (assuming this is just the average bid ask price) Here is my data: http://r.789695.n4.nabble.com/file/n3747509/S%26P_500_calls%2C_jan-jun_2010.csv S%26P_500_calls%2C_jan-jun_2010.csv S0 <- 1136.03 q <- 0.02145608 S0 <- spot[10,6] S0 strike <- marketdata[1:460,9] T <- marketdata[1:460,17]/365 #Notice the T is measured in years now implvol <- marketdata[1:460,12] ask <- marketdata[1:460,10] bid <- marketdata[1:460,11] mid_bidask <- (bid + ask) /2 r <- 0.020 And my code: BS_Call <- function(S0, K, T, r, sigma, q) # Which works fine { sig <- sigma * sqrt(T) d1 <- (log (S0/K) + (r - q + sigma^2/2) * T ) / sig d2 <- d1 - sig Presentvalue <- exp(-r*T) return (S0 * exp(-q*T) * pnorm(d1) - K*Presentvalue*pnorm(d2)) } #I now define the function I later want to minimize with respect to r difference <- function (S0, K, T, r, sigma, q, mid) { return(BS_Call(S0, strike, T, r, sigma, q)- mid_bidask)) } # which gives 460 values as it should, as T = 460 f <- function(x) difference(S0, strike, T, x, implvol, q, mid_bidask) # If I now run nlminb(start=r, f) $par [1] -0.9800001 $objective [1] -395.85 $convergence [1] 0 $iterations [1] 2 $evaluations function gradient 3 4 $message [1] "relative convergence (4)" # But the risk free interest rate should not be negative, and the objective function gives an negative values when in should be minizimed to 0. # I then try adding the following to nlminb, as I understand it to set the objective function to non-negative nlminb(start=r, f, control = list(rel.tol=1e-20)) $par [1] 0.02 $objective [1] 0 $convergence [1] 1 $iterations [1] 0 $evaluations function gradient 0 0 $message [1] "'control' component 'rel.tol' = 1e-20, is out of range" #which always gives me the initial value I have tried to read other relevant R help posts, but nothing I do seems to work. Is there anyone who can help me with what I am doing wrong? I have also try summing the difference function, but the same errors occur. Thanks Rikke
How did you read the .csv? Where does variable "spot" come from? Berend -- View this message in context: http://r.789695.n4.nabble.com/Calibrating-the-risk-free-interest-rate-using-nlminb-tp3747509p3747601.html Sent from the R help mailing list archive at Nabble.com.
I used: marketdata <- read.csv(file="S&P 500 calls, jan-jun 2010.csv", header=TRUE, sep=";") after changing my directory to where the file is saved. The data imported should be correct. The spot is equal to S0, I typed it double in the post, sorry for that. So S0 = 1136.03 is the spot -- View this message in context: http://r.789695.n4.nabble.com/Calibrating-the-risk-free-interest-rate-using-nlminb-tp3747509p3747688.html Sent from the R help mailing list archive at Nabble.com.
Newbie wrote:
I used: marketdata <- read.csv(file="S&P 500 calls, jan-jun 2010.csv", header=TRUE, sep=";") after changing my directory to where the file is saved. The data imported should be correct. The spot is equal to S0, I typed it double in the post, sorry for that. So S0 = 1136.03 is the spot
1. it seems that your function difference contains an error: Superfluous
closing )
2. difference contains another possible error: it is not using the last
argument mid
It's using the global variable mid_bidask.
It should read
difference <- function (S0, K, T, r, sigma, q, mid)
{
return(BS_Call(S0, strike, T, r, sigma, q)- mid)
}
Your function returns a vector of length 460 as you correctly said.
But in the documentation of nlminb it clearly states that the objective
must return a scalar value.
(NB. It doesn't seem to check?)
So in function f you should at least reduce the vector to a scalar.
In this case I would minimize the sum of the differences squared to prevent
the optimization routine
from getting negative values for differences.
So define f as follows
f <- function(x) sum(difference(S0, strike, T, x, implvol, q, mid_bidask)^2)
and then
nlminb(start=r, f)
gives
nlminb(start=r, f)
$par
[1] 0.01268534
$objective
[1] 3140.738
$convergence
[1] 0
$iterations
[1] 5
$evaluations
function gradient
8 5
$message
[1] "relative convergence (4)"
If you try nlm and optim (with method="BFGS) you'll get similar results.
It's up to you to decide if the outcome is plausible/acceptable.
Berend
--
View this message in context: http://r.789695.n4.nabble.com/Calibrating-the-risk-free-interest-rate-using-nlminb-tp3747509p3747758.html
Sent from the R help mailing list archive at Nabble.com.
thank you for your help! kinds Rikke -- View this message in context: http://r.789695.n4.nabble.com/Calibrating-the-risk-free-interest-rate-using-nlminb-tp3747509p3748442.html Sent from the R help mailing list archive at Nabble.com.