2013-11-04 2 views
2

Matlab (2012b)의 Black-Scholes 공식을 사용하여 내재 변동성을 계산하려고하지만 일부 파업 가격에 문제가 있습니다. 예를 들어 blsimpv (1558,1440,0.0024, (1/12), 116.4)는 NaN을 반환합니다. 아마 함수에 문제가있을 것이라고 생각하여 인터넷에서 다른 MATLAB 스크립트를 검색하고 사용자 정의 요구 사항에 맞게 사용자 정의했지만 불행히도 유효한 암시 적 변동성을 반환 할 수는 없습니다.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; 
    [email protected](x) call(S,K,r,x,T)-C; 
    [email protected](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 방법의 문제가 있습니다. 그러나 저는 이것을 해결하는 방법을 알지 못합니다. 누구든지이 문제를 해결하는 방법을 알고 있거나 묵시적 변동성을 계산하는 방법을 알고 있습니까?

이미 도움을 주셔서 감사합니다. 종류와 관련,

헹크 내재 변동성 잘 작동하지 않습니다

+0

이것은 상당히 많은 코드입니다. 문제를 일으키는 부분을 분리 할 수 ​​있습니까?/예상 한대로하지 않습니까? –

답변

1

뉴턴 - Rhapson 방법. 이분법을 사용해야합니다 (Matlab에서 어떻게 사용되는지 모르겠습니다). 이것은 http://en.wikipedia.org/wiki/Bisection_method에 설명되어 있습니다. 완전성을 위해 다음과 같이 작동합니다.

1) 높은 = 200 %/년과 같이 임의의 높은 (불가능한) 변동성을 선택하십시오.

2) 가능한 최저 휘발성 (낮은 = 0 %)을 선택하십시오.

2a) 0 % 변동성에 대한 옵션 프리미엄을 계산하십시오. 실제 프리미엄이 그보다 낮 으면 음의 변동성 ("불가능")을 의미합니다. 내재 변동성이 발견되지 동안

3) :

3.1)이 "저", "높은"및 아주 가까운 (예를 들어)이 5 소수점까지 동일, 둘 중 하나는 당신의 내재 변동성이다. 그렇지 않은 경우 ...

3.2 "높음"과 "낮음"사이의 평균을 계산합니다. 평균 = (높음 + 낮음)/2

3.3) 평균 변동성에 대한 옵션 프리미엄을 계산합니다.

3.4) 실제 보험료가 p (avg)보다 높으면 내재 변동성이 평균과 최대 사이에 있어야하므로 min = avg로 만듭니다.

3.4a) 실제 보험료가 p (avg)보다 낮은 경우에는 묵시적 권이 최소값과 평균값 사이에 있어야하므로 max = avg로 만듭니다.

bisect의 주된 단점은 최대 값을 선택해야한다는 것입니다. 따라서 함수는 암시 적 휘발성을 더 크게 찾을 수 없습니다. 그러나 200 %/년과 같은 것은 실제 사용을 위해 충분히 높아야합니다.

I 인해 작은 베가스 사냥 고장을 피하기 위해 더 따라서 베가 유도체이기 때문에, 범위에 한정되지 뉴턴 방법처럼 또 다른 방법을 사용하지만, "선형화"수정과 :

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 

아직도, 나는 이등분이 당신의 최선의 방법이라고 생각합니다.

2

나는 확실히이 코드를 제안 : Fast Matrixwise Black-Scholes Implied Volatility 한 번에 전체 표면을 계산할 수 있고 - 내 경험을 - 내가 훨씬 더 안정적인 blsimpv() 또는 MATLAB에서 구현 다른 기능입니다 impvol() 이상 발견했다.

+0

Li 2006 논문의 코드를 링크 해 주셔서 감사합니다! 매우 도움이됩니다. –

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 형식입니다.