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_timeshiftmin_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)