查看全集:💎Quantopia量化分析56讲
假设你在21点游戏中拥有1%的优势,若将所有资金押注在一局游戏,尽管胜率51%,但仍有49%概率血本无归。通过将资金分散到100局独立游戏中,虽然期望收益相同,但总收益的波动性(风险)会大幅降低。
import numpy as np
import matplotlib.pyplot as plt
# 模拟1000次单局赌博
universes = 1000
single_bet = np.random.binomial(n=1, p=0.51, size=universes)
print(f"单局均值:{np.mean(single_bet):.2f}, 标准差:{np.std(single_bet):.2f}")
# 模拟100次分散赌博
diversified = np.random.binomial(n=100, p=0.51, size=universes)
print(f"百局均值:{np.mean(diversified):.2f}, 标准差:{np.std(diversified):.2f}")
关键输出:
单局均值:0.51, 标准差:0.50
百局均值:51.00, 标准差:5.00
import yfinance as yf
# 获取科技股与能源股数据
tech = yf.download(['AAPL', 'MSFT', 'GOOG'], start='2020-01-01', end='2023-01-01')['Close']
energy = yf.download(['XOM', 'CVX'], start='2020-01-01', end='2023-01-01')['Close']
# 计算相关系数矩阵
tech_returns = tech.pct_change().corr()
energy_returns = energy.pct_change().corr()
print("科技股相关系数:\n", tech_returns)
print("\n能源股相关系数:\n", energy_returns)
投资组合方差公式:
其中:
特殊情况:
def simulate_portfolio(n_assets, correlation):
np.random.seed(42)
means = [1.01] * n_assets
cov = (0.03**2) * (np.eye(n_assets)*1 + np.ones((n_assets,n_assets))*(correlation -1)/n_assets)
returns = np.random.multivariate_normal(means, cov, 252)
portfolio = returns.mean(axis=1)
return portfolio.std()
print(f"10只不相关资产波动率: {simulate_portfolio(10, 0):.4f}")
print(f"10只相关资产波动率: {simulate_portfolio(10, 0.8):.4f}")
# 获取不同行业股票数据
stocks = yf.download(['AAPL', 'XOM', 'JPM', 'WMT'], start='2020-01-01', end='2023-01-01')['Close']
returns = stocks.pct_change().dropna()
# 计算组合波动性
weights = np.array([0.25]*4)
cov_matrix = returns.cov() * 252 # 年化协方差
portfolio_vol = np.sqrt(weights.T @ cov_matrix @ weights)
print(f"四行业组合年化波动率: {portfolio_vol:.2%}")
注意:实际投资需考虑交易成本、流动性等因素,理论模型需结合市场微观结构分析
重要提醒:真正的风险分散需要底层逻辑的多样性,而非简单增加资产数量
根据马科维茨投资组合理论,组合波动率随资产数量增加呈渐进式下降:
其中:
这个公式说明组合的极限波动率由两个关键因素决定:平均相关系数的平方根与平均波动率的乘积。
关键推论:
def diversification_paradox(n_max=100, base_rho=0.3):
""" 展示相关系数变化时的分散化效果 """
n_assets = np.arange(2, n_max)
vol_list = []
for n in n_assets:
# 每增加5个资产,平均相关系数上升0.02
rho = base_rho + (n//5)*0.02
vol = np.sqrt( (1 + rho*(n-1))/n ) * 0.2
vol_list.append(vol)
plt.plot(n_assets, vol_list)
plt.xlabel('Number of Assets'); plt.ylabel('Portfolio Volatility')
plt.title('Diversification Paradox Simulation')
plt.show()
diversification_paradox(n_max=50, base_rho=0.2)
当组合包含看似分散实则关联的资产时:
# 分析FAANG股票与云计算ETF的相关性
tech = yf.download(['META', 'AMZN', 'NFLX', 'GOOG', 'MSFT', 'SNOW', 'DDOG'],
start='2020-01-01', end='2023-01-01')['Adj Close']
corr_matrix = tech.pct_change().corr()
print("科技股隐性相关系数矩阵:\n", corr_matrix.round(2))
分散投资小盘股的潜在风险:
# 比较大盘股与小盘股流动性指标
def calculate_liquidity(symbols):
data = yf.download(symbols, start='2023-01-01', end='2023-06-01')
return data['Volume'].mean(axis=0).sort_values()
large_cap = calculate_liquidity(['AAPL', 'MSFT', 'GOOG'])
small_cap = calculate_liquidity(['FIZZ', 'KNSA', 'RDNT'])
print("大盘股日均成交量:\n", large_cap)
print("\n小盘股日均成交量:\n", small_cap)
假设新增资产满足:
组合波动率变化推导过程:
第一步,新组合波动率表达式:
第二步,对权重求导:
第三步,判断条件:
其中:
情景设定:
def risk_acceleration_test():
np.random.seed(42)
base_assets = 10
added_groups = 4
results = []
current_rho = 0.25
for _ in range(added_groups):
# 每次添加资产使平均相关系数上升
current_rho += 0.15
n = base_assets + 5*(_+1)
vol = np.sqrt( (1 + current_rho*(n-1))/n ) * 0.18
results.append(vol)
plt.plot(range(added_groups), results, marker='o')
plt.xticks(range(added_groups), ['+5 Tech','+5 Fin','+5 Energy','+5 Retail'])
plt.ylabel('Portfolio Volatility'); plt.title('Industry Concentration Risk')
plt.show()
risk_acceleration_test()
黄金分割法则:
关于n求最优解,需要对方程求导并令其等于0:
这是一个权衡最优资产数量的数学表达式,其中包含了分散化带来的边际收益递减和管理成本线性增加两个因素。
n = np.arange(20, 100)
cost = 0.4/np.sqrt(n) + 0.003*n
plt.plot(n, cost)
plt.xlabel('Number of Assets'); plt.ylabel('Combined Cost')
plt.vlines(x=45, ymin=0, ymax=0.25, colors='r', linestyles='dashed')
plt.show()