Calibrating VIX option data to model - lsqnonlin problem

Im new to MatLab and in the process of learning it. Currently im trying to calibrate VIX option market data to Mean-reverting volatility process. To begin with im just trying to get an output without errors.
I have coded this script and the following function: ___________________________________________________________________________ clear all
load('callopt.mat');
global K; global T; global r; global market;
%K=strike, T=time to expiration in year fraction %market=market option prices
K=callopt(:,3); T=callopt(:,2); market=callopt(:,10); r=0.01;
x0=[2,2,2,2];
[x,resnorm]=lsqnonlin(@myfun,x0); ___________________________________________________________________________
function F=myfun(bet,rev,V,sig)
global K; global T; global r; global market;
vega=4*rev*bet./(sig^2);
gam=(4*bet)./((sig^2)*(1-exp(-bet*T)));
lambda=vega*exp(-bet*T)*V;
model=exp(-r.*T).*(exp(-bet.*T).*V.*ncx2cdf(gam.*K,vega+4,lambda))+rev.*(1-exp(-bet.*T)).*ncx2cdf(gam.*K,vega+2,lambda)-K.*ncx2cdf(gam.*K,vega,lambda);
F=(market-model); ___________________________________________________________________________
This is the complete error i receive: Error using myfun (line 5) Not enough input arguments.
Error in lsqnonlin (line 197) initVals.F = feval(funfcn{3},xCurrent,varargin{:});
Error in meanrev (line 15) [x,resnorm]=lsqnonlin(@myfun,x0); Caused by: Failure in initial user-supplied objective function evaluation. LSQNONLIN cannot continue.
Can someone help?

 Accepted Answer

lsqnonlin does not know that myfun takes 4 arguments, it expects it to just take one. You can get around this using an 'anonymous' function call like so:
[x,resnorm]=lsqnonlin(@(argthatchanges) myfun(argthatchanges,rev,V,sig), x0);
Note that I don't know which of your argument your actually solving for, so you may need to change about. Read about anonymous functions to understand better how this works.
Incidentally it is good programming practice to avoid the use of global variables unless absolutely necessary.

5 Comments

Thank you very much for your quick answer. It is very appreciated.
Actually im trying to solve for all input arguments simultanouosly. Let me take a step back and explain what i want.
I have the following Stochastic Differential Equation (SDE) to explain the evolution of the VIX:
dV=beta(m-V)dt+sigma*sqrt(V)*dW (I have changed the names in my code becauce i found out that the names were already used in MatLab build in functions)
where dW is Brownian Motion.
The closed form solution to this SDE with boundary conditions of a call option is calculated as "Model" in my function.
The loss function to be minimized is: L(theta) = sum((Market - Model(theta))^2)
where theta is a vector of parameters to be estimated: theta=(beta,m,V,sigma).
I actually didnt intend to use global variables, but I couldnt figure out how refer to a matrix from inside a function. Hence, i made them global. If you know how I can get around that problem it is very much appreciated as well.
Hope this clarified what i wanted my script to be able to do and that you can help.
if theta is the vector of parameters to be solved myfun must accept this vector as an input e.g:
function F=myfun(theta)
bet = theta(1)
rev = theta(2)
V = theta(3)
sig = theta(4)
global K; global T; global r; global market;
vega=4*rev*bet./(sig^2);
gam=(4*bet)./((sig^2)*(1-exp(-bet*T)));
lambda=vega*exp(-bet*T)*V;
model=exp(-r.*T).*(exp(-bet.*T).*V.*ncx2cdf(gam.*K,vega+4,lambda))+rev.*(1-exp(-bet.*T)).*ncx2cdf(gam.*K,vega+2,lambda)-K.*ncx2cdf(gam.*K,vega,lambda);
F=(market-model);
You can then get around the global variable problem using anonymous functions where your function would look like:
F=myfun(theta, K, T, r, market)
and call to lsqnonlin
[x,resnorm]=lsqnonlin(@(theta) myfun(theta,K,T,r,market), x0);
so no globals required
Thank you very much! I think this will solve my problem. I will try and implement it later tonight.
I tried the first thing you suggested and that worked great.
Then i tried to implement the anonymous function, but i couldnt get that to work.
My codes now looks like this:
________________________________________________
clear all
load('callopt.mat');
%K=strike, T=time to expiration in year fraction
%market=market option prices
K=callopt(:,3);
T=callopt(:,2);
market=callopt(:,10);
r=0.01;
x0=[1,1,1,1];
[x,resnorm]=lsqnonlin(@(theta)myfun(theta,K,T,r,market,x0));
____________________________________________________
function F=myfun(theta,K,T,r,market)
bet=theta(1);
rev=theta(2);
V=theta(3);
sig=theta(4);
vega=4*rev*bet./(sig^2);
gam=(4*bet)./((sig^2)*(1-exp(-bet*T)));
lambda=vega*exp(-bet*T)*V;
model=exp(-r.*T).*(exp(-bet.*T).*V.*ncx2cdf(gam.*K,vega+4,lambda))+rev.*(1-exp(-bet.*T)).*ncx2cdf(gam.*K,vega+2,lambda)-K.*ncx2cdf(gam.*K,vega,lambda);
F=(market-model);
___________________________________________________________________
Error using lsqnonlin (line 161)
The input to LSQNONLIN should be either a structure with
valid fields or consist of at least two arguments.
Error in meanrev (line 15)
[x,resnorm]=lsqnonlin(@(theta)myfun(theta,K,T,r,market,x0));
______________________________________________________
Did i miss something?
Another question I have is, if it is possible to weight each of the numbers in the vector F differently? It is market practice to weight each market price by its bid-ask spread.
The loss function to minimized will then look like this: L(theta) = sum(w_i(Market - Model(theta))^2)
where w_i is each individual weight.
I thought of just expanding F to be F=w_i(market-model), but this would be unfortunate as I understand lsqnonlin minimize the square of F and I dont want the weights to be squared as well. If you know what i mean?
To the question regarding weights i guess i could just take sqrt(w_i)*(Market-Model) and then when running the lsqnonlin it would look as i want it?

Sign in to comment.

More Answers (0)

Products

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!