历史文档

【历史文档】策略-BigQuant AI策略详解

由ypyu创建,最终由small_q 被浏览 1120 用户

更新

本文内容对应旧版平台与旧版资源,其内容不再适合最新版平台,请查看新版平台的使用说明

新版量化开发IDE(AIStudio):

https://bigquant.com/wiki/doc/aistudio-aiide-NzAjgKapzW

新版模版策略:

https://bigquant.com/wiki/doc/demos-ecdRvuM1TU

新版数据平台:

https://bigquant.com/data/home

https://bigquant.com/wiki/doc/dai-PLSbc1SbZX

新版表达式算子:

https://bigquant.com/wiki/doc/dai-sql-Rceb2JQBdS

新版因子平台:

https://bigquant.com/wiki/doc/bigalpha-EOVmVtJMS5

\

导语

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

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

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

{w:100}{w:100}

基础配置

这些配置将在后续用到:


  1. start_date 和 end_date 确定了我们要用数据段 其中 [start_date, split_date) 区间的数据,用于模型训练 [split_date, end_date] 区间的数据,用户模型回测
  2. instruments:股票池,D.instruments(start_date, split_date) 取A股给定时间段内所有出现过的股票。
  3. label_expr,用户标注的函数,更多说明见下面关于 M.advanced_auto_labeler的介绍。
  4. hold_days:持仓时间,用于数据标注和回测,具体见下面相关模块使用
  5. features:特征 (因子),具体见下面相关模块使用

class conf:
    start_date = '2014-01-01'
    end_date='2017-07-17'
    split_date = '2015-01-01'
    instruments = D.instruments(start_date, end_date)
    hold_days = 5
    features = [
        'close_5/close_0',  # 5日收益
        'close_10/close_0',  # 10日收益
        'close_20/close_0',  # 20日收益
        'avg_amount_0/avg_amount_5',  # 当日/5日平均交易额
        'avg_amount_5/avg_amount_20',  # 5日/20日平均交易额
        'rank_avg_amount_0/rank_avg_amount_5',  # 当日/5日平均交易额排名
        'rank_avg_amount_5/rank_avg_amount_10',  # 5日/10日平均交易额排名
        'rank_return_0',  # 当日收益
        'rank_return_5',  # 5日收益
        'rank_return_10',  # 10日收益
        'rank_return_0/rank_return_5',  # 当日/5日收益排名
        'rank_return_5/rank_return_10',  # 5日/10日收益排名
        'pe_ttm_0',  # 市盈率TTM
    ]
    # 数据标注
    label_expr = [
    # 计算未来一段时间(hold_days)的相对收益
    '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)'
    ]

示例解读:


  1. shift(close, -5) / shift(open, -1) - shift(benchmark_close, -5) / shift(benchmark_open, -1):未来5天的相对收益率(股票收益率减去基准收益率),其中shift(close,-5)为未来5天的收盘价,shift(open,-1)为明天的开盘价,基准同理。
  2. clip:clip用于极值处理,上面的例子就是将1%分位数和99%分位数以外的数据进行裁剪
  3. all_wbins:对连续性的标注数据进行离散化,上面的例子是将标注数据分为20类。详情请参考:表达式引擎
  4. where(shift(high, -1) == shift(low, -1), NaN, label):过滤掉一字涨停的情形

数据标注

之前采取的是 M.fast_auto_labeler 进行数据标注,但如果要使用表达式引擎构建因子、数据标注,建议使用功能更为强大的M.advanced_auto_labeler进行数据标注。

# 给数据做标注:给每一行数据(样本)打分,一般分数越高表示越好
m1 = M.advanced_auto_labeler.v1(
                               instruments=conf.instruments, start_date=conf.start_date, end_date=conf.split_date,
                               label_expr=conf.label_expr, benchmark='000300.SHA', cast_label_int=True)

示例解读:


  1. label_expr:表示通过conf类中的标注语句进行数据标注
  2. benchmark:对数据进行标注的时候,偶尔会用到基准数据,因此需要制定基准
  3. cast_label_int:标注结果是否转换为整数;默认值是True

\

基础特征抽取

机器学习算法很大程度上依赖于特征工程,AI策略同样如此,特征抽取地好,对收益率的预测将更加准确。 有些因子的基础因子,直接可以抽取。

m2 = M.general_feature_extractor.v5(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.end_date,
    features=conf.features)

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

\

衍生特征抽取

很多AI策略的特征并不是简单的基础特征,而是由基础特征衍生计算出来的衍生特征。

# 计算衍生特征
m2_1 = M.derived_feature_extractor.v1(data=m2.data, features=conf.features)

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

\

数据转换

如果你采用的模型是StockRanker,该算法需要对输入的特征作相应转换。如果你使用的是随机森林、线性SGD模型等,这一步可以省略。

m3 = M.transform.v2(data=m2_1.data, transforms=None, drop_null=True)

