策略概述#
130/30 策略持有 130% 多头仓位和 30% 空头仓位:净敞口为 100%,总敞口为 160%。它仍是净多头策略,并不天然实现市场中性;空头仓位用于表达负面观点,组合还需要另行约束 Beta、行业和其他因子暴露。本教程使用四类价值指标演示评分流程。
核心价值因子解析#
股息率(Dividend Yield)#
-
公式:股息率 = 年度股息总额 / 当前股价
-
意义:高股息率表明公司用更多利润回馈股东,常用于识别价值股
-
yFinance实现(示例):
import yfinance as yf
stock = yf.Ticker("AAPL")
div_yield = stock.info.get('trailingAnnualDividendYield', 0)市净率(Price-to-Book Ratio)#
-
公式:市净率 = 股价 / 每股净资产
-
意义:低市净率可能预示股票被低估
-
注意:需对原始值取负,使低值在计算中呈现高吸引力
pb_ratio = -stock.info.get('priceToBook', 0) # 取负实现价值反转市销率(Price-to-Sales Ratio)#
-
公式:市销率 = 股价 / 每股销售收入
-
处理:使用TTM(过去12个月)数据平滑季节性波动
ps_ratio = -stock.info.get('priceToSalesTrailing12Months', 0)市现率(Price-to-Cash Flow)#
-
公式:市现率 = 股价 / 每股现金流
-
逻辑:在同一口径下,较低的市现率通常对应较高的价值评分
market_cap = stock.info.get('marketCap')
operating_cashflow = stock.info.get('operatingCashflow')
pcf_ratio = (
-(market_cap / operating_cashflow)
if market_cap and operating_cashflow and operating_cashflow > 0
else None
)数据获取与处理#
使用yfinance获取多只股票数据:
import pandas as pd
import numpy as np
tickers = ['AAPL', 'MSFT', 'GOOGL']
factor_data = []
for ticker in tickers:
stock = yf.Ticker(ticker)
info = stock.info
factor_data.append({
'Ticker': ticker,
'Dividend Yield': info.get('trailingAnnualDividendYield', 0),
'PB Ratio': -info.get('priceToBook', 0),
'PS Ratio': -info.get('priceToSalesTrailing12Months', 0),
'PCF Ratio': (
-(info['marketCap'] / info['operatingCashflow'])
if info.get('marketCap') and info.get('operatingCashflow', 0) > 0
else None
)
})
df = pd.DataFrame(factor_data).set_index('Ticker')数据标准化处理#
标准化步骤#
-
计算基准指数指标:选取市值最大的500只股票作为"虚拟标普500"
-
Z-Score标准化
其中:
-
为原始数据
-
为样本均值
-
为样本标准差
-
为标准化后的数据
该变换只保证样本的均值约为 0、标准差约为 1,并不会把原分布变成正态分布。
- 极值处理:实践中通常先按横截面分位数缩尾,再做标准化。下例只演示 z-score 截断;
[-10, 10]不是通用阈值,应按样本分布预先设定。
def standardize(series):
mu = series.mean()
sigma = series.std()
z_scores = (series - mu) / sigma
return z_scores.clip(-10, 10)
# 对各因子分别标准化
df_standardized = df.apply(standardize)综合评分与选股#
计算综合得分#
df['Composite Score'] = df_standardized.mean(axis=1)构建投资组合#
-
多头组合:选择综合得分最高的 30% 股票
-
空头组合:选择得分最低的 5% 股票
n = len(df)
n_long = max(1, int(np.ceil(n * 0.30)))
n_short = max(1, int(np.ceil(n * 0.05)))
long_candidates = df.nlargest(n_long, 'Composite Score').index.tolist()
short_candidates = df.nsmallest(n_short, 'Composite Score').index.tolist()策略回测要点#
权重分配示例#
| 组合类型 | 股票数量 | 单股权重 | 总仓位 |
|---|---|---|---|
| 多头 | 由股票池决定 | 合计 130% / 多头数量 | 130% |
| 空头 | 由股票池决定 | -30% / 空头数量 | -30% |
因此组合净敞口为 100%,总敞口为 160%。还应在回测中计算组合 Beta 和行业暴露,不能用净名义敞口替代风险中性检验。
再平衡机制#
-
每月调仓一次
-
设置10%的止损线
小练习#
-
使用yfinance获取3只金融股的市净率,比较它们的价值吸引力
-
尝试对某行业的PS Ratio进行标准化处理,找出最具吸引力的股票
-
思考:如果加入动量因子,应该如何调整现有评分体系?
# 练习1示例代码
financial_stocks = ['JPM', 'BAC', 'C']
for ticker in financial_stocks:
stock = yf.Ticker(ticker)
print(f"{ticker} P/B Ratio: {stock.info.get('priceToBook')}")关键点总结#
-
价值投资的核心是识别市场价格与内在价值的偏离
-
多因子组合能有效分散单一因子的失效风险
-
标准化处理确保不同量纲因子可比
-
130/30结构在控制风险的同时提升收益弹性
注意:实际应用中需考虑交易成本、滑点等现实约束。建议在Paper Trading环境中充分测试策略后再实盘操作。
Capstone 交付要求#
将本案例扩展为一份可复核的研究包,而不只是运行示例代码:
-
一页研究备忘录:经济假设、预期收益来源、可证伪条件与目标使用场景
-
point-in-time 数据字典:字段来源、发布日期、修订处理、退市证券与股票池重建规则
-
可复现实验:固定代码/数据版本,分离训练、验证和最终留出集,登记全部参数与因子试验
-
组合结果:行业和风格暴露、换手、容量、借券与成本后收益,并与简单基准比较
-
风险结论:主要失效区间、压力测试、上线门槛与停止交易规则
完成后请让另一位研究员仅依据交付包复现主要表格;无法复现或仍存在时点泄漏时,不应通过结业评审。