Files
stock/stockapp/src/test_quant.py
2024-12-21 09:32:01 +08:00

83 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.optimize as sco
import yfinance as yf
# 下载资产历史数据
assets = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA'] # 资产代码
data = yf.download(assets, start="2020-01-01", end="2023-01-01")['Adj Close']
print(data)
# 计算每日收益率
returns = data.pct_change().dropna()
print(returns)
# 计算年化预期收益和协方差矩阵
annual_returns = returns.mean() * 252
cov_matrix = returns.cov() * 252
print(annual_returns)
print(cov_matrix)
# 定义组合的预期收益和风险(方差)
def portfolio_performance(weights, mean_returns, cov_matrix):
returns = np.sum(weights * mean_returns)
volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
return returns, volatility
# 定义目标函数:最小化风险(方差)
def minimize_volatility(weights, mean_returns, cov_matrix):
return portfolio_performance(weights, mean_returns, cov_matrix)[1]
# 定义约束条件
def constraint_sum(weights):
return np.sum(weights) - 1
# 初始化权重和边界每个资产的权重在0-1之间
num_assets = len(assets)
bounds = tuple((0, 1) for asset in range(num_assets))
initial_weights = num_assets * [1. / num_assets] # 初始等权重
# 定义约束条件总权重为1
constraints = ({'type': 'eq', 'fun': constraint_sum})
# 优化组合,使得组合的方差最小
opt_result = sco.minimize(minimize_volatility, initial_weights, args=(annual_returns, cov_matrix),
method='SLSQP', bounds=bounds, constraints=constraints)
# 提取最优权重
optimal_weights = opt_result.x
# 计算最优组合的收益和风险
optimal_return, optimal_volatility = portfolio_performance(optimal_weights, annual_returns, cov_matrix)
# 输出最优组合结果
print("最优资产组合权重:")
for i, asset in enumerate(assets):
print(f"{asset}: {optimal_weights[i]:.2%}")
print(f"\n最优组合的年化预期收益: {optimal_return:.2%}")
print(f"最优组合的年化风险(标准差): {optimal_volatility:.2%}")
# 可视化有效前沿
def plot_efficient_frontier(mean_returns, cov_matrix, num_portfolios=10000):
results = np.zeros((3, num_portfolios))
for i in range(num_portfolios):
weights = np.random.random(num_assets)
weights /= np.sum(weights)
portfolio_return, portfolio_volatility = portfolio_performance(weights, mean_returns, cov_matrix)
results[0, i] = portfolio_return
results[1, i] = portfolio_volatility
results[2, i] = results[0, i] / results[1, i] # 计算夏普比率
plt.figure(figsize=(10, 6))
plt.scatter(results[1, :], results[0, :], c=results[2, :], cmap='viridis')
plt.colorbar(label='Sharpe Ratio')
plt.scatter(optimal_volatility, optimal_return, c='red', marker='*', s=200) # 最优组合
plt.title('Efficient Frontier')
plt.xlabel('Volatility (Risk)')
plt.ylabel('Return')
plt.show()
# 绘制有效前沿
plot_efficient_frontier(annual_returns, cov_matrix)