当然,在之前我们的AI策略是采取的 M.fast_auto_labeler进行数据标注,详解请点击展开。

基础配置

这些配置将在后续用到:


  1. start_date 和 end_date 确定了我们要用数据段 其中 [start_date, split_date) 区间的数据,用于模型训练 [split_date, end_date] 区间的数据,用户模型回测
  2. instruments:股票池,D.instruments(start_date, split_date) 取A股给定时间段内所有出现过的股票。
  3. label_expr,用户标注的函数,更多说明见下面关于 M.fast_auto_labeler的介绍。
  4. hold_days:持仓时间,用于数据标注和回测,具体见下面相关模块使用
  5. features:特征 (因子),具体见下面相关模块使用


class conf:
    start_date = '2010-01-01'
    end_date='2017-01-01'
    # split_date 之前的数据用于训练,之后的数据用作效果评估
    split_date = '2015-01-01'
    # D.instruments: https://bigquant.com/docs/data_instruments.html
    instruments = D.instruments(start_date, split_date)

    # 机器学习目标标注函数
    # 如下标注函数等价于 min(max((持有期间的收益 * 100), -20), 20) + 20 (后面的M.fast_auto_labeler会做取整操作)
    # 说明:max/min这里将标注分数限定在区间[-20, 20],+20将分数变为非负数 (StockRanker要求标注分数非负整数)
    label_expr = ['return * 100', 'where(label > {0}, {0}, where(label < -{0}, -{0}, label)) + {0}'.format(20)]
    # 持有天数,用于计算label_expr中的return值(收益)
    hold_days = 5

    # 特征 https://bigquant.com/docs/#/datasource?id=%E5%9B%A0%E5%AD%90%E5%BA%93,你可以通过表达式构造任何特征
    features = [
        'close_5/close_0',  # 5日收益
        'close_10/close_0',  # 10日收益
        'close_20/close_0',  # 20日收益
        'avg_amount_0/avg_amount_5',  # 当日/5日平均交易额
        'avg_amount_5/avg_amount_20',  # 5日/20日平均交易额
        'rank_avg_amount_0/rank_avg_amount_5',  # 当日/5日平均交易额排名
        'rank_avg_amount_5/rank_avg_amount_10',  # 5日/10日平均交易额排名
        'rank_return_0',  # 当日收益
        'rank_return_5',  # 5日收益
        'rank_return_10',  # 10日收益
        'rank_return_0/rank_return_5',  # 当日/5日收益排名
        'rank_return_5/rank_return_10',  # 5日/10日收益排名
        'pe_ttm_0',  # 市盈率TTM
    ]

数据标注

为了使用有监督的机器学习算法,我们需要对数据做标注。M.fast_auto_labeler 是一个自动标注模块,具体使用说明见文档

# 给数据做标注:给每一行数据(样本)打分,一般分数越高表示越好
m1 = M.fast_auto_labeler.v8(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.split_date,
    label_expr=conf.label_expr, hold_days=conf.hold_days,
    benchmark='000300.SHA', sell_at='open', buy_at='open')

示例解读:


  1. return * 100:表示将收益 * 100,比如某只股票,今天的收盘价是10元,5天后的收盘价是11.32元,则return = 13.2%,return * 100 = 13.2
  2. 'where(label > {0}, {0}, where(label < -{0}, -{0}, label)) + {0}'.format(20):这个表达式,20带入之后是 where(label > 20, 20, where(label < -20, -20, label)) + 20 第一部分:where(label > 20, 20, where(label < -20, -20, label)),将数据裁剪到[-20, 20],即小于-20的用-20替换,大于20的用20替换 第二部分:+20,则将整个值的范围变换到[0, 40]

 label_expr = ['return * 100', 'where(label > {0}, {0}, where(label < -{0}, -{0}, label)) + {0}'.format(20)]

特征抽取

机器学习算法很大程度上依赖于特征工程,AI策略同样如此,特征构建地好,对收益率的预测将更加准确。

# 计算特征数据
m2 = M.general_feature_extractor.v5(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.split_date,
    features=conf.features)

示例解读:


  1. 特征抽取也可以称作因子抽取或者特征数据计算,接口的介绍参考 模块和API概览:特征抽取
  2. instruments=conf.instruments:表示计算哪些股票的特征数据。
  3. start_date=conf.start_date, end_date=conf.split_date :表示对什么时间段的股票数据计算特征。该时间段和训练集的时间段是一致的。
  4. features=conf.features:表示抽取哪些特征。


数据预处理

从上一步 特征抽取中,我们可以将特征数据抽取出来,但是计算出来的特征数据不一定满足机器学习算法的需要。StockRanker算法要求数据为正整数,因此需要对数据进行预处理。

m3 = M.transform.v2(
    data=m2.data, transforms=T.get_stock_ranker_default_transforms(),
    drop_null=True, astype='int32', except_columns=['date', 'instrument'],
    clip_lower=0, clip_upper=200000000)

