Python量化交易学习笔记(41)——深度学习挖短线股1

本文开始探索使用深度学习进行量化交易的过程,几点说明如下:

  • 文章仍然以“趟路”为主要目的,旨在走通将深度学习在量化交易中使用过程,忽略当前学习模型的收益情况。
  • 深度学习框架选择使用Keras。没有特殊原因,就是之前下载zwPython时,里面集成了Keras,拿来直接用了,省去配置环境的工作量,图个方便。
  • 数据源来自baostock。
  • 后续文章将陆续尝试多种模式、多种深度模型(包括RNN)在量化中的应用,望读者多多捧场指教。
  • 笔者对Python和深度学习来说都是新手,如有错误或待改进之处,还请多多批评指正。

本文首先探索使用简单的全连接网络筛选短线个股的流程,主要步骤如下:

  1. 数据预处理,根据短线个股筛选标准,给个股日线数据打标。
  2. 模型训练,针对每只股票,训练得到分类模型。
  3. 结果预测,根据训练得到的模型,计算股票每日的分类预测值。
  4. 策略回测,基于股票每日的分类预测值,回测策略收益情况。
  5. 个股筛选,如果策略验证可行,即可根据模型筛选出当前符合买入条件的股票。

数据预处理

这里将短线个股的筛选问题处理为使用深度学习解决的分类问题,目标是筛选出10个交易日内,上涨幅度大于10%的股票。这里选择2017年12月31日及之前的数据作为训练数据,2018年1月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)
  1. 训练数据计算
    选择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)
  1. 预测数据计算

为了便于后面的回测使用,这里将预测数据的计算与训练数据的计算分开处理,但二者计算实现逻辑基本相同,对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)

这篇文章完成了数据预处理工作,后续文章继续介绍基于这些数据进行训练、预测以及回测的过程。

欢迎大家关注、点赞、转发、留言,感谢支持!
为了便于相互交流学习,已建微信群,感兴趣的读者请加微信。

在这里插入图片描述

おすすめ

転載: blog.csdn.net/m0_46603114/article/details/107970812