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