#蒙特卡洛模拟看涨期权价格
def call_MonteCarlo(S,K,T,r,sigma,n):
z = standard_normal(n)
St = S*np.exp((r-0.5*sigma**2)*T+sigma*z*np.sqrt(T))
c = sum(np.maximum(0,St-K))*(np.exp(-r*T))/n
return c
#蒙特卡洛模拟看跌期权价格
def put_MonteCarlo(S,K,T,r,sigma,n):
z = standard_normal(n)
St = S*np.exp((r-0.5*sigma**2)*T+sigma*z*np.sqrt(T))
p = sum(np.maximum(0,K-St))*(np.exp(-r*T))/n
return p
c = call_MonteCarlo(5.29,6,0.5,0.04,0.24,5000)
p = put_MonteCarlo(5.29,6,0.5,0.04,0.24,5000)
print('蒙特卡洛模拟看涨期权价格为{:.4f},看跌期权价格为{:.4f}'.format(c,p))
#对偶变量法蒙特卡洛模拟看涨期权价格
def call_dual(S,K,T,r,sigma,n):
z = standard_normal(n)
S1 = S*np.exp((r-0.5*sigma**2)*T+sigma*z*np.sqrt(T))
S2 = S*np.exp((r-0.5*sigma**2)*T+sigma*(-z)*np.sqrt(T))
C1 = sum(np.maximum(0,S1-K))*(np.exp(-r*T))/n
C2 = sum(np.maximum(0,S2-K))*(np.exp(-r*T))/n
return (C1+C2)/2
#对偶变量法蒙特卡洛模拟看跌期权价格
def put_dual(S,K,T,r,sigma,n):
z = standard_normal(n)
S1 = S*np.exp((r-0.5*sigma**2)*T+sigma*z*np.sqrt(T))
S2 = S*np.exp((r-0.5*sigma**2)*T+sigma*(-z)*np.sqrt(T))
C1 = sum(np.maximum(0,K-S1))*(np.exp(-r*T))/n
C2 = sum(np.maximum(0,K-S2))*(np.exp(-r*T))/n
return (C1+C2)/2
c = call_dual(5.29,6,0.5,0.04,0.24,10000)
p = put_dual(5.29,6,0.5,0.04,0.24,10000)
print('对偶蒙特卡洛模拟看涨期权价格为{:.4f},看跌期权价格为{:.4f}'.format(c,p))
#最小二乘蒙特卡洛模拟美式期权价格
def sample_paths(r, sigma, S_0, T, M, N):
'''
r: 无风险利率
sigma: 股价波动率
S_0: 初始股价
T: 期权期限
M: 股价变化过程离散化的段数
N: 路径数
'''
data = S_0*np.ones((N,1))
for i in range(M):
normal_variables = np.random.normal(0,1,(N,1))
ratios = np.exp((r-0.5*sigma*sigma)*T/M +normal_variables*sigma*(T/M)**0.5)
# data[:,-1:]截取的数据维度形状可以保持为(N,1),而data[:,-1]截取的数据的维度为(N)。
data = np.concatenate((data,data[:,-1:]*ratios),axis=1)
return data
def linear_fitting(X,Y):
X = np.array(X)
Y = np.array(Y)
S0,S1,S2,S3,S4 = len(X),sum(X),sum(X*X),sum(X**3),sum(X**4)
V0,V1,V2 = sum(Y), sum(Y*X), sum(Y*X*X)
coeff_mat = np.array([[S0,S1,S2],[S1,S2,S3],[S2,S3,S4]])
target_vec = np.array([V0,V1,V2])
inv_coeff_mat = np.linalg.inv(coeff_mat)
fitted_coeff = np.matmul(inv_coeff_mat,target_vec)
resulted_Ys = fitted_coeff[0]+fitted_coeff[1]*X+fitted_coeff[2]*X*X
return resulted_Ys
def MC_American_put_price(r,sigma,S_0,K,T,M,N):
# data 数组的维度形状为(N,M+1), 即(paths_num,steps_num+1)。
data = sample_paths(r,sigma,S_0,T,M,N)
option_prices = np.maximum(K-data[:,-1], 0)
for i in range(M-1,0,-1):
# 期权价格贴现到当前时刻。
option_prices *= np.exp(-r*T/M)
# 线性回归拟合更新期权价格。
option_prices = linear_fitting(data[:,i], option_prices)
# 判断是不是应该执行期权,并更新价格。
option_prices = np.maximum(option_prices,K-data[:,i])
# 递推回的是初始时刻下一时刻,所以还需要再贴现一次。
option_prices *= np.exp(-r*T/M)
return np.average(option_prices)
#考虑无风险利率为0.1,股价波动率为0.4,初始股价为50,执行时间为5个月后,执行价格为60的美式看跌期权。
#我们把股价变化过程离散化为M=200小段,进行蒙卡抽样股价变化路径N=40000条。
p = MC_American_put_price(0.1,0.4,50,60,5/12,200,40000)
print('最小二乘蒙特卡洛模拟美式看跌期权价格为{:.4f}'.format(p))