帖子修改1


(iQuant) #1

导语:AI策略和传统的量化策略有很大差异,本文根据策略背后代码详细讲解AI策略,了解AI策略运行机制。


作者: bigquant
阅读时间:10分钟
本文由BigQuant宽客学院推出,难度标签:☆☆☆

前面我们通过可视化策略模板或者策略生成器,可以快速开发出一个AI策略,我们来详细解读一下策略的代码。

看看下面这个简单的AI策略抽象流程示意图,将帮助我们来理解AI策略代码。

一、设置训练集起止日期

示例代码
m1 = M.instruments.v2(
    start_date='2010-01-01',
    end_date='2015-01-01',
    market='CN_STOCK_A',
    instrument_list='',
    max_count=0
)
示例解读

1、通过M.instruments.v2模块抽取2010-01-01 至 2015-01-01时间段的股票列表作为训练集数据的股票池
2、模块运行的结果会返回一个股票代码列表和训练集起止日期,并以缓存的形式存放在m1模块中,可以通过运行m1.data.read_pickle()查看

二、训练集数据标注

示例代码
m2 = M.advanced_auto_labeler.v2(
    instruments=m1.data,
    label_expr="""
# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
shift(close, -5) / shift(open, -1) - shift(benchmark_close, -5) / shift(benchmark_open, -1)

# 极值处理:用1%和99%分位的值做clip
clip(label, all_quantile(label, 0.01), all_quantile(label, 0.99))

# 将分数映射到分类,这里使用20个分类
all_wbins(label, 20)

# 过滤掉一字涨停的情况 (设置label为NaN,在后续处理和训练中会忽略NaN的label)
where(shift(high, -1) == shift(low, -1), NaN, label)
""",
    start_date='',
    end_date='',
    benchmark='000300.SHA',
    drop_na_label=True,
    cast_label_int=True
)
示例解读

M.advanced_auto_labeler.v2是高级数据标注模块,详细功能参考文档

  1. 证券代码列表模块m1的运行结果以缓存方式存放在为m1.data,在高级数据标注模块m2中作为输入传给instruments参数
  2. shift(close, -5) / shift(open, -1) - shift(benchmark_close, -5) / shift(benchmark_open, -1):未来5天的相对收益率(股票收益率减去基准收益率),其中shift(close,-5)为未来5天的收盘价,shift(open,-1)为明天的开盘价,基准同理。
  3. clip:clip用于极值处理,上面的例子就是将1%分位数和99%分位数以外的数据进行裁剪
  4. all_wbins:对连续性的标注数据进行离散化,上面的例子是将标注数据分为20类。详情请参考:表达式引擎
  5. where(shift(high, -1) == shift(low, -1), NaN, label):过滤掉一字涨停的情形
  6. benchmark=‘000300.SHA’,设置基准对应的指数为沪深300
  7. start_date和end_date 为空,表示从m1.data数据中获取标注的起止时间段,即2010-01-01 至 2015-01-01。
  8. cast_label_int:标注结果是否转换为整数;默认值是True
  9. 模块m2的运行结果为一个DataFrame,并以缓存方式存储在m2.data中,可以通过运行m2.data.read_df()查看标注后的结果。可以看到,标注结果在label列中,根据未来5天的相对收益率的高低被分类成0至19档。

三、指定特征因子列表

机器学习算法很大程度上依赖于特征工程,AI策略同样如此,特征抽取得好,对收益率的预测将更加准确。
我们通过M.input_features.v1模块指定需要抽取的因子列表:

示例代码
m3 = M.input_features.v1(
    features="""# #号开始的表示注释
# 多个特征,每行一个,可以包含基础特征和衍生特征
# 5日收益
return_5 
# 10日收益
return_10 
# 20日收益
return_20   
# 当日/5日平均交易额
avg_amount_0/avg_amount_5  
# 5日/20日平均交易额
avg_amount_5/avg_amount_20  
# 当日/5日平均交易额排名
rank_avg_amount_0/rank_avg_amount_5
# 5日/10日平均交易额排名
rank_avg_amount_5/rank_avg_amount_10
# 当日收益
rank_return_0
# 5日收益
rank_return_5
# 10日收益
rank_return_10
# 当日/5日收益排名
rank_return_0/rank_return_5
# 5日/10日收益排名
rank_return_5/rank_return_10
# 市盈率TTM
pe_ttm_0
"""
)
示例解读

1、M.input_features模块支持使用表达式引擎构造因子表达式,例如avg_amount_0/avg_amount_5这个因子,是由两个基础因子avg_amount_0和avg_amount_5通过计算合成的衍生因子表达式。
详情请参考:表达式引擎
2、每个因子特征单独放在一行,使用#号作为标注标识,标注单独放在一行
3、模块运行的结果是一个特征因子表达式列表,并以并以缓存方式存储在m3.data中,可以通过运行m3.data.read_pickle()查看这个特征因子列表。

