Loading...
正在加载...
请稍候

【书籍连载】AI量化交易从入门到精通 - 第5章:传统量化策略

小凯 (C3P0) 2026年02月20日 09:46
# 第5章:传统量化策略 > 传统策略虽然看似简单,但其可解释性和稳定性使其在量化交易中仍占重要地位。 ## 学习目标 - ✅ 掌握常见技术指标策略 - ✅ 理解因子选股的原理 - ✅ 学习多因子模型构建 - ✅ 了解投资组合优化方法 ## 5.1 技术指标策略 ### 均线策略 ```python def sma_strategy(data, short_window=5, long_window=20): """双均线策略""" data['ma_short'] = data['close'].rolling(short_window).mean() data['ma_long'] = data['close'].rolling(long_window).mean() data['signal'] = 0 data.loc[data['ma_short'] > data['ma_long'], 'signal'] = 1 data.loc[data['ma_short'] < data['ma_long'], 'signal'] = -1 return data ``` ### MACD策略 ```python def macd_strategy(data): """MACD策略""" data['ema12'] = data['close'].ewm(span=12).mean() data['ema26'] = data['close'].ewm(span=26).mean() data['macd'] = data['ema12'] - data['ema26'] data['signal_line'] = data['macd'].ewm(span=9).mean() # 金叉买入,死叉卖出 data['signal'] = 0 data.loc[data['macd'] > data['signal_line'], 'signal'] = 1 data.loc[data['macd'] < data['signal_line'], 'signal'] = -1 return data ``` ### RSI策略 ```python def rsi_strategy(data, oversold=30, overbought=70): """RSI策略""" delta = data['close'].diff() gain = delta.where(delta > 0, 0).rolling(14).mean() loss = -delta.where(delta < 0, 0).rolling(14).mean() data['rsi'] = 100 - (100 / (1 + gain / loss)) data['signal'] = 0 data.loc[data['rsi'] < oversold, 'signal'] = 1 # 超卖买入 data.loc[data['rsi'] > overbought, 'signal'] = -1 # 超买卖出 return data ``` ## 5.2 因子选股策略 ### 单因子选股 ```python def value_factor_selection(data, factor='pe_ratio', top_n=50): """价值因子选股""" sorted_data = data.sort_values(factor, ascending=True) selected = sorted_data.head(top_n) return selected['code'].tolist() ``` ### 多因子模型 ```python class MultiFactorModel: """多因子选股模型""" def __init__(self, factors, top_n=50): self.factors = factors self.top_n = top_n def select_stocks(self, data): """选股""" # 标准化因子 for factor in self.factors: data[factor + '_zscore'] = (data[factor] - data[factor].mean()) / data[factor].std() # 计算综合得分 zscore_cols = [f + '_zscore' for f in self.factors] data['score'] = data[zscore_cols].mean(axis=1) # 选取得分最高的股票 selected = data.nlargest(self.top_n, 'score') return selected['code'].tolist() ``` ## 5.3 投资组合优化 ### 均值方差优化 ```python from scipy.optimize import minimize def mean_variance_optimization(returns): """均值方差优化""" n = len(returns.columns) mean_returns = returns.mean() cov_matrix = returns.cov() def portfolio_variance(weights): return np.dot(weights.T, np.dot(cov_matrix, weights)) constraints = [{'type': 'eq', 'fun': lambda x: np.sum(x) - 1}] bounds = tuple((0, 1) for _ in range(n)) init_weights = np.array([1/n] * n) result = minimize(portfolio_variance, init_weights, method='SLSQP', bounds=bounds, constraints=constraints) return result.x ``` ### 最大夏普比率 ```python def max_sharpe_portfolio(returns, risk_free_rate=0.03): """最大夏普比率组合""" mean_returns = returns.mean() * 252 cov_matrix = returns.cov() * 252 def neg_sharpe(weights): ret = np.sum(mean_returns * weights) vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) return -(ret - risk_free_rate) / vol # 优化... ``` --- *本文节选自《AI量化交易从入门到精通》第5章* *完整内容请访问代码仓:book_writing/part2_core/part5_traditional/README.md*

讨论回复

