一、蒙特卡洛方法概述
1.基本思想
蒙特卡洛模拟法通过选择或建立适当的随机模型模拟风险因子的未来变化路径,并利用估值公示计算出对应路径的资产组合价值。然后反复重复上述模拟过程,可以最大限度获得风险因子的未来变化路径及其对应的资产组合价值在未来的可能取值,以更加准确的描述出资产组合的未来损益分布。
蒙特卡罗方法的基本思想即在大数定理的保证下,利用事件发生的“频率”作为事件发生的“概率”的近似值。只要设计一个随机试验,使一个事件的概率与某未知数有关,然后通过重复试验,以频率近似值表示概率,即可求得该未知数的近似值。在此方法中利用随机试验求近似解,需要相当多的试验次数,且次数越多近似效果也越好。
2.主要步骤
蒙特卡罗方法主要有三个步骤:
- 1.描述或构造概率过程:对于不具有随机性质的确定性问题,需要人为地构造一个概率过程。
- 2.利用概率分布抽样:通过计算机产生已知概率分布的随机变量,如均匀分布,正态分布、指数分布、泊松分布等。
- 3.建立各种估计量:构造了随机概率模型并从中抽样后,就要确定一个随机变量,作为所要求问题的解。一般是把次随机抽样结果的算术平均值作为解的近似值。
3.数据选取
本项目选取上证500指数和个股的数据进行Monte Carlo模拟研究拟合效果。考虑到银行业股价具有较强的可预测性,因此选取平安银行(股票代码:SZ000001)进行个股股价预测。
数据来源:从wind和tushare数据库拉取了2018年1月2日至2024年4月12日间每个交易日的上证指数和平安银行股价数据。
二、模型搭建
1.基本假设
- 1.股价服从几何布朗运动。
几何布朗运动:布朗运动的一种变体,它描述了一个资产价格的随机运动,其中价格的对数服从布朗运动。这个模型假设资产价格的波动率是恒定的,并且价格的变动是连续的。
假设股价$S(t)$的变化服从以下形式的随机微分方程:
其中:
是股价的预期收益率(即股价的无风险增长率),
是股价的波动率,
是布朗运动的微分项,表示时间
到
之间的随机变化。
- 2.资产收益率服从正态分布。
- 3.不同资产价格变化之间是独立的,或者具有某种已知的相关性。
2.参数估计
利用历史数据估计几何布朗运动模型中的参数,代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data = pro.daily(ts_code='000001.SZ', start_date='20180101', end_date='20240411')
#这里计算的是一年的数据
historical_prices = data.loc['2023-01-01':'2023-12-29','close']
test = data.loc['2024-01-01':'2024-04-30','close']
train = data.loc[:,'close']
# 计算对数收益率
log_returns = np.log(np.array(historical_prices[1:]) / np.array(historical_prices[:-1]))
# 估计漂移率和波动率
drift = np.mean(log_returns)
volatility = np.std(log_returns)
print("漂移率 (drift):", drift)
print("波动率 (volatility):", volatility)
得到计算结果如下所示:
5年预期收益率 (
): -0.0002368310
5年波动率 ():0.0206163004
1年预期收益率 ():-0.0015885768
1年波动率 (): 0.0133056153
3.开始模拟
首先考虑到,模型训练数据较为久远的话,对于整个市场变动情况可以有较为充分的反映,因此选用2018年1月1日至2023年12月29日的股票价格数据来预测2024年1月1日至2024年4月11日的股票价格,绘制股价预测值和股价预测区间。
具体做法如下:进行N次模拟,预测区间即这N条股价路径所覆盖的区域,而股价预测值则为这N条股价路径的均值。
预测区间先采用5条股价路径进行预测。对于股价预测值,分别进行一次模拟和五次模拟的方法,分别绘制预测股价曲线与实际股价曲线。其中,灰色区域为五次模拟产生的五条股价路径所覆盖的区域,橙色趋势线为预测值,蓝色趋势线为股价实际走势。
代码实现如下:
def brownian_motion(start_price, drift, volatility, dt, steps):
prices = [start_price]
for i in range(steps):
shock = np.random.normal(drift * dt, volatility * np.sqrt(dt))
price = prices[-1] * np.exp(shock)
prices+=[price]
return prices
# 设置模拟参数
test = data.loc['2024-01-01':'2024-04-15','close']
start_price