版本 v1.0
### 深度学习策略的交易规则
### 策略构建步骤
### 策略的实现
在画布左侧模块列表中依次拖入输入层模块、Reshape层模块、Conv2D层模块、Reshape层模块、LSTM层模块、Dropout层模块和全连接层模块(两组),构成深度学习网络构架,
最后通过“构建(深度学习)”模块组装各层。这里需要注意:
输入层的shape参数是 窗口滚动数据集的大小 X 因子数量 , 本例为 50 行 X 5个因子
ReShape层的参数是 窗口滚动数据集的大小 X 因子数量 X 1 ,本例为 50 行 X 5个因子 X1
Conv2D层中的 kernel_size参数是滑动窗口的尺寸,本例中使用 3行 X 5列 的窗口, 每次滑动的步长为 1行 X 1列 , 卷积核数目为32,这里的窗口设置决定了后面ReShape层的参数
ReShape层中的target_shape 参数,这是由 窗口滚动数据集 X 因子数量 和 Conv2D层中设置的窗口尺寸以及步长决定的。本例中 50行 X 5因子 的输入数据,使用 3行 X5列 的窗口滑动取数据,
每次移动1行,共计可以得到48次数据(即可以通过滑动3行 X 5列的窗口48次来获取完整的数据),因此target_shape= 48 X 卷积核数32
LSTM层的输出空间维度设置为卷积核数32,并设置激活函数
Dropout层是防止过度拟合采用的主动裁剪数据技术,这里设置rate 为0.8
全连接层共两层,第一层的输出空间维度与LSTM的输出维度保持一致为32,第二层将第一层的32维数据转变为1维数据输出,即获取预测的label值,此例为0到1之间的连续值,可以认为是上涨的概率。
如果当日预测的上涨概率大于0.5,则保持持仓或买入
如果当日预测的上涨概率小于0.5,则卖出股票或保持空仓。
通过 trade 模块中的初始化函数定义交易手续费和滑点,通过 context.prediction 获取每日的上涨概率预测结果;
通过 trade 模块中的主函数(handle函数)查看每日的买卖交易信号,按照买卖原则执行相应的买入/卖出操作。
可视化策略实现如下:
# 本代码由可视化策略环境自动生成 2019年10月12日 09:40
# 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
# Python 代码入口函数,input_1/2/3 对应三个输入端,data_1/2/3 对应三个输出端
def m2_run_bigquant_run(input_1, input_2, input_3):
test_data = input_2.read_pickle()
pred_label = input_1.read_pickle()
pred_result = pred_label.reshape(pred_label.shape[0])
dt = input_3.read_df()['date'][-1*len(pred_result):]
pred_df = pd.Series(pred_result, index=dt)
ds = DataSource.write_df(pred_df)
return Outputs(data_1=ds)
# 后处理函数,可选。输入是主函数的输出,可以在这里对数据做处理,或者返回更友好的outputs数据格式。此函数输出不会被缓存。
def m2_post_run_bigquant_run(outputs):
return outputs
# 回测引擎:初始化函数,只执行一次
def m1_initialize_bigquant_run(context):
# 加载预测数据
context.prediction = context.options['data'].read_df()
# 系统已经设置了默认的交易手续费和滑点,要修改手续费可使用如下函数
context.set_commission(PerOrder(buy_cost=0.0003, sell_cost=0.0013, min_cost=5))
# 回测引擎:每日数据处理函数,每天执行一次
def m1_handle_data_bigquant_run(context, data):
# 按日期过滤得到今日的预测数据
try:
prediction = context.prediction[data.current_dt.strftime('%Y-%m-%d')]
except KeyError as e:
return
instrument = context.instruments[0]
sid = context.symbol(instrument)
cur_position = context.portfolio.positions[sid].amount
# 交易逻辑
if prediction > 0.5 and cur_position == 0:
context.order_target_percent(context.symbol(instrument), 1)
print(data.current_dt, '买入!')
elif prediction < 0.5 and cur_position > 0:
context.order_target_percent(context.symbol(instrument), 0)
print(data.current_dt, '卖出!')
# 回测引擎:准备数据,只执行一次
def m1_prepare_bigquant_run(context):
pass
# 回测引擎:每个单位时间开始前调用一次,即每日开盘前调用一次。
def m1_before_trading_start_bigquant_run(context, data):
pass
m3 = M.dl_layer_input.v1(
shape='50,5',
batch_shape='',
dtype='float32',
sparse=False,
name=''
)
m13 = M.dl_layer_reshape.v1(
inputs=m3.data,
target_shape='50,5,1',
name=''
)
m14 = M.dl_layer_conv2d.v1(
inputs=m13.data,
filters=32,
kernel_size='3,5',
strides='1,1',
padding='valid',
data_format='channels_last',
dilation_rate='1,1',
activation='relu',
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='Zeros',
kernel_regularizer='None',
kernel_regularizer_l1=0,
kernel_regularizer_l2=0,
bias_regularizer='None',
bias_regularizer_l1=0,
bias_regularizer_l2=0,
activity_regularizer='None',
activity_regularizer_l1=0,
activity_regularizer_l2=0,
kernel_constraint='None',
bias_constraint='None',
name=''
)
m15 = M.dl_layer_reshape.v1(
inputs=m14.data,
target_shape='48,32',
name=''
)
m4 = M.dl_layer_lstm.v1(
inputs=m15.data,
units=32,
activation='tanh',
recurrent_activation='hard_sigmoid',
use_bias=True,
kernel_initializer='glorot_uniform',
recurrent_initializer='Orthogonal',
bias_initializer='Ones',
unit_forget_bias=True,
kernel_regularizer='None',
kernel_regularizer_l1=0,
kernel_regularizer_l2=0,
recurrent_regularizer='None',
recurrent_regularizer_l1=0,
recurrent_regularizer_l2=0,
bias_regularizer='None',
bias_regularizer_l1=0,
bias_regularizer_l2=0,
activity_regularizer='None',
activity_regularizer_l1=0,
activity_regularizer_l2=0,
kernel_constraint='None',
recurrent_constraint='None',
bias_constraint='None',
dropout=0,
recurrent_dropout=0,
return_sequences=False,
implementation='0',
name=''
)
m11 = M.dl_layer_dropout.v1(
inputs=m4.data,
rate=0.8,
noise_shape='',
name=''
)
m10 = M.dl_layer_dense.v1(
inputs=m11.data,
units=32,
activation='tanh',
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='Zeros',
kernel_regularizer='None',
kernel_regularizer_l1=0,
kernel_regularizer_l2=0,
bias_regularizer='None',
bias_regularizer_l1=0,
bias_regularizer_l2=0,
activity_regularizer='None',
activity_regularizer_l1=0,
activity_regularizer_l2=0,
kernel_constraint='None',
bias_constraint='None',
name=''
)
m12 = M.dl_layer_dropout.v1(
inputs=m10.data,
rate=0.8,
noise_shape='',
name=''
)
m9 = M.dl_layer_dense.v1(
inputs=m12.data,
units=1,
activation='sigmoid',
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='Zeros',
kernel_regularizer='None',
kernel_regularizer_l1=0,
kernel_regularizer_l2=0,
bias_regularizer='None',
bias_regularizer_l1=0,
bias_regularizer_l2=0,
activity_regularizer='None',
activity_regularizer_l1=0,
activity_regularizer_l2=0,
kernel_constraint='None',
bias_constraint='None',
name=''
)
m5 = M.dl_model_init.v1(
inputs=m3.data,
outputs=m9.data
)
m8 = M.input_features.v1(
features="""(close_0/close_1-1)*10
(high_0/high_1-1)*10
(low_0/low_1-1)*10
(open_0/open_1-1)*10
(volume_0/volume_1-1)*10"""
)
m24 = M.instruments.v2(
start_date='2015-01-01',
end_date=T.live_run_param('trading_date', '2017-03-01'),
market='CN_STOCK_A',
instrument_list='600009.SHA',
max_count=0
)
m21 = M.advanced_auto_labeler.v2(
instruments=m24.data,
label_expr="""# #号开始的表示注释
# 0. 每行一个,顺序执行,从第二个开始,可以使用label字段
# 1. 可用数据字段见 https://bigquant.com/docs/develop/datasource/deprecated/history_data.html
# 添加benchmark_前缀,可使用对应的benchmark数据
# 2. 可用操作符和函数见 `表达式引擎 <https://bigquant.com/docs/develop/bigexpr/usage.html>`_
# 计算收益:5日收盘价(作为卖出价格)除以明日开盘价(作为买入价格)
where(shift(close, -10) / close -1>0,1,0)
# 过滤掉一字涨停的情况 (设置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,
user_functions={}
)
m22 = M.general_feature_extractor.v7(
instruments=m24.data,
features=m8.data,
start_date='',
end_date='',
before_start_days=90
)
m23 = M.derived_feature_extractor.v3(
input_data=m22.data,
features=m8.data,
date_col='date',
instrument_col='instrument',
drop_na=False,
remove_extra_columns=False,
user_functions={}
)
m17 = M.join.v3(
data1=m21.data,
data2=m23.data,
on='date',
how='inner',
sort=True
)
m18 = M.dropnan.v1(
input_data=m17.data
)
m25 = M.dl_convert_to_bin.v2(
input_data=m18.data,
features=m8.data,
window_size=50,
feature_clip=5,
flatten=False,
window_along_col=''
)
m6 = M.dl_model_train.v1(
input_model=m5.data,
training_data=m25.data,
optimizer='Adam',
loss='binary_crossentropy',
metrics='accuracy',
batch_size=2048,
epochs=10,
n_gpus=1,
verbose='1:输出进度条记录'
)
m28 = M.instruments.v2(
start_date='2017-03-01',
end_date='2019-01-01',
market='CN_STOCK_A',
instrument_list='600009.SHA',
max_count=0
)
m16 = M.general_feature_extractor.v7(
instruments=m28.data,
features=m8.data,
start_date='',
end_date='',
before_start_days=90
)
m26 = M.derived_feature_extractor.v3(
input_data=m16.data,
features=m8.data,
date_col='date',
instrument_col='instrument',
drop_na=False,
remove_extra_columns=False,
user_functions={}
)
m20 = M.dropnan.v1(
input_data=m26.data
)
m27 = M.dl_convert_to_bin.v2(
input_data=m20.data,
features=m8.data,
window_size=50,
feature_clip=5,
flatten=False,
window_along_col=''
)
m7 = M.dl_model_predict.v1(
trained_model=m6.data,
input_data=m27.data,
batch_size=10240,
n_gpus=0,
verbose='2:每个epoch输出一行记录'
)
m2 = M.cached.v3(
input_1=m7.data,
input_2=m27.data,
input_3=m20.data,
run=m2_run_bigquant_run,
post_run=m2_post_run_bigquant_run,
input_ports='',
params='{}',
output_ports=''
)
m1 = M.trade.v4(
instruments=m28.data,
options_data=m2.data_1,
start_date='',
end_date='',
initialize=m1_initialize_bigquant_run,
handle_data=m1_handle_data_bigquant_run,
prepare=m1_prepare_bigquant_run,
before_trading_start=m1_before_trading_start_bigquant_run,
volume_limit=0.025,
order_price_field_buy='open',
order_price_field_sell='close',
capital_base=1000000,
auto_cancel_non_tradable_orders=True,
data_frequency='daily',
price_type='真实价格',
product_type='股票',
plot_charts=True,
backtest_only=False,
benchmark=''
)
[2019-10-12 09:24:07.108028] INFO: bigquant: cached.v3 开始运行..
[2019-10-12 09:24:07.155895] INFO: bigquant: 命中缓存
[2019-10-12 09:24:07.158261] INFO: bigquant: cached.v3 运行完成[0.050269s].
[2019-10-12 09:24:07.203340] INFO: bigquant: input_features.v1 开始运行..
[2019-10-12 09:24:07.258154] INFO: bigquant: 命中缓存
[2019-10-12 09:24:07.260520] INFO: bigquant: input_features.v1 运行完成[0.057193s].
[2019-10-12 09:24:07.274096] INFO: bigquant: instruments.v2 开始运行..
[2019-10-12 09:24:07.339699] INFO: bigquant: instruments.v2 运行完成[0.06559s].
[2019-10-12 09:24:07.347389] INFO: bigquant: advanced_auto_labeler.v2 开始运行..
[2019-10-12 09:24:07.576235] INFO: 自动标注(股票): 加载历史数据: 525 行
[2019-10-12 09:24:07.578543] INFO: 自动标注(股票): 开始标注 ..
[2019-10-12 09:24:07.679810] INFO: bigquant: advanced_auto_labeler.v2 运行完成[0.332399s].
[2019-10-12 09:24:07.807610] INFO: bigquant: general_feature_extractor.v7 开始运行..
[2019-10-12 09:24:07.964461] INFO: 基础特征抽取: 年份 2014, 特征行数=61
[2019-10-12 09:24:07.995513] INFO: 基础特征抽取: 年份 2015, 特征行数=244
[2019-10-12 09:24:08.025246] INFO: 基础特征抽取: 年份 2016, 特征行数=244
[2019-10-12 09:24:08.054138] INFO: 基础特征抽取: 年份 2017, 特征行数=37
[2019-10-12 09:24:08.128576] INFO: 基础特征抽取: 总行数: 586
[2019-10-12 09:24:08.131698] INFO: bigquant: general_feature_extractor.v7 运行完成[0.324101s].
[2019-10-12 09:24:08.138851] INFO: bigquant: derived_feature_extractor.v3 开始运行..
[2019-10-12 09:24:08.278492] INFO: derived_feature_extractor: 提取完成 (close_0/close_1-1)*10, 0.002s
[2019-10-12 09:24:08.282731] INFO: derived_feature_extractor: 提取完成 (high_0/high_1-1)*10, 0.002s
[2019-10-12 09:24:08.285716] INFO: derived_feature_extractor: 提取完成 (low_0/low_1-1)*10, 0.001s
[2019-10-12 09:24:08.288645] INFO: derived_feature_extractor: 提取完成 (open_0/open_1-1)*10, 0.001s
[2019-10-12 09:24:08.291632] INFO: derived_feature_extractor: 提取完成 (volume_0/volume_1-1)*10, 0.002s
[2019-10-12 09:24:08.349739] INFO: derived_feature_extractor: /y_2014, 61
[2019-10-12 09:24:08.385737] INFO: derived_feature_extractor: /y_2015, 244
[2019-10-12 09:24:08.419597] INFO: derived_feature_extractor: /y_2016, 244
[2019-10-12 09:24:08.450961] INFO: derived_feature_extractor: /y_2017, 37
[2019-10-12 09:24:08.578944] INFO: bigquant: derived_feature_extractor.v3 运行完成[0.440068s].
[2019-10-12 09:24:08.586030] INFO: bigquant: join.v3 开始运行..
[2019-10-12 09:24:08.733123] INFO: join: /y_2014, 行数=0/61, 耗时=0.028867s
[2019-10-12 09:24:08.774101] INFO: join: /y_2015, 行数=244/244, 耗时=0.036187s
[2019-10-12 09:24:08.807981] INFO: join: /y_2016, 行数=244/244, 耗时=0.029041s
[2019-10-12 09:24:08.835860] INFO: join: /y_2017, 行数=37/37, 耗时=0.026162s
[2019-10-12 09:24:08.914471] INFO: join: 最终行数: 525
[2019-10-12 09:24:08.917469] INFO: bigquant: join.v3 运行完成[0.331441s].
[2019-10-12 09:24:08.923535] INFO: bigquant: dropnan.v1 开始运行..
[2019-10-12 09:24:09.003998] INFO: dropnan: /y_2014, 0/0
[2019-10-12 09:24:09.032231] INFO: dropnan: /y_2015, 244/244
[2019-10-12 09:24:09.060844] INFO: dropnan: /y_2016, 244/244
[2019-10-12 09:24:09.091875] INFO: dropnan: /y_2017, 37/37
[2019-10-12 09:24:09.175157] INFO: dropnan: 行数: 525/525
[2019-10-12 09:24:09.178648] INFO: bigquant: dropnan.v1 运行完成[0.255089s].
[2019-10-12 09:24:09.212157] INFO: bigquant: dl_convert_to_bin.v2 开始运行..
[2019-10-12 09:24:09.608608] INFO: bigquant: dl_convert_to_bin.v2 运行完成[0.396427s].
[2019-10-12 09:24:09.619469] INFO: bigquant: dl_model_train.v1 开始运行..
[2019-10-12 09:24:10.476978] INFO: dl_model_train: 准备训练,训练样本个数:525,迭代次数:10
[2019-10-12 09:24:15.522367] INFO: dl_model_train: 训练结束,耗时:5.04s
[2019-10-12 09:24:15.632669] INFO: bigquant: dl_model_train.v1 运行完成[6.013195s].
[2019-10-12 09:24:15.636824] INFO: bigquant: instruments.v2 开始运行..
[2019-10-12 09:24:15.723619] INFO: bigquant: instruments.v2 运行完成[0.086768s].
[2019-10-12 09:24:15.767058] INFO: bigquant: general_feature_extractor.v7 开始运行..
[2019-10-12 09:24:15.909290] INFO: 基础特征抽取: 年份 2016, 特征行数=22
[2019-10-12 09:24:15.936480] INFO: 基础特征抽取: 年份 2017, 特征行数=244
[2019-10-12 09:24:16.009381] INFO: 基础特征抽取: 年份 2018, 特征行数=243
[2019-10-12 09:24:16.034893] INFO: 基础特征抽取: 年份 2019, 特征行数=0
[2019-10-12 09:24:16.115291] INFO: 基础特征抽取: 总行数: 509
[2019-10-12 09:24:16.119082] INFO: bigquant: general_feature_extractor.v7 运行完成[0.352045s].
[2019-10-12 09:24:16.122262] INFO: bigquant: derived_feature_extractor.v3 开始运行..
[2019-10-12 09:24:16.275716] INFO: derived_feature_extractor: 提取完成 (close_0/close_1-1)*10, 0.001s
[2019-10-12 09:24:16.279564] INFO: derived_feature_extractor: 提取完成 (high_0/high_1-1)*10, 0.002s
[2019-10-12 09:24:16.282840] INFO: derived_feature_extractor: 提取完成 (low_0/low_1-1)*10, 0.001s
[2019-10-12 09:24:16.286369] INFO: derived_feature_extractor: 提取完成 (open_0/open_1-1)*10, 0.001s
[2019-10-12 09:24:16.290287] INFO: derived_feature_extractor: 提取完成 (volume_0/volume_1-1)*10, 0.001s
[2019-10-12 09:24:16.357164] INFO: derived_feature_extractor: /y_2016, 22
[2019-10-12 09:24:16.393812] INFO: derived_feature_extractor: /y_2017, 244
[2019-10-12 09:24:16.434004] INFO: derived_feature_extractor: /y_2018, 243
[2019-10-12 09:24:16.551389] INFO: bigquant: derived_feature_extractor.v3 运行完成[0.429059s].
[2019-10-12 09:24:16.554769] INFO: bigquant: dropnan.v1 开始运行..
[2019-10-12 09:24:16.660816] INFO: dropnan: /y_2016, 22/22
[2019-10-12 09:24:16.689288] INFO: dropnan: /y_2017, 244/244
[2019-10-12 09:24:16.717598] INFO: dropnan: /y_2018, 243/243
[2019-10-12 09:24:16.826991] INFO: dropnan: 行数: 509/509
[2019-10-12 09:24:16.830246] INFO: bigquant: dropnan.v1 运行完成[0.275474s].
[2019-10-12 09:24:16.874946] INFO: bigquant: dl_convert_to_bin.v2 开始运行..
[2019-10-12 09:24:17.299778] INFO: bigquant: dl_convert_to_bin.v2 运行完成[0.424834s].
[2019-10-12 09:24:17.311071] INFO: bigquant: dl_model_predict.v1 开始运行..
[2019-10-12 09:24:18.701740] INFO: bigquant: dl_model_predict.v1 运行完成[1.390687s].
[2019-10-12 09:24:18.707861] INFO: bigquant: cached.v3 开始运行..
[2019-10-12 09:24:18.932672] INFO: bigquant: cached.v3 运行完成[0.224799s].
[2019-10-12 09:24:18.998790] INFO: bigquant: backtest.v8 开始运行..
[2019-10-12 09:24:19.004759] INFO: bigquant: biglearning backtest:V8.2.16
[2019-10-12 09:24:19.006832] INFO: bigquant: product_type:stock by specified
[2019-10-12 09:24:19.229838] INFO: bigquant: cached.v2 开始运行..
[2019-10-12 09:24:28.216680] INFO: bigquant: 读取股票行情完成:695
[2019-10-12 09:24:28.554987] INFO: bigquant: cached.v2 运行完成[9.325144s].
[2019-10-12 09:24:28.588720] INFO: algo: TradingAlgorithm V1.5.9
[2019-10-12 09:24:28.716281] INFO: algo: trading transform...
[2019-10-12 09:24:28.999478] INFO: algo: handle_splits get splits [dt:2017-08-24 00:00:00+00:00] [asset:Equity(0 [600009.SHA]), ratio:0.9882099126332605]
[2019-10-12 09:24:29.001557] INFO: Position: position stock handle split[sid:0, orig_amount:36200, new_amount:36631.0, orig_cost:27.61057956776991, new_cost:27.29, ratio:0.9882099126332605, last_sale_price:36.87999363789555]
[2019-10-12 09:24:29.003464] INFO: Position: after split: PositionStock(asset:Equity(0 [600009.SHA]), amount:36631.0, cost_basis:27.29, last_sale_price:37.31999969482422)
[2019-10-12 09:24:29.005225] INFO: Position: returning cash: 32.94
[2019-10-12 09:24:29.552385] INFO: algo: handle_splits get splits [dt:2018-08-23 00:00:00+00:00] [asset:Equity(0 [600009.SHA]), ratio:0.9900703412737303]
[2019-10-12 09:24:29.554974] INFO: Position: position stock handle split[sid:0, orig_amount:36631.0, new_amount:36998.0, orig_cost:27.29, new_cost:27.02, ratio:0.9900703412737303, last_sale_price:57.83000848272584]
[2019-10-12 09:24:29.556595] INFO: Position: after split: PositionStock(asset:Equity(0 [600009.SHA]), amount:36998.0, cost_basis:27.02, last_sale_price:58.40999984741211)
[2019-10-12 09:24:29.557921] INFO: Position: returning cash: 22.05
[2019-10-12 09:24:29.784782] INFO: Performance: Simulated 451 trading days out of 451.
[2019-10-12 09:24:29.786911] INFO: Performance: first open: 2017-03-01 09:30:00+00:00
[2019-10-12 09:24:29.788554] INFO: Performance: last close: 2018-12-28 15:00:00+00:00
[2019-10-12 09:24:31.831398] INFO: bigquant: backtest.v8 运行完成[12.832555s].
model = m6.load_model()
for i,layer in enumerate(model.layers):
print(i,layer.name,layer.output_shape)
from keras.models import Model
layer_model = Model(input=model.input, output=model.get_layer('L3').output)
x=m27.data.read()['x']
layer_result = layer_model.predict(x)
layer_result[0:1]