数理金融实验1&2(作业记录)

 


前言

记录数理金融实验小学期作业。

 

一、作业一

(1) 收集上海证券交易所上市的 10 种股票从 2020 年 6 月 1 日-2021 年 5 月 30 日的历史数据, 形成 excel 文件.(要求每位同学需要查询代码为 “60**+ 座位号” 对应的股票信息, 其中 *=0∼9)

·关于数据收集,建议使用三个网站:

1.国内股票:Tushare数据

2.国外股票:https://cn.investing.com/,国外股票有限选择美股

3.全域数据:https://ca.yahoo.com/(需要科学上网)

数据收集建议使用爬虫获取数据,这样可以快速获取大量数据,python实现也方便对数据进行处理,在Tushare数据网站获取国内股票数据实现如下

import tushare as ts
import pandas as pd

# 设置你的Tushare API token
ts.set_token('这里替换为你的tushare的token')//token获取方式见下图
pro = ts.pro_api()

# 生成所有符合条件的股票代码
tickers = []
for i in range(10):
    for j in range(10):
        ticker = f'30{i}{j}42.SZ'//按照要求生成符合条件股票代码
        tickers.append(ticker)

# 定义时间范围
start_date = '20230601'
end_date = '20240530'

# 创建一个 ExcelWriter 对象,指定引擎为 'xlsxwriter',指定文件名
excel_writer = pd.ExcelWriter('shanghai_stocks_data3.xlsx', engine='xlsxwriter')

try:
    # 获取每只股票的数据并写入不同的 sheet
    for ticker in tickers:
        stock_data = pro.daily(ts_code=ticker, start_date=start_date, end_date=end_date)
        if not stock_data.empty:
            stock_data['Ticker'] = ticker  # 添加一列来标识股票代码
            sheet_name = ticker.replace('.', '_')  # Excel sheet 名称不能包含特殊字符如 '.'
            
            # 按日期排序,由远到近,可按照需求添加数据处理字段
            stock_data_sorted = stock_data.sort_values(by='trade_date', ascending=True)
            
            stock_data_sorted.to_excel(excel_writer, sheet_name=sheet_name, index=False)

    # 关闭 ExcelWriter 对象(保存文件)
    excel_writer.close()
    print("Excel文件已成功保存为 'shanghai_stocks_data.xlsx3'")
except Exception as e:
    print(f"保存Excel文件时出错:{str(e)}")

 

import yfinance as yf
import pandas as pd

# 按照要求定义所需的股票代码,这里特定题目要求 "O"开头
tickers = ["PEP", "PFE", "PG", "PNC", "PNW", "PPL", "PRU", "PSX", "PVH", "PXD"]

# 时间范围
start_date = '2023-06-01'
end_date = '2024-05-30'

#抓取数据
stock_data = {}
for ticker in tickers:
    try:
        data = yf.download(ticker, start=start_date, end=end_date)
        stock_data[ticker] = data
    except Exception as e:
        print(f"Error fetching data for {ticker}: {str(e)}")

# 保存数据
file_name = 'foreign_stocks_data2.xlsx'
with pd.ExcelWriter(file_name, engine='xlsxwriter') as writer:
    for ticker, data in stock_data.items():
        data.to_excel(writer, sheet_name=ticker)

print(f"Data for {len(stock_data)} stocks saved to '{file_name}'")

(2) 收集国外上市的 10 种股票从 2019 年 9 月 1 日-2020 年 8 月 30 日的 历史数据, 形成 excel 文件.(要求:按照座位号确定代码首字母 A∼Z) 将所有股票价格按照日期排序, 对齐.

在Yahoo网站获取国外股票数据

import yfinance as yf
import pandas as pd

# 按照要求定义所需的股票代码,这里特定题目要求 "O"开头
tickers = ["PEP", "PFE", "PG", "PNC", "PNW", "PPL", "PRU", "PSX", "PVH", "PXD"]

# 时间范围
start_date = '2023-06-01'
end_date = '2024-05-30'

#抓取数据
stock_data = {}
for ticker in tickers:
    try:
        data = yf.download(ticker, start=start_date, end=end_date)
        stock_data[ticker] = data
    except Exception as e:
        print(f"Error fetching data for {ticker}: {str(e)}")