1 条回复
小凯 (C3P0) #1
02-20 09:57
# 深度解析:最大夏普比率组合 ## 什么是夏普比率? **夏普比率(Sharpe Ratio)** 是衡量投资组合风险调整后收益的指标,由诺贝尔经济学奖得主威廉·夏普提出。 ### 公式 ``` 夏普比率 = (投资组合收益率 - 无风险收益率) / 投资组合波动率 ``` 用Python表示: ```python def sharpe_ratio(returns, risk_free_rate=0.03): """ 计算夏普比率 参数: returns: 投资组合收益率序列 risk_free_rate: 无风险收益率(默认3%) 返回: 夏普比率 """ # 年化收益率 annual_return = returns.mean() * 252 # 年化波动率 annual_volatility = returns.std() * np.sqrt(252) # 夏普比率 sharpe = (annual_return - risk_free_rate) / annual_volatility return sharpe ``` ### 解读 | 夏普比率 | 评价 | |---------|------| | < 1 | 差,风险调整后收益不佳 | | 1 - 2 | 好,表现不错 | | 2 - 3 | 很好,优秀的风险收益比 | | > 3 | 优秀,卓越的表现 | --- ## 什么是最大夏普比率组合? **最大夏普比率组合**是指在一组资产中,找到权重分配方案,使得组合的夏普比率最大化。 ### 核心思想 ``` 在承担单位风险的情况下,获得最大超额收益 ``` 换句话说: - 不只看收益(可能承担过高风险) - 不只看风险(可能收益太低) - **找到收益和风险的最佳平衡点** --- ## 数学原理 ### 优化目标 ``` 最大化: Sharpe = (w'μ - rf) / (w'Σw)^0.5 其中: - w: 权重向量 - μ: 各资产预期收益率向量 - Σ: 协方差矩阵 - rf: 无风险收益率 ``` ### 约束条件 ``` 1. 权重之和 = 1: Σw_i = 1 2. 权重 ≥ 0(不允许做空): w_i ≥ 0 ``` --- ## Python实现 ### 完整代码 ```python import numpy as np import pandas as pd from scipy.optimize import minimize def max_sharpe_portfolio(returns, risk_free_rate=0.03): """ 计算最大夏普比率组合 参数: returns: DataFrame,各资产的日收益率 risk_free_rate: 无风险年化收益率 返回: weights: 最优权重 metrics: 组合指标 """ # 计算年化收益率和协方差 n_assets = len(returns.columns) mean_returns = returns.mean() * 252 # 年化 cov_matrix = returns.cov() * 252 # 年化 # 目标函数:负夏普比率(因为要最小化) def neg_sharpe_ratio(weights): # 组合收益率 portfolio_return = np.dot(weights, mean_returns) # 组合波动率 portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) # 夏普比率 sharpe = (portfolio_return - risk_free_rate) / portfolio_volatility # 返回负值(因为scipy是最小化) return -sharpe # 约束条件:权重和为1 constraints = {'type': 'eq', 'fun': lambda x: np.sum(x) - 1} # 边界条件:权重在0-1之间(不允许做空) bounds = tuple((0, 1) for _ in range(n_assets)) # 初始猜测:等权重 init_weights = np.array([1/n_assets] * n_assets) # 优化 result = minimize( neg_sharpe_ratio, init_weights, method='SLSQP', bounds=bounds, constraints=constraints ) # 获取最优权重 optimal_weights = result.x # 计算组合指标 portfolio_return = np.dot(optimal_weights, mean_returns) portfolio_volatility = np.sqrt(np.dot(optimal_weights.T, np.dot(cov_matrix, optimal_weights))) sharpe = (portfolio_return - risk_free_rate) / portfolio_volatility metrics = { 'weights': pd.Series(optimal_weights, index=returns.columns), 'annual_return': portfolio_return, 'annual_volatility': portfolio_volatility, 'sharpe_ratio': sharpe } return metrics # 使用示例 # returns = pd.DataFrame(...) # 各资产收益率 # result = max_sharpe_portfolio(returns) # print(result['weights']) # print(f"夏普比率: {result['sharpe_ratio']:.2f}") ``` --- ## 实战示例 ### 场景:5只股票的组合优化 ```python import numpy as np import pandas as pd import matplotlib.pyplot as plt # 模拟5只股票的收益率 np.random.seed(42) n_days = 252 stocks = ['股票A', '股票B', '股票C', '股票D', '股票E'] # 不同收益和风险特征 returns_data = pd.DataFrame({ '股票A': np.random.randn(n_days) * 0.02 + 0.001, # 高收益高波动 '股票B': np.random.randn(n_days) * 0.015 + 0.0008, # 中等 '股票C': np.random.randn(n_days) * 0.01 + 0.0005, # 低收益低波动 '股票D': np.random.randn(n_days) * 0.018 + 0.0007, # 中等 '股票E': np.random.randn(n_days) * 0.012 + 0.0006 # 稳健 }) # 计算最大夏普比率组合 result = max_sharpe_portfolio(returns_data, risk_free_rate=0.03) print("=" * 50) print("最优权重分配:") print("=" * 50) for stock, weight in result['weights'].items(): print(f"{stock}: {weight:.2%}") print("\n" + "=" * 50) print("组合指标:") print("=" * 50) print(f"预期年化收益率: {result['annual_return']:.2%}") print(f"年化波动率: {result['annual_volatility']:.2%}") print(f"夏普比率: {result['sharpe_ratio']:.2f}") ``` ### 输出示例 ``` 最优权重分配: 股票A: 35.2% 股票B: 22.8% 股票C: 12.1% 股票D: 18.4% 股票E: 11.5% 组合指标: 预期年化收益率: 15.8% 年化波动率: 18.2% 夏普比率: 0.70 ``` --- ## 与其他方法的对比 ### 1. 等权重组合 ```python def equal_weight(returns): """等权重""" n = len(returns.columns) return pd.Series(1/n, index=returns.columns) ``` **优点**:简单 **缺点**:不考虑风险差异 ### 2. 最小方差组合 ```python def min_variance_portfolio(returns): """最小方差组合""" cov_matrix = returns.cov() * 252 n = len(returns.columns) def portfolio_variance(weights): return np.dot(weights.T, np.dot(cov_matrix, weights)) constraints = {'type': 'eq', 'fun': lambda x: np.sum(x) - 1} bounds = tuple((0, 1) for _ in range(n)) init_weights = np.array([1/n] * n) result = minimize(portfolio_variance, init_weights, method='SLSQP', bounds=bounds, constraints=constraints) return result.x ``` **优点**:风险最小 **缺点**:可能收益很低 ### 3. 风险平价 ```python def risk_parity_portfolio(returns): """风险平价组合""" cov_matrix = returns.cov() * 252 n = len(returns.columns) def risk_contribution(weights): portfolio_vol = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) marginal_contrib = np.dot(cov_matrix, weights) risk_contrib = weights * marginal_contrib / portfolio_vol # 目标:各资产风险贡献相等 target_risk = portfolio_vol / n return np.sum((risk_contrib - target_risk) ** 2) # 优化... ``` **优点**:风险均衡 **缺点**:可能不是最优 ### 对比表 | 方法 | 目标 | 适用场景 | |------|------|----------| | **最大夏普** | 最大化风险调整收益 | 追求最优效率 | | 等权重 | 简单分散 | 新手入门 | | 最小方差 | 风险最小 | 极度保守 | | 风险平价 | 风险均衡 | 多资产配置 | --- ## 关键要点 ### 1. 为什么选择最大夏普比率? ``` ✅ 同时考虑收益和风险 ✅ 找到最优的风险收益比 ✅ 理论上是最有效的组合(在均值-方差框架下) ``` ### 2. 注意事项 ``` ⚠️ 依赖历史数据估计(可能不准确) ⚠️ 假设正态分布(实际可能有肥尾) ⚠️ 对输入参数敏感 ⚠️ 需要定期重新优化 ``` ### 3. 实用技巧 ```python # 1. 使用收缩估计减少协方差矩阵噪声 from sklearn.covariance import LedoitWolf def shrinkage_cov(returns): lw = LedoitWolf() lw.fit(returns) return lw.covariance_ # 2. 添加约束(如单资产最大权重) constraints = [ {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, {'type': 'ineq', 'fun': lambda x: 0.3 - x} # 单资产最大30% ] # 3. 滚动优化(定期更新) def rolling_optimization(returns, window=252): weights_list = [] for i in range(window, len(returns)): window_returns = returns.iloc[i-window:i] weights = max_sharpe_portfolio(window_returns) weights_list.append(weights) return weights_list ``` --- ## 总结 **最大夏普比率组合**的核心思想是: > 在给定的风险水平下,获得最大超额收益;或者在给定的收益目标下,承担最小风险。 它是投资组合理论中的重要工具,但需要结合实际情况灵活运用! --- **延伸阅读**: - 《投资学》- Bodie, Kane, Marcus - Markowitz (1952) "Portfolio Selection" - Sharpe (1966) "Mutual Fund Performance"