
Python量化交易学习笔记(41)——深度学习挖短线股1
本文记录使用Keras筛选短线个股的流程,主要步骤如下:准备数据,根据短线个股筛选标准,给个股日线数据打标。模型训练,针对每只股票,训练得到分类模型。策略回测,根据训练得到的模型,回测策略的各指标情况。个股筛选,根据模型筛选出当前符合买入条件的股票。...
·
本文开始探索使用深度学习进行量化交易的过程,几点说明如下:
- 文章仍然以“趟路”为主要目的,旨在走通将深度学习在量化交易中使用过程,忽略当前学习模型的收益情况。
- 深度学习框架选择使用Keras。没有特殊原因,就是之前下载zwPython时,里面集成了Keras,拿来直接用了,省去配置环境的工作量,图个方便。
- 数据源来自baostock。
- 后续文章将陆续尝试多种模式、多种深度模型(包括RNN)在量化中的应用,望读者多多捧场指教。
- 笔者对Python和深度学习来说都是新手,如有错误或待改进之处,还请多多批评指正。
本文首先探索使用简单的全连接网络筛选短线个股的流程,主要步骤如下:
- 数据预处理,根据短线个股筛选标准,给个股日线数据打标。
- 模型训练,针对每只股票,训练得到分类模型。
- 结果预测,根据训练得到的模型,计算股票每日的分类预测值。
- 策略回测,基于股票每日的分类预测值,回测策略收益情况。
- 个股筛选,如果策略验证可行,即可根据模型筛选出当前符合买入条件的股票。
数据预处理
这里将短线个股的筛选问题处理为使用深度学习解决的分类问题,目标是筛选出10个交易日内,上涨幅度大于10%的股票。这里选择2017年12月31日及之前的数据作为训练数据,2018年1月1日之后的数据用于做预测。
- 股票范围选择
为了应用深度学习算法,需要有足够的训练数据。为此,选择2016年1月1日至2017年12月31日内日线数量多于300的个股,代码如下:
import pandas as pd
stk_code_file = './stk_data/stk_list.csv'
stk_list = pd.read_csv(stk_code_file)['code'].tolist()
pd_stocks_list = []
for stk_code in stk_list:
df = pd.read_csv('./stk_data/d/{}.csv'.format(stk_code))
if df[(df['date'] >= '2016-01-01') & (df['date'] <= '2017-12-31')].shape[0] > 300:
pd_stocks_list.append(stk_code)
out_df = pd.DataFrame(pd_stocks_list, columns = ['code'])
out_df.to_csv('./stk_data/dp_stock_list.csv', index = False)
- 训练数据计算
选择2017年12月31日及之前的数据作为训练数据,计算训练数据的输入特征及分类标签。
将10个交易内上涨幅度超过10%的股票标记为类别1,其他股票标记为类别0。
为了给深度学习模型提供更多的输入维度,可以基于日线数据的开盘价、收盘价、最高价、最低价、成交量等进行扩展。这里只扩展5、10、20、30、60、120、240均线及均量线数据,后续可根据需要计算MACD、KDJ、RSI等指标数据,进一步扩展输入维度。
指标及类别计算代码如下:
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import datetime # 用于datetime对象操作
import os.path # 用于管理路径
import sys # 用于在argvTo[0]中找到脚本名称
import pandas as pd
import numpy as np
# 引入topq_talib,计算技术指标
script_path = os.path.dirname(os.path.abspath(sys.argv[0]))
talib_path = os.path.join(script_path, '../TQDat/TQDown2020v1/topqt/')
sys.path.append(talib_path)
import topq_talib as tt
# 类别标准:N个交易日内上涨INC_PER
N = 10
INC_PER = 0.1
# n 天内上涨inc_per
def calc_buy_signal(df, n, inc_per):
df = df[df.notnull().T.all()]
buy = np.zeros(df.shape[0])
df.insert(df.shape[1], 'buy', buy)
df = df.copy()
row_i = 0
for row_i in range(df.shape[0]):
for n_i in range(n):
if row_i + n_i + 1 < df.shape[0] and \
df.iloc[row_i + n_i + 1].at['close'] - df.iloc[row_i].at['close'] > inc_per * df.iloc[row_i].at['close']:
df.loc[df.index[row_i], 'buy'] = 1
break
return df
# 读入股票代码
stk_code_file = './stk_data/dp_stock_list.csv'
stk_pools = pd.read_csv(stk_code_file, encoding = 'gbk')
# 对每个股票添加衍生数据
for stk_code in stk_pools['code']:
# 读入数据
input_file = './stk_data/d/' + stk_code + '.csv'
if not os.path.exists(input_file):
continue
df = pd.read_csv(input_file, index_col = 0)
df = df.sort_index(ascending = True)
# MA
ma_list = [5, 10, 20, 30, 60, 120, 240]
for i in ma_list:
df = tt.MA_n(df, i)
# vol_MA
vol_ma_list = [5, 10, 20, 30, 60, 120, 240]
for i in vol_ma_list:
df = tt.vol_MA_n(df, i)
'''可扩展指标
#BBANDS
df = tt.BBANDS_UpLow(df, 20)
#MACD
df = tt.MACD020(df, 12, 26)
#KDJ
df = tt.KDJ(df, 9, 3)
#RSI
df = tt.RSI(df, 14)
# A/D
ad_list = [5, 10, 20, 30, 60, 120, 240]
for i in ad_list:
df = tt.ACCDIST(df, i)
# ATRcd
atr_list = [5, 10, 20, 30, 60, 120, 240]
for i in atr_list:
df = tt.ATR(df, i)
'''
df = calc_buy_signal(df, N, INC_PER)
# 写出文件
output_file = './baostock/data_ext/' + stk_code +'.csv'
df.to_csv(output_file)
print(stk_code + ' done!')
上面代码中,调用topq_talib来计算扩展指标,读者可以根据具体情况调用其他包或者自己实现相应的指标。
为了应用时序上的信息,将前10日的指标数据合并到当日,作为输入特征,代码如下:
import numpy as np
import pandas as pd
import os
# 使用前FEATURE_N的K线数据作为输入特征
FEATURE_N = 10
# 预处理,将n行数据作为输入特征
def data_preprocessing(df, stk_code, n):
df = df.copy()
# 删除无效数据列,保留特征数据
ft_df = df.drop(columns = ['date', 'buy'])
# 返回值
out_df = pd.DataFrame()
# 生成新特征数据
for i in range(n, df.shape[0]):
# 取n行数据
part_df = ft_df.iloc[i - n : i]
# 将n行合并为一行
new_ft_df = pd.DataFrame(part_df.values.reshape(1, -1))
out_df = out_df.append(new_ft_df)
out_df['target'] = df.iloc[n:df.shape[0]]['buy'].values
out_df = out_df.reset_index(drop = True)
out_df.to_csv('./baostock/data_pre/{}.csv'.format(stk_code), index = False)
return out_df
stk_code_file = './stk_data/dp_stock_list.csv'
stk_list = pd.read_csv(stk_code_file)['code'].tolist()
for stk_code in stk_list:
# 判断是否已经经过预处理(文件是否存在)
data_file = './baostock/data_pre/{}.csv'.format(stk_code)
if not os.path.exists(data_file):
print('processing {} ...'.format(stk_code))
df = pd.read_csv('./baostock/data_ext/{}.csv'.format(stk_code))
df = df[df['date'] <= '2017-12-31']
df = data_preprocessing(df, stk_code, FEATURE_N)
- 预测数据计算
为了便于后面的回测使用,这里将预测数据的计算与训练数据的计算分开处理,但二者计算实现逻辑基本相同,对2018年1月1日至2020年6月30日间的数据进行预测,代码如下:
import numpy as np
import pandas as pd
import os
# 使用前FEATURE_N的K线数据作为输入特征
FEATURE_N = 10
# 预处理,将n行数据作为输入特征
def data_preprocessing(df, stk_code, n):
df = df.copy()
# 删除无效数据列,保留特征数据
ft_df = df.drop(columns = ['date', 'buy'])
# 返回值
out_df = pd.DataFrame()
# 生成新特征数据
for i in range(n, df.shape[0]):
# 取n行数据
part_df = ft_df.iloc[i - n : i]
# 将n行合并为一行
new_ft_df = pd.DataFrame(part_df.values.reshape(1, -1))
out_df = out_df.append(new_ft_df)
out_df = out_df.reset_index(drop = True)
out_df.to_csv('./baostock/prediction_data_pre/{}.csv'.format(stk_code), index = False)
return out_df
stk_code_file = './stk_data/dp_stock_list.csv'
stk_list = pd.read_csv(stk_code_file)['code'].tolist()
for stk_code in stk_list:
# 判断是否已经经过预处理(文件是否存在)
data_file = './baostock/prediction_data_pre/{}.csv'.format(stk_code)
if not os.path.exists(data_file):
print('processing {} ...'.format(stk_code))
df = pd.read_csv('./baostock/data_ext/{}.csv'.format(stk_code))
df = df[df['date'] <= '2020-06-30']
# 选择指定日期前FEATURE_N天的数据
index_list = df[df['date'] > '2017-12-31'].index.tolist()
if len(index_list) == 0 or min(index_list) < FEATURE_N:
continue
df = df[min(index_list) - FEATURE_N:]
df = data_preprocessing(df, stk_code, FEATURE_N)
这篇文章完成了数据预处理工作,后续文章继续介绍基于这些数据进行训练、预测以及回测的过程。
博客内容只用于交流学习,不构成投资建议,盈亏自负!
个人博客:http://coderx.com.cn/(优先更新)
项目最新代码:https://gitee.com/sl/quant_from_scratch
欢迎大家转发、留言。有微信群用于学习交流,感兴趣的读者请扫码加微信!
如果认为博客对您有帮助,可以扫码进行捐赠,感谢!
微信二维码 | 微信捐赠二维码 |
---|---|
![]() | ![]() |
更多推荐
所有评论(0)