示例解读:


  1. 不同的机器学习算法可能在数据预处理模块有所差异,StockRanker算法的接口的介绍参考 模块和API概览:特征转化
  2. data=m2.data:表示对什么数据进行数据预处理,一般为计算完成的特征数据。
  3. transforms=T.get_stock_ranker_default_transforms():表示进行怎样的数据预处理,具体的数据变换可以通过T.get_stock_ranker_default_transform()接口进行查询,transform是由正则表达式类型的变换函数组成的列表,对于输入数据的每一列,从transforms里依序寻找到匹配的表达式,用对应的变换函数对列数据做处理。
  4. 该接口其他的参数一般采用默认即可,详情请参考 [模块和API概览:特征转化]。(https://bigquant.com/docs/#/develop?id=数据变换)。

[/details]


\

合并数据

通过数据标注和计算特征数据,我们获得了两个数据,只有同时包含这两部分数据的训练集才能完整地训练一个AI模型,因此需要进行数据合并。

# 合并标注和特征数据
m4 = M.join.v2(data1=m1.data, data2=m3.data, on=['date', 'instrument'], sort=True)

示例解读:

  1. 数据合并也成为数据连接,详情请参考 模块和API:数据连接
  2. data1=m1.data 表示:第一个需要连接的数据,例如标注数据。
  3. data2=m3.data 表示:第二个需要连接的数据,例如计算完成的特征数据。
  4. on=['date', 'instrument'] 表示:数据合并时使用的主要列。一般使用日期和股票代码就可以对数据进行合并。
  5. sort=True 表示:是否对合并数据的结果按on指定的列进行排序。

\

模型训练

当我们将标注数据和经过数据预处理的特征数据合并以后,此时可以通过机器学习算法训练出一个AI模型。

# StockRanker机器学习训练
m5=M.stock_ranker_train.v5(training_ds=m4.data, features=conf.features)

示例解读:

  1. 机器学习模型训练是必不可少的一步,训练时间依赖于数据量,如果是全市场股票多年数据,时间大概需要3-10分钟。详情请参考 模块和API概览:模型训练
  2. training_ds=m4.data 表示:训练模型时应以什么数据进行输入,输入的数据为上一步合并的数据。
  3. features=conf.features 表示:训练模型时以什么特征或因子参与模型进行训练。
  4. M.stock_ranker_train接口的其他参数一般采用默认值。

\

训练结果

通过上一步的训练模型,我们已经产生出了一个在训练集上表现不错的模型。我们可以这样查询训练结果:

print('模型ID:', m5.model_id)
print('模型因子得分:', m5.feature_gains)
print('模型可视化:', m5.plot_model())

示例解读:

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

\

模型预测

此时,我们已经产生出了一个在训练集上表现不错的模型。现在我们根据该模型来获取在测试集上的预测结果。

# 计算基础数据
n2 = M.general_feature_extractor.v5(
    instruments=conf.instruments, start_date=conf.start_date, end_date=conf.end_date,
    features=conf.features)

# 计算衍生特征
n2_1 = M.derived_feature_extractor.v1(data=n2.data, features=conf.features)

# 将特征数据转换机器学习算法能够接受的数据类型(只有StockRanker算法需要)
n3 = M.transform.v2(data=n2_1.data, transforms=None, drop_null=True)

# 进行预测
n4 = M.stock_ranker_predict.v5(model=m6.model, data=n3.data)

# 查看预测数据
prediction = n4.predictions.read_df()

示例解读:


  1. n1和n2和之前的特征抽取、特征转换完全一样,只是现在传入的时间是测试集的时间段。
  2. 机器学习算法通过模型和特征数据就可以进行预测,因此并不需要标注数据、合并数据。比如当你获得了一个回归模型后,此时传入新的自变量就可以带入模型获得因变量。
  3. n3是模型预测,详情可参看 模块和API概览:模型预测
  4. model_id=context.options['model_id'] 表示:用哪个模型进行预测就传入哪个模型ID。
  5. data=n2.data 表示:在什么数据上进行预测就传入什么数据。一般为测试集的特征数据。
  6. n3.predictions.read_df() 表示:模型在测试集上的预测结果为n3.predictions,类型为DataSource,因此需要通过read_df方法查看。

\

策略回测

当我们获得测试集上的预测结果以后,我们就可以通过BigQuant回测机制进行策略回测,验证该策略是否有效。策略回测相关内容请参考 BigQuant回测机制


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


\

标签

量化策略
评论
  • ``` 'close_5/close_0', # 5日收益,其中close_5是5日前还是5日后呢?文档是说第前5日,但是这么算是5日收益么? ``` \
  • 你反馈的有一定道理。close*5 指的是 5天前的价格,因此 close5 / close*_0 表示的是5天前的价格除以当天的最新价。这个指标的倒数再减去1才是5日收益。但它的确并不是5日收益 另外,这里这是作为特征因子,没啥问题。本文主要介绍整个ai量化策略的思路,可以不纠结这里。
{link}