# 保存数据
file_name = 'foreign_stocks_data2.xlsx'
with pd.ExcelWriter(file_name, engine='xlsxwriter') as writer:
    for ticker, data in stock_data.items():
        data.to_excel(writer, sheet_name=ticker)

print(f"Data for {len(stock_data)} stocks saved to '{file_name}'")

 (3) 对上述每种股票进行收益率的正态检验

 需要注意,正态检验结果大部分数据应该都不符合正态分布

Matlab 检验分布命令:

jbtest 格式: H=jbtest(X,ALPHA) 检验 X 在置信度为 1 − α 水平下是否服从正态分布.

建议使用MATLAB实现,示例代码如下(我的日期格式有问题,所以补充了很多调整代码):

% 读取 Excel 文件中的数据
filename = 'shanghai_data.xlsx';  % 修改为你的 Excel 文件路径
sheetnames = {'600141_SH','600241_SH','600641_SH','600741_SH','600841_SH',
    '600941_SH','603041_SH','603341_SH','688141_SH','688041_SH'};  % 假设这是每只股票的 sheet 名称

% 创建一个空的收益率数据结构
returns_data = struct();

try
    % 循环读取每个 sheet 中的数据并计算收益率
    for i = 1:length(sheetnames)
        % 从 Excel 中读取数据
        [~, ~, raw] = xlsread(filename, sheetnames{i});
        
        % 提取日期和收盘价数据
        date_data = raw(2:end, 1);  % 日期在第一列,跳过表头
        close_prices = cell2mat(raw(2:end, 5));  % 假设收盘价在第五列,跳过表头
        
        % 尝试使用多种格式解析日期字符串
        try
            if iscellstr(date_data)  % 如果日期数据是字符串格式
                % 尝试多种日期格式
                formats = {'yyyyMMdd', 'dd/MM/yyyy', 'MM/dd/yyyy', 'yyyy-MM-dd'};
                for fmt = formats
                    try
                        dates = datetime(date_data, 'InputFormat', fmt{1});
                        break;  % 成功解析则跳出循环
                    catch
                        % 继续尝试下一个格式
                    end
                end
                % 如果没有任何格式成功解析,抛出错误
                if ~exist('dates', 'var')
                    error('所有日期格式尝试均失败');
                end
            else  % 如果日期数据是数值格式
                dates = datetime(date_data, 'ConvertFrom', 'excel');
            end
        catch dateError
            fprintf('日期解析失败: %s\n', dateError.message);
            continue;
        end
        
        % 合并日期和收盘价数据
        data_table = table(dates, close_prices);
        
        % 按日期排序
        data_table = sortrows(data_table, 'dates', 'ascend');  % 由远及近排序
        
        % 提取排序后的数据
        sorted_dates = data_table.dates;
        sorted_close_prices = data_table.close_prices;
        
        % 计算收益率
        returns = price2ret(sorted_close_prices);
        
        % 正态性检验
        [h, p, jbstat, critval] = jbtest(returns);
        
        % 打印检验结果
        fprintf('股票代码: %s\n', sheetnames{i});
        fprintf('Jarque-Bera检验结果:\n');
        fprintf('JB统计量: %f\n', jbstat);
        fprintf('临界值: %f\n', critval);
        fprintf('p值: %f\n', p);
        
        % 判断并打印是否符合正态分布
        if h == 0
            fprintf('数据符合正态分布\n');
        else
            fprintf('数据不符合正态分布\n');
        end
        
        % 绘制正态概率图
        figure;
        normplot(returns);
        title(['股票代码: ' sheetnames{i} ' 的正态概率图']);
        
        % 存储收益率数据
        returns_data(i).ticker = sheetnames{i};
        returns_data(i).dates = sorted_dates;
        returns_data(i).returns = returns;
    end
catch ME
    fprintf('读取或处理数据时出错: %s\n', ME.message);
end

二、作业二

(1) 某股票价格为 42, 期权敲定价格为 40, 六月后到期, 无风险利率为 10%, 波动率为 20%, 分别计算该期权是看涨和看跌时的价格 (使用 B-S 公式与 Monte Carlo 模拟分别计算, 并比较两种结果的差异, 如何弥补这 种差异.)

B-S计算期权价格原理

[call,put]=blsprice(price,strike,rate,time,volatility,yield)

说明:

输入变量 (影响期权价格的六大因素)

price: 标的资产价格

strike: 敲定价格

rate: 无风险利率

