美式期权定价—BAW模型(MATLAB与VBA代码)

论坛 期权论坛 期权     
voltrader   2018-5-25 03:35   37568   2
BAW模型
一、MATLAB代码
% Barone-Adesi and Whaley quadratic approximation to vanilla options

clc; clear;

% Input the option parameters
S = 90;          % Spot Price
K = 100;          % Strike Price
T = 0.5;         % Maturity
r = 0.1;         % Risk free rate
q = 0.1;         % Dividend yield
v = 0.25;         % Volatility
IsCall = 1;       %



% Find the European and American prices, and the critical stock value S*
fprintf(' Spot    Euror   Amer  Premium\n')
fprintf('--------------------------------------- \n')
%[Sx,EuroPrice,AmerPrice]
[Sx,EuroPrice,AmerPrice] = BAWPrice(S,K,r,q,v,T,IsCall);
  fprintf('%8.4f %8.4f %8.4f %8.4f\n',...
    Sx,EuroPrice,AmerPrice,AmerPrice-EuroPrice);

fprintf('--------------------------------------- \n')
function [Sx,EuroPrice,AmerPrice]= BAWPrice(S,K,r,q,sigma,T,IsCall)

% Barone-Adesi and Whaley Method for American options
% Finds the American prices as the European prices + premium
% Premium is based on Sx, the critical stock price
% S = Spot price
% K = Strike price
% r = Risk free rate
% q = Dividend yield
% v = Volatility
% T = Maturity
% PutCall = 'C'all or 'P'ut


% Functions for Black Scholes call and put
BSCall = @(s,K,r,q,sigma,T) s.*exp(-q.*T).*normcdf((log(s./K) + (r-q+sigma.^2./2).*T)./sigma./sqrt(T)) - K.*exp(-r.*T).*normcdf((log(s./K) + (r-q+sigma.^2./2).*T)./sigma./sqrt(T) - sigma.*sqrt(T));
BSPut = @(s,K,r,q,sigma,T) K.*exp(-r.*T).*normcdf(-(log(s./K) + (r-q+sigma.^2./2).*T)./sigma./sqrt(T) + sigma.*sqrt(T)) - s.*exp(-q.*T).*normcdf(-(log(s./K) + (r-q+sigma.^2./2).*T)./sigma./sqrt(T));


% Quadratic approximation
switch IsCall
case 1
  EuroPrice = BSCall(S,K,r,q,sigma,T);
  start = S;
  [Sx,~] = fminsearch(@(s) findSx(s,K,r,q,sigma,T,IsCall), start);
  d1 = (log(Sx/K) + (r-q+sigma^2/2))/sigma/sqrt(T);
  n = 2*(r-q)/sigma^2;
  k = 2*r/sigma^2/(1-exp(-r*T));
  q2 = (1-n+sqrt((n-1)^2+4*k))/2;
  A2 = Sx*(1-exp(-q*T)*normcdf(d1))/q2;
  if SSx
   AmerPrice = EuroPrice + A1*(S/Sx)^q1;
  else
   AmerPrice = K - S;
  end
end


二、VBA代码
Public Function BWAmerican(S, k, T, R, q, Sigma As Double, IsCall As Boolean) As Double
  '===========================================================
  'BAW定价计算模块
  '输入参数:
  '——→ S:标的价
  '——→ K:执行价
  '——→ T:到期期限
  '——→ r:无风险利率
  '——→ q:红利率
  '——→ Sigma:波动率
  '——→ IsCall:是否看涨期权,输入True为看涨,输入False为看跌
  '
  '输出参数
  '——→ BWAmerican:美式期权价格
  '===========================================================

  Dim dt As Double
  Dim A1 As Double, a2 As Double, b As Double, A As Double
  Dim h As Double, L1 As Double, L2 As Double
  Dim D1 As Double, Sc As Double
   
  b = 2 * (R - q) / Sigma ^ 2 - 1
  A = 2 * R / Sigma ^ 2
  h = 1 - Exp(-R * T)
  L1 = (-b - Sqr(b ^ 2 + 4 * A / h)) / 2
  L2 = (-b + Sqr(b ^ 2 + 4 * A / h)) / 2
  dt = Sigma * Sqr(T)

  Select Case IsCall
  
  Case True  '//看涨
  If q = 0 Then
    BWAmerican = BSprice(S, k, T, R, q, Sigma, True)
  Else
    Sc = Bisectional_call(S, k, T, R, q, Sigma)
    D1 = (Log(Sc / k) + (R - q + 0.5 * Sigma ^ 2) * T) / dt
    a2 = (1 - Exp(-q * T) * Application.NormSDist(D1)) * (Sc / L2)
    If S < Sc Then
      BWAmerican = BSprice(S, k, T, R, q, Sigma, True) + a2 * (S / Sc) ^ L2
    Else
      BWAmerican = S - k
    End If
  End If

  Case False '//看跌

  Sc = Bisectional_put(S, k, T, R, q, Sigma)
  D1 = (Log(Sc / k) + (R - q + Sigma ^ 2 / 2) * T) / dt
  A1 = -(1 - Exp(-q * T) * Application.NormSDist(-D1)) * (Sc / L1)

  If S > Sc Then
    BWAmerican = BSprice(S, k, T, R, q, Sigma, False) + A1 * (S / Sc) ^ L1
  Else
    BWAmerican = k - S
  End If

  End Select
