我是初学者使用SAS。 我想计算隐含波动率。
我的数据集如下所示
Option_code / put_call_idx / underlying_price / dividend_yield / maturity / option_premium / strike_price / etc.
A / "PUT" / 1000 / 0.5 / 13 / 5 / 980 / .......
B / "CALL" / 1000 / 0.5 / 13 / 10 / 990 / .......
每一行都有不同的选项信息,所以我希望得到我的决赛 解决隐含波动率后的数据集,其形式如下:
A / "PUT" / 1000 / 0.5 / 13 / ...... / **0.15 (IV for option A)**
B / "CALL" / 1000 / 0.5 / 13 / ...... / **0.18 (IV for option B)**
我的凌乱代码看起来像这样
proc model data = INPUT noprint;
exogenous ksp200 ksp200_div ttm strike_prc rf;
endogenous iv;
n_1 = log(ksp200 * exp((rf - ksp200_div) * (ttm/250)) / strke_price
.... other Black-Scholes Formula input .......
0 = abs(model price - market price)
solve iv / maxiter = 100 converge = 0.1 out = iv_root;
by option_code;
run;
执行某些行后,有正确的解决方案但有错误消息 意思是一些观察在牛顿方法迭代之后没有解决方案。
我认为来自实际交换的数据引用了错误消息对我没有意义。所以我的杂乱的代码或方法定义错了?还是有其他计算隐含波动率的方法?
让我知道一些引用或参考页面。
答案 0 :(得分:0)
我经常处理这个问题。通常时间选项报价是陈旧的,没有意义。当您尝试求解隐含波动率时,解决方案会在IV = 0时达到界限。例如,一个简单的电话报价为5美元,但这笔钱是6美元。您应该检查没有意义的值并找到处理它们的方法。
我喜欢你的PROC MODEL
方法我个人会使用PROC FCMP
将它们放入我自己的函数中并使用数据步骤。 SOLVE
中有一个FCMP
函数可以为您找到根。
proc fcmp outlib=work.fns.options;
/*Taken from Wikipedia - BS with a continous dividend*/
function optPrc(type $, K,S,q,r,ttm,vol);
d1 = (1/(vol*sqrt(ttm)))*(log(S/K)+(r-q+.5*vol**2)*ttm);
d2 = d1-(vol*sqrt(ttm));
F=S*exp((r-q)*ttm);
ert = exp(-r*ttm);
prc = .;
if upcase(substr(type,1,1)) = "C" then
prc = ert*(F*cdf('NORMAL',d1,0,1)-K*cdf('NORMAL',d2,0,1));
else if upcase(substr(type,1,1)) = "P" then
prc = ert*(K*cdf('NORMAL',-d2,0,1)-F*cdf('NORMAL',-d1,0,1));
return(prc);
endsub;
/*IV Solver*/
function opt_iv(type $, K,S,q,r,ttm,opt_prc);
iv = .;
prc = optPrc(type , K,S,q,r,ttm,1e-8);
if opt_prc < prc then do;
PUT "ERROR: Option Price out of bounds" opt_prc= prc= "at 0 vol";
end;
else do;
array opts[5] initial abconv relconv maxiter status
(.5 .001 1.0e-6 100 -1);
iv = solve("optPrc",opts, opt_prc, type , K, S, q, r, ttm, .);
if status ^= 0 then
PUT "ERROR: Problem Solving." STATUS=;
end;
return (iv);
endsub;
run;
quit;
options cmplib=(work.fns);
data test;
Type = "PUT";
Underlying = 1000;
Div_Yield = 0.5;
Maturity = 13;
Opt_Prc=5;
Strike=980;
output;
Type = "CALL";
Underlying = 1000;
Div_Yield = 0.5;
Maturity = 13;
Opt_Prc=10;
Strike=990;
output;
/*This obviously is bad - call is $10 in the money, but quoted at 5*/
Type = "CALL";
Underlying = 1000;
Div_Yield = 0;
Maturity = 13;
Opt_Prc=5;
Strike=990;
output;
/*This obviously is put - put is $10 in the money, but quoted at 5*/
Type = "PUT";
Underlying = 1000;
Div_Yield = 0;
Maturity = 13;
Opt_Prc=5;
Strike=1010;
output;
run;
data test2;
set test;
iv= opt_iv(type, Strike,Underlying,Div_Yield/100,0.005,Maturity/250,Opt_Prc);
run;