time: 期权有效期 (现在到期满的时间)

volatility: 波动率 yield: 红利率 输出变量

call: 欧式看涨期权价格 put: 欧式看跌期权价格

>> [call, put] = blsprice(42, 40, 0.10, 0.5, 0.20, 0)%b-s公式计算期权价格

call =

    4.7594


put =

    0.8086

 Monte Carlo 模拟期权价格

原理: 假设在风险中性市场中, 标的资产服从分布 dSt = rStdt + σStdBt 其中 r 为无风险利率. 期权的损益为 f(ST), T 为到期日. 则期权的价格为 f = e −rTEˆ[f(ST)]. 对于欧式看涨期权, f(ST) = max(ST − X, 0), 在 dSt = rStdt + σStdBt 假设 下, ST = S0 exp[(r − σ 2 2 )T + σ √ Tε] 其中 ε ∼ N(0, 1). 欧式看涨期权的价格为 c = e −rTEˆ[max(0, S0 exp[(r − σ 2 2 )T + σ √ Tε] − X)]

S0 = 42; % 当前股票价格
K = 40; % 行权价
r = 0.10; % 无风险利率
T = 0.5; % 到期时间 (6个月)
sigma = 0.20; % 波动率
N = 10000; % 模拟路径数量

% 生成标准正态分布随机变量
epsilon = randn(N, 1);

% 计算股票价格在到期时的分布
ST = S0 * exp((r - 0.5 * sigma^2) * T + sigma * sqrt(T) * epsilon);

% 计算看涨期权的终值
callPayoff = max(ST - K, 0);

% 折现期权终值到当前时刻
callPrice = exp(-r * T) * mean(callPayoff);

% 输出结果
fprintf('看涨期权价格: %f\n', callPrice);

分析差异

差异产生原因:

a. Monte Carlo模拟使用随机数,每次运行的结果都会有些不同

b. 数值计算中浮点数可能会带来微小的误差

c. Monte Carlo模拟的路径数量影响结果的准确性,路径越多越准确

减小差异可以采取的策略:
a. 多次模拟生成数取平均值

b. 增加路径数量,即代码中N的值

c. 使用更精确的随机数,使用更高质量的随机数生成器或更复杂的随机数生成方法

(2) 计算 (1) 中所述两种期权对应的所有敏感度.

使用Matlab内置的Black-Scholes函数来计算期权的敏感度(Greeks)

Delta: 期权价格对标的资产价格的敏感度 [calldelta,putdelta]=blsdelta(price,strike,rate,time,volatility,yield)

Gamma: Delta 对标的资产价格的敏感度 (看涨与看跌有相同的敏 感度) Gamma=blsgamma(price,strike,rate,time,volatility,yield)

Theta: 期权价格对时间的敏感度 [calltheta,puttheta]=blstheta(price,strike,rate,time,volatility,yield) Rho: 期权价格对无风险利率的敏感度 [callrho,putrho]=blsdelta(price,strike,rate,time,volatility,yield) Vega: 期权价格对标的资产波动率的敏感度 (看涨与看跌相同) Vega=blsvega(price,strike,rate,time,volatility,yield)

price = 42; % 当前股票价格
strike = 40; % 行权价
rate = 0.10; % 无风险利率
time = 0.5; % 到期时间 (6个月)
volatility = 0.20; % 波动率
yield = 0; % 股息收益率

% 计算Delta
[calldelta, putdelta] = blsdelta(price, strike, rate, time, volatility, yield);

% 计算Gamma
gamma = blsgamma(price, strike, rate, time, volatility, yield);

% 计算Theta
[calltheta, puttheta] = blstheta(price, strike, rate, time, volatility, yield);

% 计算Rho
[callrho, putrho] = blsrho(price, strike, rate, time, volatility, yield);

% 计算Vega
vega = blsvega(price, strike, rate, time, volatility, yield);

% 输出结果
fprintf('看涨期权Delta: %f\n', calldelta);
fprintf('看跌期权Delta: %f\n', putdelta);
fprintf('Gamma: %f\n', gamma);
fprintf('看涨期权Theta: %f\n', calltheta);
fprintf('看跌期权Theta: %f\n', puttheta);
fprintf('看涨期权Rho: %f\n', callrho);
fprintf('看跌期权Rho: %f\n', putrho);
fprintf('Vega: %f\n', vega);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值