1. 程式人生 > 其它 >Python 與金融科技9|生成機器學習的標籤和特徵

Python 與金融科技9|生成機器學習的標籤和特徵

技術標籤:Python金融資料python機器學習人工智慧大資料

這一期,我們將共同學習如何生成機器學習所需要的特徵和標籤。有了特徵和標籤,我們才能使用機器學習方法對資料進行分類。然後根據建立好的分類模型完成預測。

前言

在這個系列中,我們將共同學習如何藉助Python這個強大的工具處理金融資料。在正式開始這個系列的學習之前,需要您具有Python程式設計的基礎知識,至少需要將Python安裝好。如果暫時還不滿足這一要求的,建議先關注公眾號 IT資訊教室,學習 Python入門教程。

內容首發於微信公眾號IT資訊教室,如果您想學習更多AI相關的技能,歡迎搜尋關注或微信掃描下方二維碼關注~~

在這裡插入圖片描述

機器學習概述

說到機器學習,就不得不提到其中的一些基本概念:

標籤,特徵,模型,樣本

首先來看標籤。機器學習一般就是去訓練機器,讓機器有‘思維’,然後能夠用訓練好的‘思維’幫助我們去預測一些事情。因此機器學習的目的之一是去預測資訊。而這裡預測的資訊就叫做 標籤。這個標籤都是人為去設定的,由於自然界的資訊是多種多樣的,因此標籤也是多種多樣的。標籤可以是一類物體,比如’水果’,‘蔬菜’ 等。也可以是一種變化趨勢,例如 '未來股票走勢’等。

標籤的選擇對我們的預測結果很重要,最好不要選的太泛,也不要選的特別具體。

另一個概念是特徵。標籤表示的是資訊,而具體一個標籤表示什麼樣的資訊就是由特徵決定的。例如 ‘毛絨絨的’,‘白色的’,‘長長的耳朵’,‘喜歡吃胡蘿蔔和青菜’,這些資訊可以作為特徵,而 ‘兔子’ 就可以作為這些特徵對應的標籤。當然,也可以定義為其他標籤,例如‘動物’。

特徵就是一系列的資訊,用來表徵事物,映射出標籤。特徵應該是具體可量化的資訊,不包括主觀感受。

模型,就是能訓練與預測的程式。模型的訓練過程就是找到特徵與標籤之間固定化的對映關係。訓練好的模型會用來預測標籤。預測的過程就是根據給定的特徵,按照固定化的關係,判斷出標籤是什麼。

從模型預測的資訊可以將其分為迴歸模型和分類模型。 迴歸模型用於預測“未來”會發生的事情。而分類模型,用於預測事物是哪一類。

樣本一般就是指的資料,是特徵的封裝。 樣本可以帶標籤,也可以不帶標籤。

帶標籤的樣本,可以用於模型的訓練。 不帶標籤的樣本,可用於模型的預測。

生成標籤

我們定義的標籤有買入,賣出和繼續持有。分別用數字 1,-1 和 0 表示。標籤的定義方法是由未來 7 天內收盤價的變化趨勢決定的。如果 7天 內會最先出現收盤價漲幅超過 x% 的情況,那麼就定義當前的標籤為買入,如果 7天 內會最先出現收盤價跌幅超過 x% 的情況,那麼就定義當前的標籤為賣出。其餘情況定義為繼續持有。

以 x=2 為例,使用函式 buySellHold 實現上述功能,程式碼實現如下:

def buySellHold(*args):
    cols = [col for col in args]
    requirement = 0.02
    for col in cols:
        if col > requirement:
            return 1
        if col < -requirement:
            return -1
    return 0

*args 表示當前函式傳遞的引數個數是未知的。多個引數可以通過列表傳遞。這樣,給定一組股票的特徵資料(特徵資料的獲取參考上一期),使用這個函式就能生成對應的標籤。

提取特徵、生成標籤

提取特徵、生成標籤

def extractFeaturesets(ticker):

首先根據上一期的內容生成交易資訊的特徵資料:

tickers, dataFrame = processDataForLables(ticker)

生成的新的 dataFrame 中 ‘ticker_1d’, ‘ticker_2d’, …, ‘ticker_7d’ 對應列的內容將作為我們每一支股票生成標籤的資料。

            600585.SS_1d  600585.SS_2d  600585.SS_3d  600585.SS_4d  600585.SS_5d  600585.SS_6d  600585.SS_7d
Date                                                                                                        
2010-01-04     -0.012037     -0.009753     -0.041290     -0.039423     -0.067014     -0.050209     -0.090043
2010-01-05      0.002312     -0.029610     -0.027720     -0.055647     -0.038637     -0.078956     -0.072449
2010-01-06     -0.031848     -0.029962     -0.057825     -0.040855     -0.081081     -0.074588     -0.078360
2010-01-07      0.001948     -0.026832     -0.009303     -0.050853     -0.044146     -0.048042     -0.045659
2010-01-08     -0.028723     -0.011229     -0.052698     -0.046005     -0.049892     -0.047514     -0.011015
2010-01-11      0.018012     -0.024683     -0.017792     -0.021795     -0.019346      0.018232     -0.035357

