tsfresh 笔记
数据准备
准备符合 tsfresh 输入格式的数据集。
tsfresh 是对序列数据提取特征,输入一个时间序列数据就会转换为一个数值,例如输入一段时间的股价序列,那么可以转化成最大值、最小值、平均值、中位数、波峰数这样的标量数值。
tsfresh 是不允许有空值的,所以在衍生特征列时,需要提前保证无空值。可以使用
fillna(0)
和dropna()
两种方式进行调整。
样本抽样
以步长 s 为间隔的滚动抽样。
量化需要的是每个交易日都要有一个样本,需要用到 tsfresh 的滚动 (roll) 技术了,也就是使用 roll_time_series()
方法进行滚动处理。
from tsfresh.utilities.dataframe_functions import roll_time_series
data_roll = roll_time_series(data, column_id='code', column_sort='date', max_timeshift=20, min_timeshift=5).drop(columns=['code'])
在这个变换中,新生成了一个 id 列,数值是一个元组 (证券代码, 日期)
,每个 id 列是记录哪些日期生成对应的因子,而使用用多长的序列数据,由参数 max_timeshift
和 min_timeshift
决定。
max_timeshift=n
- 表示每个交易日最多使用包含当日在内的 n+1 个数据点序列
min_timeshift=m
- 表示每个交易日至少使用包含当日在内的 m+1 个数据点序列
可以使用正面的方法查看对应的时间范围。
gg = data_roll.groupby('id').agg({'date':['count', min, max]})
看到这里应该就明白了,数据长度在 min_timeshift+1 ~ max_timeshift+1
之间时,有多少数据用多少数据,当超出这个范围后,就每个交易日滚动 (roll) 使用 max_timeshift+1
个数据点的序列数据,因此原始因子数量不变,但行数被扩展为 9 万多行,因为部分数据被重复滚动使用。
特征生成
对采样样本生成特征,并收集所有的特征信息。
在 data_roll 之上,就可以使用 tsfresh 的 extract_features()
函数在基础因子之上衍生出众多因子,这一步较为耗时,不同电脑配置执行时间不一样,须耐心等待。
from tsfresh import extract_features
data_feat = extract_features(data_roll, column_id='id', column_sort='date')
# 对单独标的而言,将日期作为index
data_feat.index = [v[1] for v in data_feat.index]
因子生成的原理是,tsfresh 预置了 783 个算子 (calculator) ,会逐个用在每一个交易日的基础因子数值序列上,生成出 783 个形态各异的特征值,相同计算公式不同单参数也算 1 个。
新生成的特征因子里都是衍生出来的因子,是不包含原始的基础因子的,记得也把基础因子添加回去。然后给每个交易日的数据打上标签,每个样本标签对应的是第二个交易日的涨跌情况,计算出每个样本第二天的涨幅(pct),如果第二天上涨,则设置标签(rise)为 1 ,反之为 0 。
efftract_features()
内置的 default_fc_parameters
可以配置不同的特征生成策略:
- ComprehensiveFCParameters
- 包括所有没有参数的特征和所有有参数的特征,每个特征都有不同的组合。默认值。
- MinimalFCParameters
- 仅包含少数功能,可用于快速测试。
- EfficientFCParameters
- 与 ComprehensiveFCParameters 中的大部分功能相同,但没有
high_comp_cost
。若使用此方案,则可以提高性能表现。可以设置
n_jobs=n
来设置同时运行的线程数。
具体的使用方法如下:
from tsfresh.feature_extraction import ComprehensiveFCParameters
from tsfresh.feature_extraction import extract_features
settings = ComprehensiveFCParameters()
extract_features(df, default_fc_parameters=settings)
特征选择
将收集的多个特征下的衍生特征进行选择,筛选出相关的特征值。
select_features()
方法是调用 calculate_relevance_table()
计算特征矩阵 X 中包含特征相对于目标向量 y 的相关性表—— 由 p 值决定,越低意味着越重要。
这里使用的是 Benjamini Hochberg procedure 方法进行验证,其中设置 FDR 默认为 0.05 。
- fdr_level (float)
- 设置不相关特征的理论预期百分比。默认为 5% 。
所以为了进一步减少生成特征的量,可以基于 p 值获取前排的特征作为衍生特征集:
relevance_table = calculate_relevance_table(trn_data_x, trn_data_y, n_jobs=5)
# 选了前59个top p值小的特征
select_feats = relevance_table[relevance_table.relevant].sort_values('p_value', ascending=True).iloc[:59]['feature'].values
kind_to_fc_parameters=tsfresh.feature_extraction.settings.from_columns(trn_x_selected[select_feats]) # 抽取选择后的特征配置
np.save('../kind_to_fc_parameters.npy', kind_to_fc_parameters)
部署时,可以使用刚刚生成的特征集进行处理:
# 获取预准备好的特征生成配置
saved_kind_to_fc_parameters = np.load('./kind_to_fc_parameters.npy', allow_pickle='TRUE').item()
extracted_features = extract_features(sample_data_x, column_id="code", column_sort="time", disable_progressbar=False, kind_to_fc_parameters=saved_kind_to_fc_parameters, n_jobs=5)