《金融建模基础》综合实验

实验报告
实 验 基 本 信 息 | |||||||
项目名称 | 《金融建模基础》综合实验 | ||||||
课程名称 | 金融建模基础 | 教学班级 | |||||
上课学期 | 2021-2022(1) | 指导教师 | 闵晓平 | ||||
实 验 完 成 人 情 况 | |||||||
序号 | 学 号 | 专业班级 | 姓 名 | ||||
0194726 | 金融191 | 刘健 | |||||
实 验 报 告 评 分 表 | |||||||
评 分 项 目 | 评 分 标 准 | 分值 | 得分 | ||||
报告格式 | 版面美观,格式规范 | 20分 | |||||
三基技能 | 概念准确,代码正确 | 40分 | |||||
问题分析 | 分析合理,有创新性 | 20分 | |||||
学习感悟 | 语句流畅,条理清晰 | 20分 | |||||
本 实 验 报 告 的 成 绩 | 100分 | ||||||
实 验 指 导 教 师 签 名 | |||||||
一、实验目的与要求
(一)实验目的通过本课程的学习,系统掌握现代金融学的基本模型,构建借助python软件应用金融学基本模型解决现实金融问题的思路,增强应用金融模型进行资产定价,组合管理和风险管理的实际动手能力,具体目的如下:
掌握金融数据的预处理、统计计量分析和图形展示的基本技能
掌握应用金融模型进行资产定价的能力
掌握应用金融模型进行风险衡量、对冲的能力
(二)实验要求
1.使用2021年1-3季度上证综指,深成指,沪深300指数的日度行情,(1)画出3个指数的时间序列图;(2)分析3个指数之间的相关关系;(3)分析三个指数的日度收益的概率分布是否服从正态分布。
2.使用2010年1月1日以来A股10支个股的日度行情,(1)计算各股贝塔,绘制贝塔时间序列图;(2)验证资本资产定价模型;(3)构建系统风险大于0.5且小于1的最优组合。
3.使用2021年1-3季度沪深300指数日度数据;(1)估计沪深300指数的历史波动率;(2)使用期权估计前瞻性波动率;(3)模拟未来1个月指数分布;(4)计算某个基于沪深300ETF的看涨期权价格的价格,与市场价格进行对比分析。
二、实验设备与软件
本实验需要使用安装了Anaconda软件的计算机。
三、实验内容报告
# 第一部分
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import statsmodels.api as sm
import scipy.optimize as sco
import scipy.stats as st
from scipy.stats import norm
# 显示中文
from pylab import mpl
mpl.rcParams[font.sans-serif] = [SimHei]
mpl.rcParams[axes.unicode_minus] = False
# 导入数据
SH = pd.read_excel(C:Users86138Desktop金融建模指数.xlsx,sheet_name=上证指数,header=0,index_col=0)
SZ = pd.read_excel(C:Users86138Desktop金融建模指数.xlsx,sheet_name=深证成指,header=0,index_col=0)
HS300 = pd.read_excel(C:Users86138Desktop金融建模指数.xlsx,sheet_name=沪深300,header=0,index_col=0)
# 时间序列图
# 上证指数时间序列图
plt.figure(figsize=(15, 8))# 画布尺寸
# 开盘点位
plt.subplot(2,2,1)# 放在第一张图
plt.plot(SH[开盘指数],r-,label=u上证指数开盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 收盘点位
plt.subplot(2,2,2)# 放在第二张图
plt.plot(SH[收盘指数],r-,label=u上证指数收盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最高点位
plt.subplot(2,2,3)# 放在第一张图
plt.plot(SH[最高指数],r-,label=u上证指数最高指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最低点位
plt.subplot(2,2,4)# 放在第二张图
plt.plot(SH[最低指数],r-, label=u上证指数最低指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格

# 深证成指时间序列图
plt.figure(figsize=(15, 8))# 画布尺寸
# 开盘点位
plt.subplot(2,2,1)# 放在第一张图
plt.plot(SZ[开盘指数],r-,label=u深证成指开盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 收盘点位
plt.subplot(2,2,2)# 放在第二张图
plt.plot(SZ[收盘指数],r-, label=u深证成指收盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最高点位
plt.subplot(2,2,3)# 放在第一张图
plt.plot(SZ[最高指数],r-, label=u深证成指最高指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最低点位
plt.subplot(2,2,4)# 放在第二张图
plt.plot(SZ[最低指数],r-, label=u深证成指最低指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格

# 沪深300时间序列图
plt.figure(figsize=(15, 8))# 画布尺寸
# 开盘点位
plt.subplot(2,2,1)# 放在第一张图
plt.plot(HS300[开盘指数],r-, label=u沪深300开盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 收盘点位
plt.subplot(2,2,2)# 放在第二张图
plt.plot(HS300[收盘指数],r-, label=u沪深300收盘指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最高点位
plt.subplot(2,2,3)# 放在第一张图
plt.plot(HS300[最高指数],r-,label=u沪深300最高指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格
# 最低点位
plt.subplot(2,2,4)# 放在第二张图
plt.plot(HS300[最低指数],r-,label=u沪深300最低指数,lw=2.0)# 折线图
plt.xticks(fontsize=13,rotation=30)
plt.xlabel(u日期,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u点位,fontsize=13)# 字号和标签
plt.legend(loc=2,fontsize=13)# 图例放在左上
plt.grid()# 网格

# 三个指数之间的相关系数
SH_profit = SH.iloc[:,4]
SZ_profit = SZ.iloc[:,4]
HS300_profit = HS300.iloc[:,4]
profit = pd.concat([SH_profit, SZ_profit,HS300_profit],axis=1)# 将三个指数回报率拼接成一个新数据框
profit.columns = [上证指数回报率,深证成指回报率,沪深300回报率] # 改数据框列名
print(profit.corr())# 输出相关系数

# 三个指数的日回报率的概率分布与正态分布的对比
plt.figure(figsize=(15, 8))# 画布尺寸
# 上证指数与正态分布对比
SH_mean = np.mean(SH_profit)# 上证指数回报率均值
SH_std = np.std(SH_profit)# 上证指数回报率标准差
SH_norm = np.random.normal(loc=SH_mean,scale=SH_std,size=(len(SH_profit),1))# 正态分布抽样
SH_pro = np.array(SH_profit)# 将上证指数回报率转换为数组
SH_pro = SH_pro.reshape(len(SH_profit),1)# 转换为一列
SH_compare = np.hstack([SH_norm,SH_pro])# 将正态分布样产生的数组与上证指数回报率拼接为两列的数组
plt.subplot(2, 2, 1)# 第一张图
plt.hist(SH_compare,label=[u正态分布抽样,u上证指数回报率],bins=10,edgecolor=k)# 画直方图
plt.xticks(fontsize=13)
plt.xlabel(u样本值,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u频数,fontsize=13)
plt.legend(loc=2,fontsize=13)
plt.grid()
# 深证成指与正态分布对比
SZ_mean = np.mean(SZ_profit)# 深证成指回报率均值
SZ_std = np.std(SZ_profit)# 深证成指回报率标准差
SZ_norm = np.random.normal(loc=SZ_mean,scale=SZ_std,size=(len(SZ_profit),1))# 正态分布抽样
SZ_pro = np.array(SZ_profit)# 将深证成指回报率转换为数组
SZ_pro = SZ_pro.reshape(len(SZ_profit),1)# 转换为一列
SZ_compare = np.hstack([SZ_norm,SZ_pro])# 将正态分布样产生的数组与深证成指回报率拼接为两列的数组
plt.subplot(2, 2, 2)# 第二张图
plt.hist(SZ_compare,label=[u正态分布抽样,u深证成指回报率],bins=10,edgecolor=k)# 画直方图
plt.xticks(fontsize=13)
plt.xlabel(u样本值,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u频数,fontsize=13)
plt.legend(loc=2,fontsize=13)
plt.grid()
# 沪深300与正态分布对比
HS300_mean = np.mean(HS300_profit)# 沪深300回报率均值
HS300_std = np.std(HS300_profit)# 沪深300回报率标准差
HS300_norm = np.random.normal(loc=HS300_mean,scale=HS300_std,size=(len(HS300_profit),1))# 正态分布抽样
HS300_pro = np.array(HS300_profit)# 将沪深300回报率转换为数组
HS300_pro = HS300_pro.reshape(len(HS300_profit),1)# 转换为一列
HS300_compare = np.hstack([HS300_norm,HS300_pro])# 将正态分布样产生的数组与沪深300回报率拼接为两列的数组
plt.subplot(2, 2, 3)# 第三张图
plt.hist(HS300_compare,label=[u正态分布抽样,u沪深300回报率],bins=10,edgecolor=k)# 画直方图
plt.xticks(fontsize=13)
plt.xlabel(u样本值,fontsize=13)
plt.yticks(fontsize=13)
plt.ylabel(u频数,fontsize=13)
plt.legend(loc=2,fontsize=13)
plt.grid()
plt.show()

# 正态分布检验
# kstest检验
print(st.kstest(rvs=SH_profit,cdf=norm,args=(SH_mean,SH_std)))
print(st.kstest(rvs=SZ_profit,cdf=norm,args=(SZ_mean,SZ_std)))
print(st.kstest(rvs=HS300_profit,cdf=norm,args=(HS300_mean,HS300_std)))
# anderson检验
print(st.anderson(SH_profit,dist=norm))
print(st.anderson(SZ_profit,dist=norm))
print(st.anderson(HS300_profit,dist=norm))
# shapiro检验
print(st.shapiro(SH_profit))
print(st.shapiro(SZ_profit))
print(st.shapiro(HS300_profit))
# normaltest检验
print(st.normaltest(SH_profit))
print(st.normaltest(SZ_profit))
print(st.normaltest(HS300_profit))

# 第二部分
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import statsmodels.api as sm
import scipy.optimize as sco
from scipy.stats import norm
# 显示中文
from pylab import mpl
mpl.rcParams[font.sans-serif] = [SimHei]
mpl.rcParams[axes.unicode_minus] = False
# 计算十只股票的beta值
data = pd.read_excel(C:/Users/86138/Desktop/金融建模/十只个股+沪深300.xlsx,sheet_name=收盘,header=0,index_col=0)
R = np.log(data/data.shift(1))# 按照对数收益率公式计算收益率
R = R.dropna()# 删除缺失的数据
R_index = R.iloc[:,0] # 提取出沪深300收益率
R_stocks = R.iloc[:,1:11] # 提取出个股收益率
R_index_addons = sm.add_constant(R_index)# 对自变量的样本值增加一列常数项
beta = R_index
alpha = R_index # 利用沪深300指数构建辅助数据框
for i in range(0,10):
A = [] # 建立空列表存放alpha值
B = [] # 建立空列表存放beta值
for j in range(len(R_stocks)):
model = sm.OLS(endog=R_stocks.iloc[0:j+1,i:i+1],exog=R_index_addons.iloc[0:j+1,])# 建立OLS拟合模型
result = model.fit()# 进行拟合b = result.params.iloc[1,] # 提取出beta值
B.append(b)# 将股票的beta值添加到列表中
A.append(result.params.const)# 将alpha值添加到列表中
B1 = pd.DataFrame(data=B,index=R_index.index)# 将股票的beta值转化为数据框,beta = pd.concat([beta,B1],axis=1)# 进行拼接
A1 = pd.DataFrame(data=A, index=R_index.index)# 将股票的alpha值转化为数据框,alpha = pd.concat([alpha, A1], axis=1)# 进行拼接
beta = beta.iloc[:,1:11] # 删除沪深300指数所在列
alpha = alpha.iloc[:,1:11] # 删除沪深300指数所在列
# beta时间序列图
plt.figure(figsize=(15,8))
plt.plot(beta.iloc[365:,:])# 前几行拟合数据过少,得到的beta不准确,因此去除
plt.xlabel(u日期,fontsize=13)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.title(u十只股票的beta时间序列,fontsize=13)
plt.grid()
plt.show()

# 验证CAPM模型
capm = beta.mul(R_index,axis=0)+alpha # capm模型所计算出的股票收益率 R_stock=alpha+beta*R_index
print(R_stocks)# 输出股票的真实收益
print(capm)# 输出CAPM模型计算出的收益

# 生成系统风险大于0.5小于1的最优组合beta_new = np.array(beta.iloc[len(R_index)-1:len(R_index),:])# 提取出2021.11.30日的beta数据(最新数据)
R_stocks_block = np.array(R_stocks.iloc[len(R_index)-1:len(R_index),:])# 提取出2021.11.30日股票收盘价
R_stocks_mean = np.array(R_stocks.mean()*252)# 股票的年化收益率
def f(w):
w=np.array(w)
return-np.sum(R_stocks_mean*w)
cons =({type:ineq,fun:lambda w: np.sum(w*beta_new)-0.5},{type:ineq,fun:lambda w: 1.0-np.sum(w*beta_new)},{type:eq,fun:lambda w: np.sum(w)-1})#约束条件:股票组合的beta值在0.5到1.0之间
bnds =((0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1),(0,1))# 边界条件
result = sco.minimize(f,np.array([0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1]),method=SLSQP,bounds=bnds,constraints=cons)#最优化求解
result = result[x].round(4)# 提取每只股票的比重并保留四位小数
stocks_group_profit = sum(np.array(result)*R_stocks_mean)# 计算股票组合的收益率
for i in range(0,10):
print(R_stocks.columns[i],的比重,result[i])#输出每只股票的权重
print(beta值在0.5到1.0之间的最优组合的收益率,stocks_group_profit.round(4))

第三部分
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
import scipy.optimize as sco
import numpy as np
from scipy.stats import norm
# 显示中文
from pylab import mpl
from scipy.optimize import fsolve
mpl.rcParams[font.sans-serif] = [SimHei]
mpl.rcParams[axes.unicode_minus] = False
# 使用2021年1——3季度的数据估计沪深300的历史波动率
HS300 = pd.read_excel(C:Users86138Desktop金融建模指数.xlsx,sheet_name=沪深300,header=0,index_col=0)
HS300 = HS300.iloc[:,3] # 沪深300收盘价
HS300_profit = np.log(HS300/HS300.shift(1))# 沪深300回报率
HS300_profit = HS300_profit.dropna()# 删除缺失值
mu = HS300_profit.mean()*252 # 年化回报率
sigma = HS300_profit.std()*np.sqrt(252)# 标准差
print("沪深300的预期年化收益率",round(mu,4))
print("沪深300收益的年化波动率",round(sigma,4))

# 模拟未来一个月的指数分布
date = pd.bdate_range(2021-10-01,2021-11-01)# 生成从2021.10.1日到2021.12.1日之间的工作日
N = len(date)# 日期数
I = 20 # 模拟的路径数
dt = 1.0/252 # 单位时间的区间长度
mu = np.array(mu)
sigma = np.array(sigma)
S_GBM = np.zeros((N,I))# 生成存放服从几何布朗运动的未来股价的初始数组
S_GBM[0] = 4866.383 # 将模拟的起点设为2021.9.30日沪深300的收盘指数
for t in range(1,N):
epsilon = np.random.standard_normal(I)
S_GBM[t] = S_GBM[t-1]*np.exp((mu-0.5*sigma**2)*dt+sigma*epsilon*np.sqrt(dt))
S_GBM = pd.DataFrame(S_GBM,index=date)# 将模拟的数值转化为带有时间索引的数据框
# 将模拟结果可视化
plt.figure(figsize=(15,8))
plt.plot(S_GBM)
plt.xlabel(u日期,fontsize=13)
plt.ylabel(u点位,fontsize=13)
plt.xticks(fontsize=13)
plt.yticks(fontsize=13)
plt.grid()
plt.show()

# 期权的隐含波动率
HS300ETF = pd.read_excel(C:Users86138Desktop金融建模期权.xlsx,sheet_name=Sheet1,header=0,index_col=0)
# 定义求隐含波动率的函数
def impvol_Binary(C,S,K,r,T,cp_flag):
:param C: 期权的市场价格
:param S: 期权基础资产的价格
:param K: 期权的执行价格
:param r: 无风险利率
:param T: 期权合约的剩余年限
:param cp_flag: 看涨还是看跌,“C”代表看涨,“P”代表看跌
:return: 期权的隐含波动率
def cp_BS(S,K,sigma,r,T,cp_flag): # 计算期权价格
d1 =(np.log(S/K)+(r+pow(sigma,2)/2)*T)/(sigma*np.sqrt(T))
d2 = d1-sigma*np.sqrt(T)
if cp_flag == C: # 如果是看涨
return S*norm.cdf(d1)-K*np.exp(-r*T)*norm.cdf(d2)
else: # 如果是看跌
return K*np.exp(-r*T)*norm.cdf(-d2)-S*norm.cdf(-d1)
sigma_min = 0.001 # 最小sigma
sigma_max = 1.000 # 最大sigma
sigma_mid =(sigma_max+sigma_min)/2 # 中间值
cp_min = cp_BS(S,K,sigma_min,r,T,cp_flag)
cp_max = cp_BS(S,K,sigma_max,r,T,cp_flag)
cp_mid = cp_BS(S,K,sigma_mid,r,T,cp_flag)
diff = C-cp_mid
if C
return Error
while abs(diff)>1e-6:
diff = C-cp_BS(S,K,sigma_mid,r,T,cp_flag)
sigma_mid =(sigma_min+sigma_max)/2
call_mid = cp_BS(S,K,sigma_mid,r,T,cp_flag)
if C >call_mid:
sigma_min = sigma_mid
else:
sigma_max = sigma_mid
return sigma_mid
C = HS300ETF.iloc[:,4] # 期权的市场价格
S = HS300ETF.iloc[:,5] # 标的资产的价格
K = HS300ETF.iloc[:,1] # 执行价格
r = HS300ETF.iloc[:,7]/100 # 无风险利率
T = HS300ETF.iloc[:,6] # 剩余期限
cp_flag = HS300ETF.iloc[:,0] # 看涨还是看跌,“C”代表看涨,“P”代表看跌
imp = [] # 建立空列表存储隐含波动率
for i in range(0,len(C)): # 计算期权的隐含波动率
imp_vol1 = impvol_Binary(C[i],S[i],K[i],r[i],T[i],cp_flag[i])
imp.append(imp_vol1)
imp = np.array(imp)# 将隐含波动率转化为数组
print(imp)

# 计算某个基于沪深300ETF期权的价格,并与市场价格做对比
def call_BS(S, K, sigma, r, T): # 计算期权价格
d1 =(np.log(S / K)+(r + pow(sigma, 2)/ 2)* T)/(sigma * np.sqrt(T))
d2 = d1-sigma * np.sqrt(T)
return S * norm.cdf(d1)-K * np.exp(-r * T)* norm.cdf(d2)
print(标的资产价格,S.iloc[0])
print(执行价格,K.iloc[0])
print(沪深300年化波动率,HS300_profit.std()*np.sqrt(252))
print(无风险利率,r.iloc[0])
print(剩余期限,T.iloc[0])
print(期权的理论加价格,call_BS(S.iloc[0],K.iloc[0],HS300_profit.std()*np.sqrt(252),r.iloc[0],T.iloc[0]))
print(期权的市场价格,C.iloc[0])

版权声明:
1.大文斗范文网的资料来自互联网以及用户的投稿,用于非商业性学习目的免费阅览。
2.《《金融建模基础》综合实验》一文的著作权归原作者所有,仅供学习参考,转载或引用时请保留版权信息。
3.如果本网所转载内容不慎侵犯了您的权益,请联系我们,我们将会及时删除。
