利用Python和蒙特卡洛模拟进行量化投资风险评估及决策,附完整代码实现。
原文标题:Python量化投资实践:基于蒙特卡洛模拟的投资组合风险建模与分析
原文作者:数据派THU
冷月清谈:
文章使用EODHD APIs获取标准普尔500指数的每日交易数据,并用Python代码演示了如何进行模拟和可视化。之后,文章深入探讨了如何利用蒙特卡洛模拟进行投资风险评估和决策,包括明确投资目标、量化风险承受能力、执行模拟、分析模拟结果(如概率分布、VaR、CVaR)以及结合具体投资案例进行分析。
最后,文章提供了完整的Python代码实现,方便读者进行实践。代码涵盖了数据获取、收益率模拟、风险指标计算、目标收益概率分析以及结果可视化等步骤。
怜星夜思:
2、蒙特卡洛模拟依赖于历史数据,但历史并不能完全预测未来,如何改进模型以更好地适应未来的市场变化?
3、文章中提到了VaR和CVaR两种风险指标,它们有什么区别和联系?实际应用中应该如何选择?
原文内容
来源:Deephub Imba本文约3700字,建议阅读8分钟
本文介绍了Python量化投资实践。
-
历史数据分析:对历史价格数据(OHLC:开盘价、最高价、最低价、收盘价)进行分析,确定平均收益率和波动率参数。
-
随机样本生成:基于历史平均收益率和波动率,采用统计模型生成随机日收益率序列。
-
价格路径模拟:将随机生成的收益率序列应用于当前价格,重复计算生成多条可能的未来价格路径。
-
结果分析:对模拟生成的未来价格分布进行统计分析,估计不同结果的发生概率。
第一部分:数据获取与基础模拟
python3 -m pip install eodhd -U import numpy as np import matplotlib.pyplot as plt from eodhd import APIClient
API_KEY = “<YOUR_KEY>”
api = APIClient(API_KEY)
df = api.get_historical_data(“GSPC.INDX”, “d”, results=365)
print(df)
# 计算日收益率序列 daily_returns = df["adjusted_close"].pct_change().dropna() print(daily_returns)
定义模拟参数
num_simulations = 1000 # 模拟路径数量
forecast_days = 365 # 预测天数初始化模拟数组
simulations = np.zeros((num_simulations, forecast_days))
生成价格路径
last_price = df[“adjusted_close”].iloc[-1]
for i in range(num_simulations):
cumulative_returns = np.random.choice(daily_returns, size=forecast_days, replace=True).cumsum()
simulations[i, :] = last_price * (1 + cumulative_returns)
print(simulations)
可视化模拟结果
# 绘制价格路径
plt.figure(figsize=(10, 6))
plt.plot(simulations.T, color="blue", alpha=0.025)
plt.title("Monte Carlo Simulation of Future Prices")
plt.xlabel("Day")
plt.ylabel("Price")
plt.show()
-
波动率特征捕捉:模拟通过历史波动率数据捕捉了价格变动的可能范围,提供了不确定性的定量表示。然而需要注意的是,该方法基于历史波动模式的持续性假设,这在实际市场环境中可能存在偏差。
-
预测能力边界:虽然模拟对于理解潜在结果分布具有重要价值,但其无法准确预测具体的未来价格点位。市场条件、宏观经济因素以及突发事件都可能导致实际结果偏离模拟范围。
-
情景分析框架:模拟结果的分布为投资者提供了系统的情景分析框架,有助于在收益潜力与损失风险之间进行量化权衡。这种方法推动了从确定性预测向概率思维的转变。
-
模型依赖性:模拟精度在很大程度上取决于收益分布和波动率假设的合理性。不同的分布假设(如正态分布与对数正态分布)可能产生显著不同的结果,这凸显了模型选择和参数校准的重要性。
投资决策框架的关键要素
投资目标与风险偏好量化
-
预期收益率的具体目标设定
-
风险承受能力的量化界定
-
投资期限的明确规划
-
流动性需求的评估
模拟执行的技术实现
模拟结果的量化分析
-
概率分布特征:通过分析模拟终值的分布特征,评估结果的离散程度。较大的离散度通常意味着更高的波动风险。
-
风险价值度量(VaR):在给定置信水平下估计特定时间范围内的最大潜在损失。例如,95%置信水平下的VaR值表示在正常市场条件下的最大可能损失限额。
-
条件风险价值(ETL):又称条件VaR,计算超出VaR阈值的平均损失水平,提供了尾部风险的更全面度量。
量化投资决策实例
-
在95%置信水平下,年度最大损失不超过2,000英镑(95% VaR约束)
-
实现至少10%年化收益的概率不低于50%
# 设置模拟参数 daily_returns = df["adjusted_close"].pct_change().dropna()
基础参数配置
initial_investment = 10000 # 初始投资金额
num_simulations = 1000 # 模拟路径数量
forecast_days = 365 # 预测期限(日)
desired_return = 0.10 # 目标收益率计算收益率统计特征
average_daily_return = daily_returns.mean()
volatility = daily_returns.std()
print(f"Average Daily Return: {average_daily_return}“)
print(f"Volatility: {volatility}”)
![图片](https://media1.xinfinite.net/original/3X/8/9/897ff62c26ac8c232d6ed153b9a51fe264e2769d.jpeg)
daily_returns = np.log(df["adjusted_close"] / df["adjusted_close"].shift(1)).dropna() 优化后的模拟实现代码如下: # 执行收益率模拟 simulated_end_returns = np.zeros(num_simulations) for i in range(num_simulations): random_returns = np.random.normal(average_daily_return, volatility, forecast_days) cumulative_return = np.prod(1 + random_returns) simulated_end_returns[i] = initial_investment * cumulative_return
计算最终投资价值
final_investment_values = simulated_end_returns
print(final_investment_values)
第二部分:风险指标的量化分析
风险价值与条件风险价值的计算实现
confidence_level = 0.95
sorted_returns = np.sort(final_investment_values)
index_at_var = int((1-confidence_level) * num_simulations)
var = initial_investment - sorted_returns[index_at_var]
conditional_var = initial_investment - sorted_returns[:index_at_var].mean()
print(f"Value at Risk (95% confidence): £{var:,.2f}“)
print(f"Expected Tail Loss (Conditional VaR): £{conditional_var:,.2f}”)
![图片](https://media1.xinfinite.net/original/3X/b/9/b949dbde1634017446680e09544565eee4bdac3a.jpeg)
风险指标的技术解读
风险价值(VaR)分析
条件风险价值(CVaR)分析
目标收益实现概率分析
num_success = np.sum(final_investment_values >= initial_investment * (1 + desired_return)) probability_of_success = num_success / num_simulations
print(f"Probability of achieving at least a {desired_return100}% return: {probability_of_success100:.2f}%")
![图片](https://media1.xinfinite.net/original/3X/f/0/f0946a59cc43f0f3313b0cbf015950059f69543f.jpeg)
投资结果分布的可视化分析
plt.figure(figsize=(10, 6)) plt.hist(final_investment_values, bins=50, alpha=0.75) plt.axvline( initial_investment * (1 + desired_return), color="r", linestyle="dashed", linewidth=2, ) plt.axvline(initial_investment - var, color="g", linestyle="dashed", linewidth=2) plt.title("Distribution of Final Investment Values") plt.xlabel("Final Investment Value") plt.ylabel("Frequency") plt.show()
收益目标线(红色虚线)
-
技术定义:表示达到目标收益率时的投资价值水平
-
计算方法:initial_investment * (1 + desired_return)
-
分析意义:该线右侧的分布区域代表实现预期收益目标的情景,其面积与目标实现概率直接相关
风险阈值线(绿色虚线)
-
技术定义:表示95%置信水平下的VaR阈值位置
-
计算方法:initial_investment - var
-
分析意义:该线左侧的分布区域代表超出预期风险容忍度的极端损失情景,其面积为5%
-
投资结果的概率分布特征
-
实现目标收益的可能性
-
极端损失情景的发生频率和程度
完整模型实现代码
import numpy as np import matplotlib.pyplot as plt from eodhd import APIClient import config as cfg
api = APIClient(cfg.API_KEY)
def get_ohlc_data():
df = api.get_historical_data(“GSPC.INDX”, “d”, results=365)
return dfif name == “main”:
df = get_ohlc_data()计算日收益率序列
daily_returns = df[“adjusted_close”].pct_change().dropna()
基础参数配置
initial_investment = 10000 # 初始投资金额
num_simulations = 1000 # 模拟路径数量
forecast_days = 365 # 预测期限(日)
desired_return = 0.10 # 目标收益率计算收益率统计特征
average_daily_return = daily_returns.mean()
volatility = daily_returns.std()print(f"Average Daily Return: {average_daily_return}“)
print(f"Volatility: {volatility}”)执行收益率模拟
simulated_end_returns = np.zeros(num_simulations)
for i in range(num_simulations):
random_returns = np.random.normal(
average_daily_return, volatility, forecast_days
)
cumulative_return = np.prod(1 + random_returns)
simulated_end_returns[i] = initial_investment * cumulative_return计算最终投资价值
final_investment_values = simulated_end_returns
风险指标计算
confidence_level = 0.95
sorted_returns = np.sort(final_investment_values)
index_at_var = int((1 - confidence_level) * num_simulations)
var = initial_investment - sorted_returns[index_at_var]
conditional_var = initial_investment - sorted_returns[:index_at_var].mean()print(f"Value at Risk (95% confidence): £{var:,.2f}“)
print(f"Expected Tail Loss (Conditional VaR): £{conditional_var:,.2f}”)目标收益实现概率分析
num_success = np.sum(
final_investment_values >= initial_investment * (1 + desired_return)
)
probability_of_success = num_success / num_simulationsprint(
f"Probability of achieving at least a {desired_return100}% return: {probability_of_success100:.2f}%"
)结果分布可视化
plt.figure(figsize=(10, 6))
plt.hist(final_investment_values, bins=50, alpha=0.75)
plt.axvline(
initial_investment * (1 + desired_return),
color=“r”,
linestyle=“dashed”,
linewidth=2,
)
plt.axvline(initial_investment - var, color=“g”, linestyle=“dashed”, linewidth=2)
plt.title(“Distribution of Final Investment Values”)
plt.xlabel(“Final Investment Value”)
plt.ylabel(“Frequency”)
plt.show()