例如以上資料,對於第一行資料,首先出現了跌幅大於 2% 的情況(三天後),因此確定當前日期的操作為賣出,那麼標籤就設為 -1。同理根據每一天的資料確定對應的標籤,實現方法如下:

def extractFeaturesets(ticker):
    tickers, dataFrame = processDataForLables(ticker)
    
    dataFrame['{}_target'.format(ticker)] = list(map(buySellHold,
                                                     dataFrame['{}_1d'.format(ticker)],
                                                     dataFrame['{}_2d'.format(ticker)],
                                                     dataFrame['{}_3d'.format(ticker)],
                                                     dataFrame['{}_4d'.format(ticker)],
                                                     dataFrame['{}_5d'.format(ticker)],
                                                     dataFrame['{}_6d'.format(ticker)],
                                                     dataFrame['{}_7d'.format(ticker)]
                                                     )
                                                 )

針對特定股票 ticker,其每一天的標籤資訊存放在 ticker_target 這一列中。按照我們的定義,ticker_target 一列中的資料值為 -1,1 或 0。

針對特定股票 ticker,其每一天的標籤資訊存放在 ticker_target 這一列中。按照我們的定義,ticker_target 一列中的資料值為 -1,1 或 0。

為了實現這一功能,可以先把資料格式轉為列表,然後使用 Counter 這個方法來統計,並將結果輸出:

values = dataFrame['{}_target'.format(ticker)].values.tolist()
print('dataSpread:', Counter(values))

因為 Counter 這個方法來自於一個獨立的工具包,使用之前需要先匯入:

from collections import Counter

這時如果先呼叫並執行這個函式,將任意一個股票程式碼作為函式的引數:

extractFeaturesets('600585.SS')

就能看到與以下類似的輸出:

dataSpread: Counter({1: 1318, -1: 1199, 0: 132})

這個行輸出表示,按照我們制定的交易規則,對於 ‘600585.SS’ 這支股票,有 1318天 適合繼續買入,有 1199天 適合賣出,另外有 132天 適合繼續持有。

接下來為了方便後續的操作,我們先對資料做一些簡單的清洗。把空資料使用 0 填充,另外把無窮大或者無窮小的資料捨棄掉:

dataFrame.fillna(0, inplace=True)
dataFrame = dataFrame.replace([np.inf, -np.inf], np.nan)
dataFrame.dropna(inplace=True)

然後生成特徵,我們選取當日價格相比前一日價格的變化率作為機器學習的特徵,獲取這個變化率可以使用 pct_change 這個方法:

dataFrameValues = dataFrame[ [ticker for ticker in tickers] ].pct_change()

同樣的,對生成的資料做簡單的清洗:

dataFrameValues.replace([np.inf, -np.inf], 0, inplace = True)
dataFrameValues.fillna(0, inplace=True)

這裡將無窮大或者無窮小的資料都用 0 代替。對空白資料也是用 0 填充。

最後我們將生成好的特徵和標籤以列表的格式返回,為了方便後續的呼叫,同時返回處理完成後的完整資料:

X = dataFrameValues.values
X = dataFrame['{}_target'.format(ticker)].values
return X, y, dataFrame

X 是處理好的特徵資料,y 是處理好的標籤資料,兩者是逐行對應的。

參考程式碼

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
@author:  IT資訊教室(微信公眾號)
訂閱/關注,在看、分享三連吧~
"""
def buySellHold(*args):
    cols = [col for col in args]
    requirement = 0.02
    for col in cols:
        if col > requirement:
            return 1
        if col < -requirement:
            return -1
    return 0

def extractFeaturesets(ticker):
    tickers, dataFrame = processDataForLables(ticker)
    
    dataFrame['{}_target'.format(ticker)] = list(map(buySellHold,
                                                     dataFrame['{}_1d'.format(ticker)],
                                                     dataFrame['{}_2d'.format(ticker)],
                                                     dataFrame['{}_3d'.format(ticker)],
                                                     dataFrame['{}_4d'.format(ticker)],
                                                     dataFrame['{}_5d'.format(ticker)],
                                                     dataFrame['{}_6d'.format(ticker)],
                                                     dataFrame['{}_7d'.format(ticker)]
                                                     )
                                                
    values = dataFrame['{}_target'.format(ticker)].values.tolist()
    print('dataSpread:', Counter(values))
    
    dataFrame.fillna(0, inplace=True)
    dataFrame = dataFrame.replace([np.inf, -np.inf], np.nan)
    dataFrame.dropna(inplace=True)
    
    dataFrameValues = dataFrame[ [ticker for ticker in tickers] ].pct_change()
    dataFrameValues.replace([np.inf, -np.inf], 0, inplace = True)
    dataFrameValues.fillna(0, inplace=True)
    
    X = dataFrameValues.values
    y = dataFrame['{}_target'.format(ticker)].values
    
    return X, y, dataFrame