End Function
Private Function Bisectional_call(S, k, T, R, q, Sigma As Double) As Double


  Dim n As Integer
  Dim dt As Double
  Dim Sx As Double, Su As Double, Sl As Double, Suu As Double
  Dim D1 As Double, d2 As Double, L2 As Double
  Dim err As Double, c1 As Double, c2 As Double
  Dim b As Double, A As Double, h As Double
  Dim N1 As Double, N2 As Double, E_st As Double
  Dim IterationCountE As Double
   
  dt = Sigma * Sqr(T)
  D1 = (Log(S / k) + (R - q + Sigma ^ 2 / 2) * T) / dt
  d2 = D1 - dt
  
  N1 = Application.NormSDist(D1)
  N2 = Application.NormSDist(d2)

  E_st = S * Exp((R - q) * T) * N1 / N2
  
  Su = E_st ' Guess the high bound
  Sl = S ' Guess the low bound
  Suu = Su
  
  b = 2 * (R - q) / Sigma ^ 2 - 1
  A = 2 * R / Sigma ^ 2
  h = 1 - Exp(-R * T)
  L2 = (-b + Sqr(b ^ 2 + 4 * A / h)) / 2
   
Start_Iteration:
  
  IterationCountE = 0.000000001
  While (Su - Sl) > IterationCountE
   Sx = (Su + Sl) / 2
   
   D1 = (Log(Sx / k) + (R - q + Sigma ^ 2 / 2) * T) / dt
   c1 = Sx - k
   c2 = BSprice(Sx, k, T, R, q, Sigma, True) + (1 - Exp(-q * T) * Application.NormSDist(D1)) * Sx / L2
   
   If (c2 - c1) > 0 Then
     Sl = Sx
   Else
     Su = Sx
   End If
   
  Wend

  If (Round(Sx, 4) = Round(Suu, 4)) Then
   Su = 2 * Suu
   Suu = Su
   GoTo Start_Iteration
  End If

    Bisectional_call = Sx
End Function
Private Function Bisectional_put(S, k, T, R, q, Sigma As Double) As Double


  Dim n As Integer
  Dim dt As Double
  Dim Sx As Double, Su As Double, Sl As Double, Sll As Double
  Dim D1 As Double, d2 As Double, L2 As Double
  Dim err As Double, P1 As Double, P2 As Double
  Dim b As Double, A As Double, h As Double
  Dim NN1 As Double, NN2 As Double, E_st As Double
  Dim L1 As Double, IterationCountE As Double
   
  dt = Sigma * Sqr(T)
  D1 = (Log(S / k) + (R - q + Sigma ^ 2 / 2) * T) / dt
  d2 = D1 - dt
  
  NN1 = Application.NormSDist(-D1)
  NN2 = Application.NormSDist(-d2)

  E_st = S * Exp((R - q) * T) * NN1 / NN2
  
  Sl = 0 ' Guess the low bound
  Su = S ' Guess the high bound
  Sll = Sl
  
  b = 2 * (R - q) / Sigma ^ 2
  A = 2 * R / Sigma ^ 2
  h = 1 - Exp(-R * T)
  L1 = (-(b - 1) - Sqr((b - 1) ^ 2 + 4 * A / h)) / 2
   
Start_Iteration:
  
  IterationCountE = 0.000000001
  While (Su - Sl) > IterationCountE
   Sx = (Su + Sl) / 2
   
   D1 = (Log(Sx / k) + ((R - q) + Sigma ^ 2 / 2) * T) / dt
   P1 = k - Sx
   P2 = BSprice(Sx, k, T, R, q, Sigma, False) - (1 - Exp(-q * T) * Application.NormSDist(-D1)) * Sx / L1
   
   If (P2 - P1) > 0 Then
     Su = Sx
   Else
     Sl = Sx
   End If
   
  Wend
   
    Bisectional_put = Sx
End Function
Public Function BSprice(S, k, T, R, q, Sigma As Double, IsCall As Boolean)
  '===========================================================
  'BS定价计算模块
  '输入参数:
  '——→ S:标的价
  '——→ K:执行价
  '——→ T:到期期限
  '——→ r:无风险利率
  '——→ q:红利率
  '——→ Sigma:波动率
  '——→ IsCall:是否看涨期权,输入True为看涨,输入False为看跌
  '
  '输出参数
  '——→ BSprice:欧式期权价格
  '===========================================================

  Dim D1, d2, Price As Double

  D1 = (Log(S / k) + (R - q + Sigma ^ 2 / 2) * T) / (Sigma * Sqr(T))
  d2 = D1 - Sigma * Sqr(T)

  If IsCall Then
    Price = S * Exp(-q * (T)) * Application.WorksheetFunction.Norm_S_Dist(D1, True) - k * Exp(-R * (T)) * Application.WorksheetFunction.Norm_S_Dist(d2, True)
  Else
    Price = k * Exp(-R * (T)) * Application.WorksheetFunction.Norm_S_Dist(-d2, True) - S * Exp(-q * (T)) * Application.WorksheetFunction.Norm_S_Dist(-D1, True)
  End If

  BSprice = Price

End Function

分享到 :
0 人收藏

2 个回复

倒序浏览
2#
夏秋  1级新秀 | 2021-1-3 14:29:19 发帖IP地址来自 福建厦门
楼主,VBA代码对应的列表是啥样哒 ?
3#
波西米亚  5级知名 | 2021-1-3 15:18:38 发帖IP地址来自 中国
先收藏,没太看懂
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:778
帖子:168
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP