本文共 5022 字,大约阅读时间需要 16 分钟。
有朋友在分享了原始数据处理的想法,例如调整origin_data_row
参数、添加一些大盘的数据作为新的特征等。所以这一篇我将原始数据以及原始数据的处理方法写下来,为方便大家验证、探索更好地解决方案。
原始数据共有11列,
列名为:stock_num
,stock_date
,cir_market_value
,close_hfq
,high_hfq
,low_hfq
,open_hfq
,p_change
,total_value
,turnover
,volume
对应含义为: 股票代码、日期、流通市值、后复权收盘价、后复权最高价、后复权最低价、后复权开盘价、涨幅、总市值、换手率(流通股)、成交量(单位:股) 股票代码为整数形式,000001被表示为1,后复权以该股票上市之日计算
数据来源于网上多个数据源,进行交叉对比、填充后得到。主要有:
1. 2. 3. 某宝上面购买在此推荐使用python::pandas
库处理数据,它是使得python成为强大而高效的数据分析环境的重要因素之一。
学习资源:
1. 网上有教程,可以用以作为入门引导。 2. 《利用python进行数据分析》,可以再上搜索到。这本书无论是当成入门的教材还是查询的工具书,都表现优异。原始数据处理代码:
def make_train_test_csv(cls, orgin_data_path=None, all_data_path=None, time_step=60): """ 制作股票分类数据 orgin_data_path:原始数据存放路径 all_data_path:制作成可被算法接收的文件存放路径 """ basic_path = os.path.dirname(os.path.abspath(__file__)) #初始化源文件路径和存储文件路径 if orgin_data_path is None: orgin_data_path = os.path.join(basic_path, "origin_data.csv") if all_data_path is None: all_data_path = os.path.join(basic_path, "all_data.csv") #读取原始数据,只保留需要使用的列 total_data = pd.read_csv(orgin_data_path, usecols=["open_hfq", "high_hfq", "low_hfq", "close_hfq", "turnover", "volume", "cir_market_value", "stock_date", "stock_num"]) #根据股票代码排序,相同的股票代码按照交易日期排序。 #inplace参数表示不需要返回排序后的结果,直接覆盖原变量即可 total_data.sort_values(by = ['stock_num', 'stock_date'], inplace = True) #根据股票代码分组 g_stock_num = total_data.groupby(by = ["stock_num"]) #针对每一组股票,分别计算收益gate,其定义为:(下下一个交易日的开盘价 / 下一个交易日的开盘价) - 1 #对gate乘以100,使之变成百分比形式(0.09 -> 9,表示9%) #使用np.round函数保存两位小数,之后的数字丢弃(9.8346474 - > 9.83) total_data["gate"] = np.round((100 * (g_stock_num.shift(-2)["open_hfq"] / g_stock_num.shift(-1)["open_hfq"] - 1)), 2) #重新调整列的顺序,为接下来处理成输入、输出形式做准备 total_data = total_data[["open_hfq", "high_hfq", "low_hfq", "close_hfq", "turnover", "volume", "cir_market_value", "gate", "stock_date", "stock_num"]] #将调整列顺序后的代码,重新按照股票代码分组 g_stock_num = total_data.groupby(by = ["stock_num"]) #拿time_step个交易日的数据(默认为60个交易日),进行标准化 def func_stand(data_one_stock_num, time_step): #通过apply进入函数内的数据,其股票名为data_one_stock_num.name,类型为pd.dataFrame #即,进入此函数的数据为所有名为data_one_stock_num.name的集合 #dataFrame.shape:(num , 11), num是这个股票出现的次数 for colu_name in data_one_stock_num.columns: if colu_name in ["gate", "stock_date", "stock_num"]: continue #只针对输入数据进行标准化,标准化算法为: (原始数据 - 平均值) / 标准差 #这里每一次for循环,都拿出了1列数据,针对这一列进行标准化并覆盖原数据 data_one_stock_num[colu_name] = ((data_one_stock_num[colu_name] - data_one_stock_num[colu_name].rolling(time_step).mean())/data_one_stock_num[colu_name].rolling(time_step).std()) return data_one_stock_num #将经过标准化的数据处理成训练集和测试集可接受的形式 def func_train_test_data(data_one_stock_num, time_step): print ("正在处理的股票代码:code:%06d"%data_one_stock_num.name) #提取输入列(对应train_x) data_temp_x = data_one_stock_num[["open_hfq", "high_hfq", "low_hfq", "close_hfq", "turnover", "volume", "cir_market_value"]] #提取输出列(对应train_y) data_temp_y = data_one_stock_num[["gate", "stock_date", "stock_num"]] data_res = [] #for循环从time_step - 1开始,因为前time_step - 1个数据不满足time_step条件 #例如:time_step为60,即需要60个交易日的数据制成训练集的一个输入,但某只股票因为停牌等原因,只有50个交易日的数据。那么它就可以跳过了,不满足最低数目的要求 for i in range(time_step - 1, len(data_temp_x.index)): data_res.append( data_temp_x.iloc[i - time_step + 1: i + 1].values.reshape(1, time_step * 7).tolist() + data_temp_y.iloc[i][["gate", "stock_date", "stock_num"]].values.reshape(1,3).tolist() ) if len(data_res) != 0: #使用末尾添加的形式,将各个股票的数据依次添加进设定的路径中。 #index参数表示是否需添加一列序号,header表示是否需要添加列头,mode表示选择哪一种模型进行csv操作(类似于open函数的模型) pd.DataFrame(data_res).to_csv(all_data_path, index=False, header=False, mode="a") return data_one_stock_num #数据标准化 data_after_stand = g_stock_num.apply(func_stand, time_step = time_step) data_after_stand.dropna(inplace = True) #将数据转成训练集合的形式 g_stock_num = data_after_stand.groupby(by = ["stock_num"]) #清空接收路径下的文件,初始化列名 pd.DataFrame({"0":[], "1":[]}).to_csv(all_data_path, index=False) g_stock_num.apply(func_train_test_data, time_step = time_step) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
运行截图:
欢迎加入qq群: 一起探索量化分析股票的方法。
示例数据(2016年1月至2017年9月)以及完整代码可在获得。
更加详尽的训练集数据(2006年至2017年9月,文件名:origin_data_total_20060104-20170904.rar
)可以在qq群里下载获得(数据量较大,不方便上传至github)。