import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.dates import DateFormatter
import matplotlib.ticker as mtick
# 设置样式
plt.style.use('seaborn-v0_8-whitegrid')
sns.set_palette("deep")
# 创建金融危机前后的标普500指数数据
dates = pd.date_range(start='2007-01-01', end='2010-12-31', freq='B')
np.random.seed(42) # 确保可重现性
# 模拟金融危机期间的股市走势
base_level = 1500
trend = np.linspace(0, 500, len(dates))
crisis_effect = np.zeros(len(dates))
# 添加危机效应 - 2008年9月雷曼破产后市场大幅下跌
lehman_date = pd.Timestamp('2008-09-15')
crisis_start_idx = np.where(dates >= lehman_date)[0][0]
crisis_duration = 250 # 约一年的交易日
crisis_effect[crisis_start_idx:crisis_start_idx+crisis_duration] = \
-900 * (1 - np.exp(-np.linspace(0, 5, crisis_duration)))
# 创建指数数据
level = base_level + trend + crisis_effect
# 添加日波动
daily_returns = np.random.normal(0, 1, len(dates)) * (1 + crisis_effect/500).clip(1, 4)
# 提高危机期间的波动率
for i in range(1, len(level)):
level[i] = level[i-1] * (1 + daily_returns[i]/100)
sp500 = pd.Series(level, index=dates)
# 创建数据框
df = pd.DataFrame({'S&P500': sp500})
# 计算滚动波动率(20天)
df['Volatility'] = df['S&P500'].pct_change().rolling(20).std() * np.sqrt(252) * 100
# 绘制图表
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=True)
# 绘制标普500指数
ax1.plot(df.index, df['S&P500'], linewidth=2)
ax1.set_title('S&P 500 During Financial Crisis (2007-2010)', fontsize=15)
ax1.set_ylabel('Index Level', fontsize=12)
ax1.axvline(x=lehman_date, color='r', linestyle='--', alpha=0.7,
label='Lehman Bankruptcy (Sep 15, 2008)')
ax1.legend(fontsize=10)
# 绘制波动率
ax2.plot(df.index, df['Volatility'], color='darkred', linewidth=2)
ax2.set_title('Market Volatility (Annualized)', fontsize=15)
ax2.set_ylabel('Volatility (%)', fontsize=12)
ax2.set_xlabel('Date', fontsize=12)
ax2.axvline(x=lehman_date, color='r', linestyle='--', alpha=0.7)
ax2.axhline(y=20, color='orange', linestyle='-.', alpha=0.7,
label='High Volatility Threshold')
ax2.yaxis.set_major_formatter(mtick.PercentFormatter())
ax2.legend(fontsize=10)
# 格式化日期
date_form = DateFormatter("%Y-%m")
ax2.xaxis.set_major_formatter(date_form)
fig.autofmt_xdate()
plt.tight_layout()
plt.show()
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.dates import DateFormatter
import matplotlib.patches as mpatches
# 设置样式
plt.style.use('seaborn-v0_8-whitegrid')
# 创建主要金融风险事件数据
events = [
{'date': '2007-02-27', 'event': 'Shanghai Stock Market Crash', 'type': 'Market Risk', 'impact': 6},
{'date': '2007-08-09', 'event': 'BNP Paribas Freezes Funds', 'type': 'Liquidity Risk', 'impact': 7},
{'date': '2008-03-16', 'event': 'Bear Stearns Collapse', 'type': 'Credit Risk', 'impact': 8},
{'date': '2008-09-15', 'event': 'Lehman Brothers Bankruptcy', 'type': 'Credit/Liquidity Risk', 'impact': 10},
{'date': '2008-09-16', 'event': 'AIG Bailout', 'type': 'Credit Risk', 'impact': 9},
{'date': '2008-10-03', 'event': 'TARP Enacted', 'type': 'Systemic Risk', 'impact': 7},
{'date': '2010-05-06', 'event': 'Flash Crash', 'type': 'Market/Operational Risk', 'impact': 5},
{'date': '2010-05-10', 'event': 'European Stability Mechanism', 'type': 'Sovereign Risk', 'impact': 8},
{'date': '2011-08-05', 'event': 'US Credit Downgrade', 'type': 'Sovereign Risk', 'impact': 7},
{'date': '2012-07-26', 'event': 'Draghi "Whatever it takes"', 'type': 'Systemic Risk', 'impact': 6},
{'date': '2015-08-24', 'event': 'China Market Crash', 'type': 'Market Risk', 'impact': 6},
{'date': '2016-06-23', 'event': 'Brexit Vote', 'type': 'Political Risk', 'impact': 7},
{'date': '2020-03-16', 'event': 'COVID-19 Market Crash', 'type': 'Systemic Risk', 'impact': 9}
]
# 转换为DataFrame
df = pd.DataFrame(events)
df['date'] = pd.to_datetime(df['date'])
df = df.sort_values('date')
# 为不同风险类型分配颜色
risk_types = df['type'].unique()
colors = sns.color_palette("bright", len(risk_types))
color_map = dict(zip(risk_types, colors))
# 创建图表
plt.figure(figsize=(14, 8))
# 绘制事件时间线
for i, (_, event) in enumerate(df.iterrows()):
plt.scatter(event['date'], i, s=event['impact']*50, color=color_map[event['type']], alpha=0.7)
plt.plot([event['date'], event['date']], [i-0.1, i+0.1], color='black', linewidth=1)
plt.text(event['date'], i+0.5, event['event'], ha='center', fontsize=11,
bbox=dict(facecolor='white', alpha=0.7, boxstyle='round,pad=0.3'))
# 添加Y轴标签
plt.yticks([])
plt.ylabel('Timeline')
# 格式化X轴日期
plt.gca().xaxis.set_major_formatter(DateFormatter('%Y'))
plt.gcf().autofmt_xdate()
plt.xlabel('Year')
# 添加图例
patches = [mpatches.Patch(color=color_map[risk], label=risk) for risk in color_map]
plt.legend(handles=patches, title='Risk Type', loc='upper left')
plt.title('Major Financial Risk Events (2007-2020)', fontsize=16)
plt.tight_layout()
plt.grid(True, alpha=0.3)
plt.show()
# import numpy as np
# import pandas as pd
# import matplotlib.pyplot as plt
# import yfinance as yf
# from scipy.stats import norm
# ### 下载股票数据
# tickers = ['AAPL', 'MSFT', 'AMZN', 'GOOGL']
# weights = np.array([0.3, 0.3, 0.2, 0.2])
# start_date = '2021-01-01'
# end_date = '2023-01-01'
# ### 获取历史数据
# data = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
# returns = data.pct_change().dropna()
# ### 计算组合收益
# portfolio_returns = returns.dot(weights)
# ### 设置参数
# confidence_level = 0.95
# investment_value = 1000000 ### 100万投资
# %pip install akshare
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import akshare as ak
from scipy.stats import norm
from datetime import datetime
### 下载股票数据
tickers = ['AAPL', 'MSFT', 'AMZN', 'GOOGL']
weights = np.array([0.3, 0.3, 0.2, 0.2])
start_date = '2021-01-01'
end_date = '2023-01-01'
### 获取历史数据
# 创建一个空的DataFrame来存储调整后收盘价
data = pd.DataFrame()
# 使用akshare分别获取每只股票的历史数据
for ticker in tickers:
# 获取美股日线数据(qfq表示前复权,相当于Adj Close)
stock_data = ak.stock_us_daily(symbol=ticker, adjust="qfq")
# 过滤日期范围
stock_data['date'] = pd.to_datetime(stock_data['date'])
mask = (stock_data['date'] >= start_date) & (stock_data['date'] <= end_date)
filtered_data = stock_data.loc[mask]
# 设置日期为索引
filtered_data.set_index('date', inplace=True)
filtered_data.sort_index(inplace=True)
# 添加到主数据框
data[ticker] = filtered_data['close']
# 计算收益率
returns = data.pct_change().dropna()
### 计算组合收益
portfolio_returns = returns.dot(weights)
### 设置参数
confidence_level = 0.95
investment_value = 1000000 # 100万投资
# 打印结果确认
print(f"数据范围: {data.index.min()} 至 {data.index.max()}")
print(f"数据样本数: {len(returns)}")
print(f"前5个交易日组合收益率:\n{portfolio_returns.head()}")
数据范围: 2021-01-04 00:00:00 至 2022-12-30 00:00:00 数据样本数: 502 前5个交易日组合收益率: date 2021-01-05 $0.01 2021-01-06 $-0.03 2021-01-07 $0.03 2021-01-08 $0.01 2021-01-11 $-0.02 dtype: float64
### 计算历史模拟法VaR
historical_var = -np.percentile(portfolio_returns, (1-confidence_level)*100)
historical_var_value = historical_var * investment_value
print(f"95% 历史模拟法VaR: {historical_var:.4f} ({historical_var_value:.2f}元)")
### 计算参数法VaR
mean = np.mean(portfolio_returns)
std = np.std(portfolio_returns)
parametric_var = -(mean + std * norm.ppf(1-confidence_level))
parametric_var_value = parametric_var * investment_value
print(f"95% 参数法VaR: {parametric_var:.4f} ({parametric_var_value:.2f}元)")
### 蒙特卡洛模拟法VaR
np.random.seed(42) ### 设置随机种子以确保结果可重复
n_simulations = 10000 ### 模拟次数
### 使用历史均值和标准差生成随机收益率
mc_returns = np.random.normal(mean, std, n_simulations)
mc_var = -np.percentile(mc_returns, (1-confidence_level)*100)
mc_var_value = mc_var * investment_value
print(f"95% 蒙特卡洛模拟法VaR: {mc_var:.4f} ({mc_var_value:.2f}元)")
95% 历史模拟法VaR: 0.0305 (30536.88元) 95% 参数法VaR: 0.0304 (30374.36元) 95% 蒙特卡洛模拟法VaR: 0.0306 (30559.44元)
### 可视化收益率分布与VaR
plt.figure(figsize=(12, 8))
### 绘制收益率分布直方图
plt.hist(portfolio_returns, bins=50, alpha=0.5, density=True,
label='历史收益率分布')
### 添加VaR线
plt.axvline(-historical_var, color='r', linestyle='--',
label=f'历史模拟法VaR (95%): {historical_var:.4f}')
plt.axvline(-parametric_var, color='g', linestyle='--',
label=f'参数法VaR (95%): {parametric_var:.4f}')
plt.axvline(-mc_var, color='b', linestyle='--',
label=f'蒙特卡洛模拟法VaR (95%): {mc_var:.4f}')
### 添加正态分布曲线
x = np.linspace(min(portfolio_returns), max(portfolio_returns), 1000)
plt.plot(x, norm.pdf(x, mean, std), 'k-', lw=2,
label='正态分布拟合')
plt.legend(fontsize=10)
plt.title('投资组合收益率分布与VaR比较', fontsize=15)
plt.xlabel('日收益率', fontsize=12)
plt.ylabel('概率密度', fontsize=12)
plt.grid(True, alpha=0.3)
d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 23494 (\N{CJK UNIFIED IDEOGRAPH-5BC6}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 24230 (\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 25237 (\N{CJK UNIFIED IDEOGRAPH-6295}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 36164 (\N{CJK UNIFIED IDEOGRAPH-8D44}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 32452 (\N{CJK UNIFIED IDEOGRAPH-7EC4}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 19982 (\N{CJK UNIFIED IDEOGRAPH-4E0E}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27604 (\N{CJK UNIFIED IDEOGRAPH-6BD4}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 36739 (\N{CJK UNIFIED IDEOGRAPH-8F83}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 21382 (\N{CJK UNIFIED IDEOGRAPH-5386}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 21490 (\N{CJK UNIFIED IDEOGRAPH-53F2}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27169 (\N{CJK UNIFIED IDEOGRAPH-6A21}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 25311 (\N{CJK UNIFIED IDEOGRAPH-62DF}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27861 (\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 21442 (\N{CJK UNIFIED IDEOGRAPH-53C2}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 25968 (\N{CJK UNIFIED IDEOGRAPH-6570}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 33945 (\N{CJK UNIFIED IDEOGRAPH-8499}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 29305 (\N{CJK UNIFIED IDEOGRAPH-7279}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 21345 (\N{CJK UNIFIED IDEOGRAPH-5361}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27931 (\N{CJK UNIFIED IDEOGRAPH-6D1B}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 27491 (\N{CJK UNIFIED IDEOGRAPH-6B63}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\events.py:82: UserWarning: Glyph 24577 (\N{CJK UNIFIED IDEOGRAPH-6001}) missing from current font. func(*args, **kwargs) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 23494 (\N{CJK UNIFIED IDEOGRAPH-5BC6}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24230 (\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25237 (\N{CJK UNIFIED IDEOGRAPH-6295}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 36164 (\N{CJK UNIFIED IDEOGRAPH-8D44}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 32452 (\N{CJK UNIFIED IDEOGRAPH-7EC4}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 19982 (\N{CJK UNIFIED IDEOGRAPH-4E0E}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27604 (\N{CJK UNIFIED IDEOGRAPH-6BD4}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 36739 (\N{CJK UNIFIED IDEOGRAPH-8F83}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21382 (\N{CJK UNIFIED IDEOGRAPH-5386}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21490 (\N{CJK UNIFIED IDEOGRAPH-53F2}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27169 (\N{CJK UNIFIED IDEOGRAPH-6A21}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25311 (\N{CJK UNIFIED IDEOGRAPH-62DF}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27861 (\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21442 (\N{CJK UNIFIED IDEOGRAPH-53C2}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25968 (\N{CJK UNIFIED IDEOGRAPH-6570}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 33945 (\N{CJK UNIFIED IDEOGRAPH-8499}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 29305 (\N{CJK UNIFIED IDEOGRAPH-7279}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21345 (\N{CJK UNIFIED IDEOGRAPH-5361}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27931 (\N{CJK UNIFIED IDEOGRAPH-6D1B}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27491 (\N{CJK UNIFIED IDEOGRAPH-6B63}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24577 (\N{CJK UNIFIED IDEOGRAPH-6001}) missing from current font. fig.canvas.print_figure(bytes_io, **kw)
### 计算10天VaR (使用平方根法则)
time_horizon = 10 ### 10天持有期
historical_var_10d = historical_var * np.sqrt(time_horizon)
parametric_var_10d = parametric_var * np.sqrt(time_horizon)
mc_var_10d = mc_var * np.sqrt(time_horizon)
print("\n10天持有期VaR (平方根法则):")
print(f"历史模拟法VaR (10天): {historical_var_10d:.4f} ({historical_var_10d*investment_value:.2f}元)")
print(f"参数法VaR (10天): {parametric_var_10d:.4f} ({parametric_var_10d*investment_value:.2f}元)")
print(f"蒙特卡洛模拟法VaR (10天): {mc_var_10d:.4f} ({mc_var_10d*investment_value:.2f}元)")
### 计算各资产对组合VaR的贡献
cov_matrix = returns.cov()
portfolio_variance = weights.T @ cov_matrix @ weights
portfolio_std = np.sqrt(portfolio_variance)
### 边际贡献
marginal_contrib = (cov_matrix @ weights) / portfolio_std
component_var = weights * marginal_contrib * norm.ppf(confidence_level)
percent_contrib = component_var / np.sum(component_var) * 100
var_contrib = pd.DataFrame({
'Asset': tickers,
'Weight': weights * 100,
'VaR Contribution': component_var,
'Contribution %': percent_contrib
})
print("\n各资产VaR贡献:")
print(var_contrib)
10天持有期VaR (平方根法则): 历史模拟法VaR (10天): 0.0966 (96566.08元) 参数法VaR (10天): 0.0961 (96052.15元) 蒙特卡洛模拟法VaR (10天): 0.0966 (96637.43元) 各资产VaR贡献: Asset Weight VaR Contribution Contribution % AAPL AAPL $30.00 $0.01 $28.99 MSFT MSFT $30.00 $0.01 $28.57 AMZN AMZN $20.00 $0.01 $22.69 GOOGL GOOGL $20.00 $0.01 $19.75
### 历史模拟法ES
def calculate_historical_es(returns, alpha=0.95):
var = -np.percentile(returns, (1-alpha)*100)
es = -np.mean(returns[returns <= -var])
return es
### 参数法ES (正态分布假设)
def calculate_parametric_es(mu, sigma, alpha=0.95):
z_score = norm.ppf(1-alpha)
es = -(mu + sigma * norm.pdf(z_score)/(1-alpha))
return es
### 计算实例
hist_es = calculate_historical_es(portfolio_returns)
para_es = calculate_parametric_es(
np.mean(portfolio_returns),
np.std(portfolio_returns))
# import numpy as np
# import pandas as pd
# import matplotlib.pyplot as plt
# from scipy.stats import norm, t
# import yfinance as yf
# # 下载数据
# symbol = 'SPY' # 标普500ETF
# data = yf.download(symbol, start='2018-01-01', end='2023-01-01')
# returns = data['Adj Close'].pct_change().dropna()
# print(f"数据点数: {len(returns)}")
# print(f"平均收益率: {np.mean(returns)*100:.4f}%")
# print(f"收益率标准差: {np.std(returns)*100:.4f}%")
# print(f"最小收益率: {min(returns)*100:.4f}%")
# print(f"最大收益率: {max(returns)*100:.4f}%")
# print(f"偏度: {returns.skew():.4f}")
# print(f"峰度: {returns.kurtosis():.4f}")
# # 检查是否存在异常值
# plt.figure(figsize=(12, 5))
# plt.subplot(1, 2, 1)
# plt.plot(returns.index, returns, linewidth=1)
# plt.title('SPY每日收益率')
# plt.grid(True)
# plt.subplot(1, 2, 2)
# plt.hist(returns, bins=50, alpha=0.75)
# plt.title('收益率分布')
# plt.grid(True)
# plt.tight_layout()
# plt.show()
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import norm, t
import akshare as ak
# 下载数据
symbol = 'SPY' # 标普500ETF
stock_data = ak.stock_us_daily(symbol=symbol, adjust="qfq") # qfq表示前复权数据
# 处理日期范围
stock_data['date'] = pd.to_datetime(stock_data['date'])
mask = (stock_data['date'] >= '2018-01-01') & (stock_data['date'] <= '2023-01-01')
data = stock_data.loc[mask].copy()
# 按日期排序
data.sort_values('date', inplace=True)
data.set_index('date', inplace=True)
# 计算收益率
returns = data['close'].pct_change().dropna()
# 打印统计信息
print(f"数据点数: {len(returns)}")
print(f"平均收益率: {np.mean(returns)*100:.4f}%")
print(f"收益率标准差: {np.std(returns)*100:.4f}%")
print(f"最小收益率: {min(returns)*100:.4f}%")
print(f"最大收益率: {max(returns)*100:.4f}%")
print(f"偏度: {returns.skew():.4f}")
print(f"峰度: {returns.kurtosis():.4f}")
# 检查是否存在异常值
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(returns.index, returns, linewidth=1)
plt.title('SPY每日收益率')
plt.grid(True)
plt.subplot(1, 2, 2)
plt.hist(returns, bins=50, alpha=0.75)
plt.title('收益率分布')
plt.grid(True)
plt.tight_layout()
plt.show()
数据点数: 1258 平均收益率: 0.0505% 收益率标准差: 1.5136% 最小收益率: -12.4769% 最大收益率: 10.5631% 偏度: -0.5074 峰度: 11.5832
C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 27599 (\N{CJK UNIFIED IDEOGRAPH-6BCF}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1861880576.py:43: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. plt.tight_layout() d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27599 (\N{CJK UNIFIED IDEOGRAPH-6BCF}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 26085 (\N{CJK UNIFIED IDEOGRAPH-65E5}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. fig.canvas.print_figure(bytes_io, **kw)
# 设置参数
confidence_level = 0.99 # 使用99%置信水平
position = 1000000 # 100万美元仓位
n_simulations = 10000 # 蒙特卡洛模拟次数
# 1. 参数法VaR - 正态分布
mu = np.mean(returns)
sigma = np.std(returns)
var_normal = -position * (mu + sigma * norm.ppf(1-confidence_level))
# 同时计算95%的VaR
var_normal_95 = -position * (mu + sigma * norm.ppf(1-0.95))
# 2. 参数法VaR - t分布
# 使用t分布拟合数据
params = t.fit(returns)
df, loc, scale = params # 得到自由度、位置和尺度参数
var_t = -position * (loc + scale * t.ppf(1-confidence_level, df))
var_t_95 = -position * (loc + scale * t.ppf(1-0.95, df))
print(f"t分布拟合参数: 自由度={df:.2f}, 位置={loc:.6f}, 尺度={scale:.6f}")
# 3. 历史模拟法
var_hist = -position * np.percentile(returns, (1-confidence_level)*100)
var_hist_95 = -position * np.percentile(returns, (1-0.95)*100)
# 计算条件尾部期望(Expected Shortfall)
es_hist = -position * returns[returns <= -var_hist/position].mean()
t分布拟合参数: 自由度=2.65, 位置=0.001154, 尺度=0.008563
# 4. 蒙特卡洛模拟 - 正态分布
np.random.seed(42) # 设置随机种子确保结果可重复
sim_returns_normal = np.random.normal(mu, sigma, n_simulations)
var_mc_normal = -position * np.percentile(sim_returns_normal, (1-confidence_level)*100)
var_mc_normal_95 = -position * np.percentile(sim_returns_normal, (1-0.95)*100)
# 5. 蒙特卡洛模拟 - t分布
sim_returns_t = t.rvs(df, loc=loc, scale=scale, size=n_simulations)
var_mc_t = -position * np.percentile(sim_returns_t, (1-confidence_level)*100)
var_mc_t_95 = -position * np.percentile(sim_returns_t, (1-0.95)*100)
# 6. 加权历史模拟法
# 使用指数衰减权重使最近数据权重更高
lambda_factor = 0.94 # BRW方法中常用的衰减因子
weights = np.array([(1-lambda_factor) * lambda_factor**(len(returns)-i-1)
for i in range(len(returns))])
weights = weights / sum(weights) # 标准化权重
# 按权重排序收益率
sorted_indices = np.argsort(returns)
sorted_returns = returns.iloc[sorted_indices]
cumulative_weights = np.cumsum(weights[sorted_indices])
# 找到对应置信水平的收益率
var_weight_index = np.searchsorted(cumulative_weights, 1-confidence_level)
var_weighted = -position * sorted_returns.iloc[var_weight_index]
var_weight_index_95 = np.searchsorted(cumulative_weights, 1-0.95)
var_weighted_95 = -position * sorted_returns.iloc[var_weight_index_95]
# 结果对比
results = pd.DataFrame({
'Method': ['正态分布参数法', 't分布参数法', '历史模拟法',
'蒙特卡洛(正态)', '蒙特卡洛(t分布)', '加权历史模拟法'],
'VaR_99%': [var_normal, var_t, var_hist,
var_mc_normal, var_mc_t, var_weighted],
'VaR_95%': [var_normal_95, var_t_95, var_hist_95,
var_mc_normal_95, var_mc_t_95, var_weighted_95]
})
# 计算方法间的差异百分比
base_method = '历史模拟法' # 使用历史模拟法作为基准
base_var_99 = results.loc[results['Method'] == base_method, 'VaR_99%'].values[0]
base_var_95 = results.loc[results['Method'] == base_method, 'VaR_95%'].values[0]
results['Diff_99%'] = (results['VaR_99%'] - base_var_99) / base_var_99 * 100
results['Diff_95%'] = (results['VaR_95%'] - base_var_95) / base_var_95 * 100
# 格式化输出
pd.set_option('display.float_format', '${:.2f}'.format)
print("\n不同VaR计算方法比较(99%置信水平):")
print(results[['Method', 'VaR_99%', 'Diff_99%', 'VaR_95%', 'Diff_95%']])
# 可视化VaR比较
plt.figure(figsize=(14, 6))
plt.bar(results['Method'], results['VaR_99%'], alpha=0.7)
plt.title('不同方法99% VaR比较 (100万美元头寸)', fontsize=15)
plt.xticks(rotation=45, ha='right')
plt.ylabel('VaR (美元)', fontsize=12)
plt.grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
不同VaR计算方法比较(99%置信水平): Method VaR_99% Diff_99% VaR_95% Diff_95% 0 正态分布参数法 $34707.89 $-15.51 $24392.53 $3.64 1 t分布参数法 $42126.53 $2.56 $20124.76 $-14.50 2 历史模拟法 $41077.01 $0.00 $23536.72 $0.00 3 蒙特卡洛(正态) $34620.02 $-15.72 $24543.96 $4.28 4 蒙特卡洛(t分布) $41131.40 $0.13 $19303.71 $-17.98 5 加权历史模拟法 $25560.91 $-37.77 $21572.03 $-8.35
C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 27491 (\N{CJK UNIFIED IDEOGRAPH-6B63}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 24577 (\N{CJK UNIFIED IDEOGRAPH-6001}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21442 (\N{CJK UNIFIED IDEOGRAPH-53C2}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 25968 (\N{CJK UNIFIED IDEOGRAPH-6570}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 27861 (\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21382 (\N{CJK UNIFIED IDEOGRAPH-5386}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21490 (\N{CJK UNIFIED IDEOGRAPH-53F2}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 27169 (\N{CJK UNIFIED IDEOGRAPH-6A21}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 25311 (\N{CJK UNIFIED IDEOGRAPH-62DF}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 33945 (\N{CJK UNIFIED IDEOGRAPH-8499}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 29305 (\N{CJK UNIFIED IDEOGRAPH-7279}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21345 (\N{CJK UNIFIED IDEOGRAPH-5361}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 27931 (\N{CJK UNIFIED IDEOGRAPH-6D1B}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21152 (\N{CJK UNIFIED IDEOGRAPH-52A0}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 26435 (\N{CJK UNIFIED IDEOGRAPH-6743}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 32654 (\N{CJK UNIFIED IDEOGRAPH-7F8E}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 20803 (\N{CJK UNIFIED IDEOGRAPH-5143}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 19981 (\N{CJK UNIFIED IDEOGRAPH-4E0D}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 21516 (\N{CJK UNIFIED IDEOGRAPH-540C}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 26041 (\N{CJK UNIFIED IDEOGRAPH-65B9}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 27604 (\N{CJK UNIFIED IDEOGRAPH-6BD4}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 36739 (\N{CJK UNIFIED IDEOGRAPH-8F83}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 19975 (\N{CJK UNIFIED IDEOGRAPH-4E07}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 22836 (\N{CJK UNIFIED IDEOGRAPH-5934}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\1847955310.py:31: UserWarning: Glyph 23544 (\N{CJK UNIFIED IDEOGRAPH-5BF8}) missing from current font. plt.tight_layout() d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27491 (\N{CJK UNIFIED IDEOGRAPH-6B63}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24577 (\N{CJK UNIFIED IDEOGRAPH-6001}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21442 (\N{CJK UNIFIED IDEOGRAPH-53C2}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25968 (\N{CJK UNIFIED IDEOGRAPH-6570}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27861 (\N{CJK UNIFIED IDEOGRAPH-6CD5}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21382 (\N{CJK UNIFIED IDEOGRAPH-5386}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21490 (\N{CJK UNIFIED IDEOGRAPH-53F2}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27169 (\N{CJK UNIFIED IDEOGRAPH-6A21}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25311 (\N{CJK UNIFIED IDEOGRAPH-62DF}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 33945 (\N{CJK UNIFIED IDEOGRAPH-8499}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 29305 (\N{CJK UNIFIED IDEOGRAPH-7279}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21345 (\N{CJK UNIFIED IDEOGRAPH-5361}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27931 (\N{CJK UNIFIED IDEOGRAPH-6D1B}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21152 (\N{CJK UNIFIED IDEOGRAPH-52A0}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 26435 (\N{CJK UNIFIED IDEOGRAPH-6743}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 32654 (\N{CJK UNIFIED IDEOGRAPH-7F8E}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 20803 (\N{CJK UNIFIED IDEOGRAPH-5143}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 19981 (\N{CJK UNIFIED IDEOGRAPH-4E0D}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21516 (\N{CJK UNIFIED IDEOGRAPH-540C}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 26041 (\N{CJK UNIFIED IDEOGRAPH-65B9}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27604 (\N{CJK UNIFIED IDEOGRAPH-6BD4}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 36739 (\N{CJK UNIFIED IDEOGRAPH-8F83}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 19975 (\N{CJK UNIFIED IDEOGRAPH-4E07}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 22836 (\N{CJK UNIFIED IDEOGRAPH-5934}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 23544 (\N{CJK UNIFIED IDEOGRAPH-5BF8}) missing from current font. fig.canvas.print_figure(bytes_io, **kw)
# 可视化分布对比
plt.figure(figsize=(12, 6))
plt.hist(returns, bins=50, density=True, alpha=0.5, label='实际收益率')
# 拟合分布
x = np.linspace(min(returns), max(returns), 1000)
plt.plot(x, norm.pdf(x, mu, sigma), 'r-', lw=2, label='正态分布')
plt.plot(x, t.pdf(x, df, loc, scale), 'g-', lw=2, label='t分布')
# 添加VaR标记线
plt.axvline(x=-var_normal/position, color='r', linestyle='--',
label=f'正态分布99% VaR: ${var_normal:.0f}')
plt.axvline(x=-var_t/position, color='g', linestyle='--',
label=f't分布99% VaR: ${var_t:.0f}')
plt.axvline(x=-var_hist/position, color='b', linestyle='--',
label=f'历史模拟99% VaR: ${var_hist:.0f}')
plt.legend()
plt.title('收益率分布拟合与VaR比较', fontsize=15)
plt.xlabel('收益率', fontsize=12)
plt.ylabel('概率密度', fontsize=12)
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 回测分析(简化版)
exceed_normal = sum(returns < -var_normal_95/position)
exceed_t = sum(returns < -var_t_95/position)
exceed_hist = sum(returns < -var_hist_95/position)
expected_exceeds = len(returns) * (1-0.95) # 期望违例数
print(f"\n95%置信水平回测结果:")
print(f"样本数量: {len(returns)}")
print(f"期望违例数: {expected_exceeds:.1f}")
print(f"正态分布违例数: {exceed_normal} ({exceed_normal/len(returns)*100:.2f}%)")
print(f"t分布违例数: {exceed_t} ({exceed_t/len(returns)*100:.2f}%)")
print(f"历史模拟违例数: {exceed_hist} ({exceed_hist/len(returns)*100:.2f}%)")
C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 23494 (\N{CJK UNIFIED IDEOGRAPH-5BC6}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 24230 (\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 20998 (\N{CJK UNIFIED IDEOGRAPH-5206}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 24067 (\N{CJK UNIFIED IDEOGRAPH-5E03}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 25311 (\N{CJK UNIFIED IDEOGRAPH-62DF}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 19982 (\N{CJK UNIFIED IDEOGRAPH-4E0E}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 27604 (\N{CJK UNIFIED IDEOGRAPH-6BD4}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 36739 (\N{CJK UNIFIED IDEOGRAPH-8F83}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 23454 (\N{CJK UNIFIED IDEOGRAPH-5B9E}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 38469 (\N{CJK UNIFIED IDEOGRAPH-9645}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 27491 (\N{CJK UNIFIED IDEOGRAPH-6B63}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 24577 (\N{CJK UNIFIED IDEOGRAPH-6001}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 21382 (\N{CJK UNIFIED IDEOGRAPH-5386}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 21490 (\N{CJK UNIFIED IDEOGRAPH-53F2}) missing from current font. plt.tight_layout() C:\Users\wukek\AppData\Local\Temp\ipykernel_178052\2517428418.py:23: UserWarning: Glyph 27169 (\N{CJK UNIFIED IDEOGRAPH-6A21}) missing from current font. plt.tight_layout() d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 25910 (\N{CJK UNIFIED IDEOGRAPH-6536}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 30410 (\N{CJK UNIFIED IDEOGRAPH-76CA}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 29575 (\N{CJK UNIFIED IDEOGRAPH-7387}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 27010 (\N{CJK UNIFIED IDEOGRAPH-6982}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 23494 (\N{CJK UNIFIED IDEOGRAPH-5BC6}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 24230 (\N{CJK UNIFIED IDEOGRAPH-5EA6}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 21512 (\N{CJK UNIFIED IDEOGRAPH-5408}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 19982 (\N{CJK UNIFIED IDEOGRAPH-4E0E}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 23454 (\N{CJK UNIFIED IDEOGRAPH-5B9E}) missing from current font. fig.canvas.print_figure(bytes_io, **kw) d:\Users\wukek\anaconda3\Lib\site-packages\IPython\core\pylabtools.py:152: UserWarning: Glyph 38469 (\N{CJK UNIFIED IDEOGRAPH-9645}) missing from current font. fig.canvas.print_figure(bytes_io, **kw)
95%置信水平回测结果: 样本数量: 1258 期望违例数: 62.9 正态分布违例数: 60 (4.77%) t分布违例数: 85 (6.76%) 历史模拟违例数: 63 (5.01%)
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.stats import norm
# Black-Scholes期权定价模型
def bs_call_price(S, K, T, r, sigma):
"""
计算欧式看涨期权价格
参数:
S: 标的资产价格
K: 行权价
T: 到期时间(年)
r: 无风险利率
sigma: 波动率
返回:
看涨期权价格
"""
d1 = (np.log(S/K) + (r + 0.5*sigma**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)
def bs_put_price(S, K, T, r, sigma):
"""
计算欧式看跌期权价格
参数与看涨期权相同
"""
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
return K*np.exp(-r*T)*norm.cdf(-d2) - S*norm.cdf(-d1)
# 计算希腊字母
def bs_greeks(S, K, T, r, sigma, option_type='call'):
"""
计算欧式期权的希腊字母
参数:
S: 标的资产价格
K: 行权价
T: 到期时间(年)
r: 无风险利率
sigma: 波动率
option_type: 'call'表示看涨期权,'put'表示看跌期权
返回:
包含期权价格和希腊字母的字典
"""
d1 = (np.log(S/K) + (r + 0.5*sigma**2)*T) / (sigma*np.sqrt(T))
d2 = d1 - sigma*np.sqrt(T)
if option_type == 'call':
price = bs_call_price(S, K, T, r, sigma)
delta = norm.cdf(d1)
theta = -(S*norm.pdf(d1)*sigma)/(2*np.sqrt(T)) - r*K*np.exp(-r*T)*norm.cdf(d2)
else: # 'put'
price = bs_put_price(S, K, T, r, sigma)
delta = norm.cdf(d1) - 1
theta = -(S*norm.pdf(d1)*sigma)/(2*np.sqrt(T)) + r*K*np.exp(-r*T)*norm.cdf(-d2)
gamma = norm.pdf(d1) / (S*sigma*np.sqrt(T))
vega = S * norm.pdf(d1) * np.sqrt(T) / 100 # 对应波动率变动1%
rho = K * T * np.exp(-r*T) * (norm.cdf(d2) if option_type=='call' else -norm.cdf(-d2)) / 100 # 对应利率变动1%
return {'price': price, 'delta': delta, 'gamma': gamma,
'vega': vega, 'theta': theta, 'rho': rho}
# 参数设置
S = 100 # 标的价格
K = 100 # 行权价
T = 0.5 # 到期时间(年)
r = 0.05 # 无风险利率
sigma = 0.2 # 波动率
# 计算期权价格和希腊字母
call_greeks = bs_greeks(S, K, T, r, sigma, 'call')
put_greeks = bs_greeks(S, K, T, r, sigma, 'put')
print("看涨期权:")
for greek, value in call_greeks.items():
print(f"{greek}: {value:.6f}")
print("\n看跌期权:")
for greek, value in put_greeks.items():
print(f"{greek}: {value:.6f}")
# 创建Greeks变化表
print("\nGreeks随标的价格变化表:")
prices = np.linspace(80, 120, 9)
greeks_data = []
for price in prices:
call_greeks = bs_greeks(price, K, T, r, sigma, 'call')
greeks_data.append({
'S': price,
'Call_Price': call_greeks['price'],
'Call_Delta': call_greeks['delta'],
'Call_Gamma': call_greeks['gamma'],
'Call_Vega': call_greeks['vega'],
'Call_Theta': call_greeks['theta']
})
greeks_df = pd.DataFrame(greeks_data)
print(greeks_df.round(4))
看涨期权: price: 6.888729 delta: 0.597734 gamma: 0.027359 vega: 0.273587 theta: -8.115968 rho: 0.264424 看跌期权: price: 4.419720 delta: -0.402266 gamma: 0.027359 vega: 0.273587 theta: -3.239418 rho: -0.223231 Greeks随标的价格变化表: S Call_Price Call_Delta Call_Gamma Call_Vega Call_Theta 0 $80.00 $0.46 $0.09 $0.01 $0.09 $-2.21 1 $85.00 $1.13 $0.18 $0.02 $0.16 $-3.92 2 $90.00 $2.35 $0.31 $0.03 $0.22 $-5.76 3 $95.00 $4.25 $0.45 $0.03 $0.27 $-7.27 4 $100.00 $6.89 $0.60 $0.03 $0.27 $-8.12 5 $105.00 $10.20 $0.72 $0.02 $0.25 $-8.26 6 $110.00 $14.08 $0.82 $0.02 $0.20 $-7.87 7 $115.00 $18.37 $0.89 $0.01 $0.15 $-7.23 8 $120.00 $22.95 $0.94 $0.01 $0.10 $-6.56
# Delta中性对冲
stock_position = 100 # 持有100股标的
call_contracts = 2 # 持有2张看涨期权合约(每张控制100股)
shares_per_contract = 100 # 每张期权合约对应的股数
portfolio_delta = stock_position + call_contracts * shares_per_contract * call_greeks['delta']
hedge_contracts = -portfolio_delta / (shares_per_contract * put_greeks['delta'])
print(f"\n当前组合Delta: {portfolio_delta:.2f}")
print(f"实现Delta中性需要: {hedge_contracts:.2f} 份看跌期权合约")
# 模拟Delta对冲P&L
def simulate_delta_hedge(S, K, T, r, sigma, days, price_path=None, hedge_freq=1):
"""
模拟Delta对冲策略的损益
参数:
S, K, T, r, sigma: 与前面相同
days: 模拟天数
price_path: 预定义价格路径,如果为None则生成随机路径
hedge_freq: 调整对冲头寸的频率(天)
返回:
对冲损益结果
"""
dt = 1/252 # 一个交易日
n_steps = days
# 生成或使用价格路径
if price_path is None:
np.random.seed(42)
price_path = [S]
for i in range(n_steps):
price_path.append(price_path[-1] * np.exp((r - 0.5*sigma**2)*dt +
sigma*np.sqrt(dt)*np.random.normal()))
# 初始化
option_price = bs_call_price(S, K, T, r, sigma)
cash = -option_price # 卖出看涨期权
delta = bs_greeks(S, K, T, r, sigma, 'call')['delta']
stock = delta * S # 买入Delta数量的标的
cash -= stock # 支付标的购买成本
prices = []
portfolio_values = []
deltas = []
# 模拟对冲过程
for day in range(1, n_steps+1):
# 更新价格和时间
current_price = price_path[day]
current_T = T - day*dt
# 记录当前状态
prices.append(current_price)
current_option_price = bs_call_price(current_price, K, current_T, r, sigma)
stock_value = delta * current_price
portfolio_value = cash + stock_value - current_option_price
portfolio_values.append(portfolio_value)
deltas.append(delta)
# 根据频率调整对冲
if day % hedge_freq == 0 and current_T > dt:
# 计算新的Delta
new_delta = bs_greeks(current_price, K, current_T, r, sigma, 'call')['delta']
# 调整股票头寸
adjustment = new_delta - delta
cash -= adjustment * current_price # 买入更多股票需要支付现金
delta = new_delta
return {
'prices': prices,
'portfolio_values': portfolio_values,
'deltas': deltas
}
当前组合Delta: 287.56 实现Delta中性需要: 7.15 份看跌期权合约
# 可视化Delta曲线
spot_range = np.linspace(80, 120, 100)
call_deltas = [bs_greeks(s, K, T, r, sigma, 'call')['delta'] for s in spot_range]
put_deltas = [bs_greeks(s, K, T, r, sigma, 'put')['delta'] for s in spot_range]
plt.figure(figsize=(12, 6))
plt.plot(spot_range, call_deltas, 'b-', label='Call Delta')
plt.plot(spot_range, put_deltas, 'r-', label='Put Delta')
plt.axvline(x=K, color='g', linestyle='--', label='Strike Price')
plt.axhline(y=0, color='k', linestyle='-')
plt.grid(True)
plt.legend()
plt.title('Option Delta vs. Underlying Price')
plt.xlabel('Underlying Price')
plt.ylabel('Delta')
# 可视化Delta对冲P&L
days_to_simulate = 30
price_move = 0.005 # 每日0.5%的价格变动
# 生成价格路径
price_path = [S]
for i in range(days_to_simulate):
price_path.append(price_path[-1] * (1 + np.random.normal(0, price_move)))
# 模拟不同对冲频率
daily_hedge = simulate_delta_hedge(S, K, T, r, sigma, days_to_simulate, price_path, hedge_freq=1)
weekly_hedge = simulate_delta_hedge(S, K, T, r, sigma, days_to_simulate, price_path, hedge_freq=5)
plt.figure(figsize=(12, 8))
plt.subplot(2, 1, 1)
plt.plot(range(days_to_simulate), daily_hedge['portfolio_values'], 'b-', label='Daily Hedging')
plt.plot(range(days_to_simulate), weekly_hedge['portfolio_values'], 'r-', label='Weekly Hedging')
plt.legend()
plt.title('Delta Hedging P&L')
plt.ylabel('P&L')
plt.grid(True)
plt.subplot(2, 1, 2)
plt.plot(range(days_to_simulate+1), price_path, 'g-')
plt.title('Underlying Price Path')
plt.xlabel('Days')
plt.ylabel('Price')
plt.grid(True)
plt.tight_layout()
plt.show()