查看全集:💎Quantopia量化分析56讲
股票池(Universe)是量化策略交易的标的资产集合。就像厨师需要选择优质食材一样,量化交易者需要精心挑选股票池。常见的股票池类型包括:
(演进过程示例):
2008年金融危机期间,仅包含金融股的策略普遍失效,而全市场策略表现更好。这说明:
import yfinance as yf
import pandas as pd
# 获取多只股票数据示例
tickers = ['AAPL', 'MSFT', 'GOOG']
start_date = '2020-01-01'
end_date = '2023-01-01'
data = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
print(data.head())
# 计算日收益率
returns = data.pct_change().dropna()
print(returns.describe())
小练习:尝试添加TSLA股票数据,比较其收益率波动性
使用yfinance获取行业信息(示例):
# 获取单只股票信息
aapl = yf.Ticker("AAPL")
print(aapl.info['sector']) # 输出行业分类
# 行业分布可视化
sector_counts = pd.Series({
'Technology': 150,
'Financials': 120,
'Healthcare': 80
})
sector_counts.plot(kind='pie', autopct='%1.1f%%')
常用流动性指标计算公式:
20日移动平均流动性筛选:
def liquidity_screen(data, window=20, threshold=1e6):
volume = data['Volume']
close = data['Close']
dollar_volume = (volume * close).rolling(window).mean()
return dollar_volume > threshold
换手率计算公式:
对比实验:
# 原始股票池与平滑后对比
original_turnover = [...] # 原始换手率数据
smoothed_turnover = [...] # 使用移动平均后的数据
pd.DataFrame({
'原始': original_turnover,
'平滑': smoothed_turnover
}).plot(title='换手率对比')
def build_universe(data):
# 条件1:市值大于100亿
market_cap = data['MarketCap'] > 10e9
# 条件2:过去20日平均成交量大于100万股
volume_avg = data['Volume'].rolling(20).mean() > 1e6
# 条件3:股价高于5美元
price_condition = data['Close'] > 5
return market_cap & volume_avg & price_condition
使用3个月再平衡周期示例:
from dateutil.relativedelta import relativedelta
current_date = pd.to_datetime('2022-01-01')
rebalance_dates = [current_date + relativedelta(months=3*i) for i in range(4)]
print(rebalance_dates)
小练习:尝试修改再平衡周期为1个月,观察股票池变动频率
指标 | 阈值 | 作用 |
市值 | >5亿美元 | 排除小盘股风险 |
日均成交额 | >250万美元(200日) | 确保流动性 |
股价 | >5美元 | 降低交易摩擦成本 |
def QTradableStocksUS(data):
# 市值筛选
market_cap = data['MarketCap'] > 5e8
# 流动性筛选
dollar_volume = (data['Volume'] * data['Close']).rolling(200).median() > 2.5e6
# 价格筛选
price_filter = data['Close'] > 5
# 其他条件(示例)
primary_share = data['IsPrimary'] # 假设有是否为优先股字段
no_adr = ~data['IsADR'] # 排除美国存托凭证
return market_cap & dollar_volume & price_filter & primary_share & no_adr
错误做法:在历史数据上不断调整参数直到表现完美
正确方法:
# 使用时间序列交叉验证
from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_idx, test_idx in tscv.split(data):
train_data = data.iloc[train_idx]
test_data = data.iloc[test_idx]
# 执行回测...
解决方案:使用历史时点数据进行回测,包括已退市股票
示例数据集结构:
Date | Ticker | Price | Exists
2020-01-02 | ABC | 50.2 | True
2021-05-15 | ABC | NaN | False # 标记退市
# 练习模板代码
def tech_sector_universe():
tech_tickers = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META']
data = yf.download(tech_tickers, period='1y')
# 添加你的筛选逻辑...
return selected_stocks
(注:本教程示例代码需要配合实际市场数据使用,部分筛选条件需要根据具体数据字段调整实现)