Matlab中的隐含波动率

时间:2013-11-04 03:04:07

标签: matlab volatility

我正在尝试使用Matlab(2012b)中的Black-Scholes公式来计算隐含波动率,但不知何故存在一些执行价格问题。 例如,blsimpv(1558,1440,0.0024,(1/12),116.4)将返回NaN。 我认为它可能是该功能的一些问题,因此在互联网上搜索其他一些matlab脚本并根据我的自定义需求进行定制,但不幸的是我仍然无法返回有效的隐含波动率。

function sigma=impvol(C,S,K,r,T)

   %F=S*exp((r).*T);
   %G=C.*exp(r.*T);

   %alpha=log(F./K)./sqrt(T);
   %beta=0.5*sqrt(T);

   %a=beta.*(F+K);
   %b=sqrt(2*pi)*(0.5*(F-K)-G);
   %c=alpha.*(F-K);

   %disc=max(0,b.^2-4*a.*c);
   %sigma0=(-b+sqrt(disc))./(2*a);

   i=-1000;
   while i<=5000
      sigma0=i/1000;
      sigma=NewtonMethod(sigma0);
      if sigma<=10 && sigma>=-10
          fprintf('This is sigma %f',sigma)
      end
      i=i+1;
    end
end

function s1=NewtonMethod(s0)

    s1=s0;
    count=0;
    f=@(x) call(S,K,r,x,T)-C;
    fprime=@(x) call_vega(S,K,r,x,T);

    max_count=1e4;

    while max(abs(f(s1)))>1e-7 && count<max_count
        count=count+1;
        s0=s1;
        s1=s0-f(s0)./fprime(s0);

    end

end

end

function d=d1(S,K,r,sigma,T)
   d=(log(S./K)+(r+sigma.^2*0.5).*(T))./(sigma.*sqrt(T));
end

function d=d2(S,K,r,sigma,T)
   d=(log(S./K)+(r-sigma.^2*0.5).*(T))./(sigma.*sqrt(T));
end

function p=Phi(x)
  p=0.5*(1.+erf(x/sqrt(2)));
end

function p=PhiPrime(x)
   p=exp(-0.5*x.^2)/sqrt(2*pi);
end

function c=call(S,K,r,sigma,T)
  c=S.*Phi(d1(S,K,r,sigma,T))-K.*exp(-r.*(T)).*Phi(d2(S,K,r,sigma,T));
end

function v=call_vega(S,K,r,sigma,T)
   v=S.*PhiPrime(d1(S,K,r,sigma,T)).*sqrt(T);
end

然而,运行impvol(116.4,1558,1440,0.0024,(1/12))将遗憾地返回值'Inf'。不知怎的,Newton-Rhapson方法的问题没有收敛,但我对如何解决这个问题毫无头绪。有谁知道如何解决这个问题或知道如何计算隐含波动率?

提前感谢你的帮助! 亲切的问候,

亨克

3 个答案:

答案 0 :(得分:2)

我肯定会建议这段代码:Fast Matrixwise Black-Scholes Implied Volatility 它能够一次性计算整个表面 - 我的经验 - 我发现它比blsimpv()impvol()更可靠,这是matlab中实现的其他功能。

答案 1 :(得分:1)

Newton-Rhapson方法不适用于隐含波动率。您应该使用二分法(不确定它在Matlab中的使用方式)。它在http://en.wikipedia.org/wiki/Bisection_method中描述。为了完整起见,它以这种方式工作:

1)选择任意高(不可能)的波动率,如高= 200%/年。

2)选择尽可能低的波动率(低= 0%)。

2a)计算0%波动率的期权溢价,如果实际溢价低于该波动率,则表示负波动率(&#34;不可能&#34;)。

3)虽然未找到隐含波动率:

3.1)如果&#34;高&#34;和&#34;低&#34;非常接近(例如,等于小数点后五位),其中一个是你的隐含波动率。如果不是......

3.2)计算&#34; high&#34;之间的平均值。和&#34;低&#34;。平均=(高+低)/ 2

3.3)计算平均波动率的期权溢价。

3.4)如果实际溢价高于p(平均值),则使得min = avg,因为隐含波动率必须介于avg和max之间。

3.4a)如果实际溢价低于p(平均值),则设为max = avg,因为隐含的卷必须介于min和avg之间。

bisect的主要优点是你必须选择一个最大值,因此你的函数不会发现隐含的波动率大于此值。但是,200%/年的东西应该足够高,以便在现实世界中使用。

我使用了另一种更像Newton方法的方法,因此不限于范围,因为vega是一种衍生物,但具有线性化&#34;修复以避免由于小维加斯造成的狩猎和失败:

def implied_volatility(type, premium, S, K, r, s_dummy, t):
    if S <= 0.000001 or K <= 0.000001 or t <= 0.000001 or premium <= 0.000001:
        return 0.0

    s = 0.35

    for cycle in range(0, 120):
        ext_premium = type(S, K, r, s, t)
        if abs(premium - ext_premium) < 0.005:
            return s
        ext_vega = type.vega(S, K, r, s, t)
        # print S, K, r, s, t, premium, ext_premium, ext_vega
        if ext_vega < 0.0000001:
            # Avoids zero division if stuck 
            ext_vega = 0.0000001

        s_new = s - (ext_premium - premium) / ext_vega
        if abs(s_new - s) > 1.00:
            # estimated s is too different from previous;
            # it is better to go linearly, since
            # vega is too small to give a good guess
            if s_new > s:
                s += 1.0
            else:
                s -= 1.0
        else:
            s = s_new

        if s < 0.0:
            # No volatility < 0%
            s = 0.0001
        if s > 99.99:
            # No point calculating volatilities > 9999%/year
            return 100.0

    return 0.0

尽管如此,我认为bisect是你最好的选择。

答案 2 :(得分:0)

我创建了一个简单的函数,如果blsimpv的输出是NaN,则会进行一种试验和错误计算。这对我来说显着减慢了计算时间,但它总能给我一个理想的结果。

该功能显示在

下面使用
BSIVC(t,i)= blsimpv(S(t,i),K,r,tau(t),HestonCiter(t,i))
 if isnan(BSIVC(t,i));
  BSIVC(t,i)= secondIVcalc(HestonCiter(t,i),S(t,i),K,r,q,tau(t))
 end

该功能本身如下所述:

function IV= secondIVcalc(HestonC,S,K,r,q,T)
lowCdif = 1;
a=0;
while lowCdif>0.0001
a= a+0.00001
lowCdif = HestonC - BSCprice(S,K,r,q,a,T);
end
IV= a;
end

请注意,BSCprice不是matlab中的内置函数。

只是为了让代码更清晰 - BSCprice的格式为BSCprice(标的资产价格,行使价,利率,股息收益率,隐含金额,到期时间)。