1. 程式人生 > >使用tensorflow:LSTM神經網路預測股票(三)

使用tensorflow:LSTM神經網路預測股票(三)

原始資料處理

有朋友在qq群裡分享了原始資料處理的想法,例如調整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. tushre 2. 新浪財經 3. 某寶上面購買

原始資料處理方法

在此推薦使用python::pandas庫處理資料,它是使得python成為強大而高效的資料分析環境的重要因素之一。

學習資源: 1. 網上有十分鐘搞定pandas教程,可以用以作為入門引導。 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群: 643033887 一起探索量化分析股票的方法。

示例資料(2016年1月至2017年9月)以及完整程式碼可在這裡獲得。

更加詳盡的訓練集資料(2006年至2017年9月,檔名:origin_data_total_20060104-20170904.rar )可以在qq群裡下載獲得(資料量較大,不方便上傳至github)。