(SAS)使用proc模型或任何程序计算期权隐含波动率

(SAS)使用proc模型或任何程序计算期权隐含波动率,sas,Sas,我是SAS的初学者。 我想计算一个隐含波动率 我的数据集如下所示 期权\代码/看跌\看涨\ idx/标的\价格/股息\收益率/到期/期权\溢价/履约\价格/等等 A / "PUT" / 1000 / 0.5 / 13 / 5 / 980 / ....... B / "CALL" / 1000 / 0.5 / 13 / 10 / 990 / ....... 每一行都有不同的选项信息,因此我希望有最终的 解决隐含波动率后的数据集,格式如下: A / "PUT" / 1000 / 0.5 / 13

我是SAS的初学者。 我想计算一个隐含波动率

我的数据集如下所示

期权\代码/看跌\看涨\ idx/标的\价格/股息\收益率/到期/期权\溢价/履约\价格/等等

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)**
我混乱的代码看起来像这样

执行后,某些行有正确的解决方案,但有错误消息 这意味着牛顿法迭代后,某些观测值没有解

我认为来自实际exchange的数据引用了错误消息,这对我来说没有意义。那么我混乱的代码或方法从定义上来说是错误的?或者,除了计算隐含波动率,还有其他选择吗


让我知道一些引用或参考页面

我已经处理了很多这个问题。时间选项报价通常是过时的,没有意义。当您尝试求解隐含波动率时,该解在IV=0时到达边界。例如,一个简单的电话报价为5美元,但实际价格为6美元。您应该检查没有意义的值,并找到处理它们的方法

我个人喜欢你的PROC-MODEL方法,我会使用PROC-FCMP将它们放入我自己的函数中,并使用数据步骤。FCMP中提供了一个SOLVE函数,可以为您找到根

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;
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;