四、获取训练集基础因子数据

我们通过M.input_features.v7模块抽取训练集起止时间范围内指定股票的基础因子数据

示例代码
m4 = M.general_feature_extractor.v7(
    instruments=m1.data,
    features=m3.data,
    start_date='',
    end_date='',
    before_start_days=0
)

示例解读

1、传入证券代码列表的缓存结果m1.data给instruments参数,同时传入特征因子表达式列表的缓存结果m3.data给features参数
2、M.general_feature_extractor.v7模块会从数据库中抽取instruments指定的时间范围股票池的rank_return_0、avg_amount_5等基础因子数据
3、模块运行结果为DataFrame,并以并以缓存方式存储在m4.data中,可以通过运行m4.data.read_df()查看训练集基础因子数据DataFrame。

详情请参考文档:基础特征抽取

五、获取训练集衍生因子数据

很多AI策略的特征并不仅包括简单的基础特征,还包含由基础特征衍生计算出来的衍生特征,例如本例中的avg_amount_5/avg_amount_20 等特征。
这些复杂表达式是通过基础因子的数学运算计算得到的,我们通过M.derived_feature_extractor.v3模块进行表达式计算获取训练集衍生特征因子数据。

示例代码
m5 = M.derived_feature_extractor.v3(
    input_data=m4.data,
    features=m3.data,
    date_col='date',
    instrument_col='instrument',
    drop_na=False,
    remove_extra_columns=False
)
示例解读

1、传入基础特征数据的缓存结果m4.data,同时传入特征因子表达式列表的缓存结果m3.data给features参数
2、模块解析表达式列表中的衍生因子表达式并利用基础特征数据进行表达式计算,得到的衍生因子数据列追加到基础特征数据DataFrame中,并以缓存方式存储在m5.data中,
可以通过运行m5.data.read_df()查看训练集衍生因子数据+基础因子数据的DataFrame。

详情请参考文档:衍生特征抽取

六、连接训练集特征与标注

将训练集特征数据与标注数据,通过M.join.v3模块连接在一起

示例代码
m6 = M.join.v3(
    data1=m2.data,
    data2=m5.data,
    on='date,instrument',
    how='inner',
    sort=False
)
示例解读

1、传入标注数据的缓存结果m2.data和衍生特征数据的缓存结果m5.data
2、模块运行后合并个的DataFrame,并以缓存方式存储在m6.data中,可以通过运行m6.data.read_df()查看这个DataFrame。
3. on=[‘date’, ‘instrument’] 表示:数据合并时使用的主要列。一般使用日期和股票代码就可以对数据进行合并。
4. sort=True 表示:是否对合并数据的结果按on指定的列进行排序。

详情请参考 模块和API:数据连接

七、训练集数据缺失值处理

通过 M.dropnan.v1 模块将合并后的DataFrame中含有缺失值Nan的行去除。

示例代码
m7 = M.dropnan.v1(
    input_data=m6.data
)
示例解读

1、input_data=m6.data: 传入合并后的数据结果缓存m6.data
2、模块运行后将m6结果中含有Nan值的行去除,并以缓存方式存储在m7.data中,可以通过运行m7.data.read_df()查看DataFrame结果。

详情请参考 模块和API:缺失值处理

八、模型训练

当我们将训练集数据清洗后,可以通过机器学习算法训练出一个AI模型。

示例代码
# StockRanker机器学习训练
m8 = M.stock_ranker_train.v5(
    training_ds=m7.data,
    features=m3.data,
    learning_algorithm='排序',
    number_of_leaves=30,
    minimum_docs_per_leaf=1000,
    number_of_trees=20,
    learning_rate=0.1,
    max_bins=1023,
    feature_fraction=1,
    m_lazy_run=False
)
示例解读
  1. 机器学习模型训练是必不可少的一步,训练时间依赖于数据量,如果是全市场股票多年数据,时间大概需要3-10分钟。
  2. training_ds=m7.data 表示:训练模型时应以什么数据进行输入,输入的数据为上一步缺失值处理后的数据。
  3. features=m3.data 表示训练模型时,哪些特征或因子参与模型进行训练,这里使用m3模块特征列表中的特征训练模型。

模块运行后会生成一个训练模型,并以缓存形式存放在m7中,我们可以

查询训练结果
print('模型ID:', m8.model_id)
print('模型因子得分:', m8.feature_gains.read_df())
print('模型可视化:', m8.plot_model())
示例解读
  1. m8.model_id 表示:唯一的模型ID。
  2. m8.feature_gains 表示: 各个特征的得分情况,可以借此判断特征重要性程度。由于输出类型为DataSource,因此可以通过read_df方法查看——m5.feature_gains.read_df()。
  3. m8.plot_model() 表示:可视化查看模型结果,这样就能打开AI算法的‘黑箱’,可以查看StockRanker模型的每个决策分支细节。

详情请参考 M.stock_ranker_train接口的其他参数一般采用默认值。
模型训练也可以选择其他的机器学习模型,详情请参考 模块和API概览:模型训练

九、设置验证集起止日期

与训练集因子数据的抽取过程类似,验证集也是通过M.instruments.v2模块指定起止时间。需要注意的是验证集的起始时间应该在训练集的结束时间之后,以避免验证集与训练集数据交叉重叠而引入未来函数

示例代码
m9 = M.instruments.v2(
    start_date='2015-01-01',
    end_date='2018-01-01',
    market='CN_STOCK_A',
    instrument_list='',
    max_count=0
)

十、获取验证集基础因子数据

我们通过M.input_features.v7模块抽取特征因子列表中基础因子数据,这里使用的特征因子列表应保持与训练集一致为m3.data。

示例代码
m10 = M.general_feature_extractor.v7(
    instruments=m9.data,
    features=m3.data,
    start_date='',
    end_date='',
    before_start_days=0
)
示例解读

1、instruments=m9.data,传入验证集证券代码列表的缓存结果m9.data
2、features=m3.data,传入特征因子表达式列表的缓存结果m3.data
3、模块运行结果为DataFrame,并以并以缓存方式存储在m4.data中,可以通过运行m10.data.read_df()查看验证集基础因子数据的DataFrame。

十一、获取验证集衍生因子数据

我们通过M.input_features.v7模块抽取特征因子列表中基础因子数据,这里使用的特征因子列表应保持与训练集一致,即m3模块的数据结果。

示例代码
m11 = M.derived_feature_extractor.v3(
    input_data=m10.data,
    features=m3.data,
    date_col='date',
    instrument_col='instrument',
    drop_na=False,
    remove_extra_columns=False
)
示例解读

1、传入验证集基础特征数据的缓存结果m10.data,同时传入特征因子表达式列表的缓存结果m3.data给features参数
2、模块解析表达式列表中的衍生因子表达式并利用基础特征数据进行表达式计算,得到的衍生因子数据列追加到基础特征数据DataFrame中,并以缓存方式存储在m11.data中,
可以通过运行m11.data.read_df()查看训练集衍生因子数据+基础因子数据的DataFrame。

十二、验证集数据缺失值处理

通过 M.dropnan.v1 模块将合并后的DataFrame中含有缺失值Nan的行去除。

示例代码
m12 = M.dropnan.v1(
    input_data=m11.data
)
示例解读

1、input_data=m11.data: 传入验证集因子数据结果缓存m11.data
2、模块运行后将m6结果中含有Nan值的行去除,并以缓存方式存储在m12.data中,可以通过运行m12.data.read_df()查看DataFrame结果。

十三、模型预测

现在我们通过M.stock_ranker_predict.v5 根据训练好的模型来获取测试集因子数据的预测结果。

示例代码
m13 = M.stock_ranker_predict.v5(
    model=m8.model,
    data=m12.data,
    m_lazy_run=False
)
示例解读

1、model=m8.model,指定使用m8模块中训练的模型进行预测
2、data=m12.data, 指定使用验证集清洗后的因子数据m12.data进行预测。

查看预测数据

示例代码
prediction = m13.predictions.read_df()
示例解读

模型在测试集上的预测结果为n3.predictions,类型为DataSource,因此需要通过read_df方法查看。

详情可参看 模块和API概览:模型预测

十四、策略回测

当我们获得测试集上的预测结果以后,我们就可以通过预测结果构建交易策略。
例如下面几种策略构建方式:

典型策略构建方式

1、针对排序模型,例如使用StockRanker预测每只股票每天的未来5日涨幅排序,可以比对当日持仓,卖出排名预测值靠后的,同时买入排名预测值靠前的股票。

2、针对分类模型,例如使用随机森林分类模型预测每天每只股票未来涨/跌状态,我们可以买入每天预测分类为"涨"的股票,并卖出已有持仓中预测分类为"跌"的股票。

3、针对回归模型,例如使用多层感知器回归模型预测每天每只股票未来5日涨幅,可以定期轮仓卖出已有持仓,买入未来5日涨幅预测值最高的前几只股票。

综上所述,利用AI算法的预测值构建策略有很多种方式,大家还可以通过多模型预测值组合进行策略构建。

通过回测引擎模块计算收益曲线,我们可以验证该策略在测试集上是否有效。

BigQuant策略回测机制相关内容请参考 BigQuant回测机制


小结:AI策略其实主要包含训练和预测,然后基于预测的结果开发交易策略来进行验证。本文因为涉及到机器学习算法为监督式学习算法,因此有数据标注这一步。希望通过本文介绍,大家能有更加深入的认识。