以預測股票漲跌案例入門基於SVM的機器學習
SVM是Support Vector Machine的縮寫,中文叫支援向量機,通過它可以對樣本資料進行分類。以股票為例,SVM能根據若干特徵樣本資料,把待預測的目標結果劃分成“漲”和”跌”兩種,從而實現預測股票漲跌的效果。
1 通過簡單案例瞭解SVM的分類作用
在Sklearn庫裡,封裝了SVM分類的相關方法,也就是說,我們無需瞭解其中複雜的演算法,即可用它實現基於SVM的分類。通過如下SimpleSVMDemo.py案例,我們來看下通過SVM庫實現分類的做法,以及相關方法的呼叫方式。
1 #!/usr/bin/env python 2 #coding=utf-8 3 import numpy as np 4 import matplotlib.pyplot as plt 5 from sklearn import svm 6 #給出平面上的若干點 7 points = np.r_[[[-1,1],[1.5,1.5],[1.8,0.2],[0.8,0.7],[2.2,2.8],[2.5,3.5],[4,2]]] 8 #按0和1標記成兩類 9 typeName = [0,0,0,0,1,1,1]
在第5行裡,我們引入了基於SVM的庫。在第7行,我們定義了若干個點,並在第9行把這些點分成了兩類,比如[-1,1]點是第一類,而[4,2]是第二類。
這裡請注意,在第7行定義點的時候,是通過np.r_方法,把資料轉換成“列矩陣”,這樣做的目的是讓資料結構滿足fit方法的要求。
10 #建立模型 11 svmTool = svm.SVC(kernel='linear') 12 svmTool.fit(points,typeName) #傳入引數 13 #確立分類的直線 14 sample = svmTool.coef_[0] #係數 15 slope = -sample[0]/sample[1] #斜率 16 lineX = np.arange(-2,5,1)#獲取-2到5,間距是1的若干資料 17 lineY = slope*lineX-(svmTool.intercept_[0])/sample[1]
在第11行裡,我們建立了基於SVM的物件,並指定該SVM模型採用比較常用的“線性核”來實現分類操作。
在第14行,通過fit訓練樣本。這裡fit方法和之前基於線性迴歸案例中的fit方法是一樣的,只不過這裡是基於線性核的相關演算法,而之前是基於線性迴歸的相關演算法(比如最小二乘法)。訓練完成後,通過第14行和第15行的程式碼,我們得到了能分隔兩類樣本的直線,包括直線的斜率和截距,並通過第16行和第17行的程式碼設定了分隔線的若干個點。
18 #畫出劃分直線 19 plt.plot(lineX,lineY,color='blue',label='Classified Line') 20 plt.legend(loc='best') #繪製圖例 21 plt.scatter(points[:,0],points[:,1],c='R') 22 plt.show()
計算完成後,我們通過第19行的plot方法繪製了分隔線,並在第21行通過scatter方法繪製所有的樣本點。由於points是“列矩陣”的資料結構,所以是用points[:,0]來獲取繪製點的 x座標,用points[:,1]來獲取y座標,最後是通過第22行的show方法繪製圖形。執行上述程式碼,我們能看到如下圖13.8的效果,從中我們能看到,藍色的邊界線能有效地分隔兩類樣本。
從這個例子中我們能看到,SVM的作用是,根據樣本,訓練出能劃分不同種類資料的邊界線,由此實現“分類”的效果。而且,在根據訓練樣本確定好邊界線的引數後,還能根據其它沒有明確種類樣本,計算出它的種類,以此實現“預測”效果。
2 資料標準化處理
標準化(normalization)處理是將特徵樣本按一定演算法進行縮放,讓它們落在某個範圍比較小的區間,同時去掉單位限制,讓樣本資料轉換成無量綱的純數值。
在用機器學習方法進行訓練時,一般需要進行標準化處理,原因是Sklearn等庫封裝的一些機器學習演算法對樣本有一定的要求,如果有些特徵值的數量級偏離大多數特徵值的數量級,或者有特徵值偏離正態分佈,那麼預測結果會不準確。
需要說明的是,雖然在訓練前對樣本進行了標準化處理,改變了樣本值,但由於在標準化的過程中是用同一個演算法對全部樣本進行轉換,屬於“資料優化”,不會對後繼的訓練起到不好的作用。
這裡我們是通過sklearn庫提供的preprocessing.scale方法實現標準化,該方法是讓特徵值減去平均值然後除以標準差。通過如下ScaleDemo.py案例,我們實際用下preprocessing.scale方法。
1 #!/usr/bin/env python 2 #coding=utf-8 3 from sklearn import preprocessing 4 import numpy as np 5 6 origVal = np.array([[10,5,3], 7 [8,6,12], 8 [14,7,15]]) 9 #計算均值 10 avgOrig = origVal.mean(axis=0) 11 #計算標準差 12 stdOrig=origVal.std(axis=0) 13 #減去均值,除以標準差 14 print((origVal-avgOrig)/stdOrig) 15 scaledVal=preprocessing.scale(origVal) 16 #直接輸出preprocessing.scale後的結果 17 print(scaledVal)
在第6行裡,我們初始化了一個長寬各為3的矩陣,在第10行,通過mean方法計算了該矩陣的均值,在第12行則通過std方法計算標準差。
第14行是用原始值減去均值,再除以標準差,在第17行,是直接輸出preprocessing.scale的結果。第14行和第17行的輸出結果相同,均是下值,從中我們驗證了標準化的具體做法。
1 [[-0.26726124 -1.22474487 -1.37281295] 2 [-1.06904497 0. 0.39223227] 3 [ 1.33630621 1.22474487 0.98058068]]
3 預測股票漲跌
在之前的案例中,我們用基於SVM的方法,通過一維直線來分類二維的點。據此可以進一步推論:通過基於SVM的方法,我們還可以分類具有多個特徵值的樣本。
比如可以通過開盤價、收盤價、最高價、最低價和成交量等特徵值,用SVM的演算法訓練出這些特徵值和股票“漲“和“跌“的關係,即通過特徵值劃分指定股票“漲”和“跌”的邊界,這樣的話,一旦輸入其它的股票特徵資料,即可預測出對應的漲跌情況。在如下的PredictStockBySVM.py案例中,我們給出了基於SVM預測股票漲跌的功能。
1 #!/usr/bin/env python 2 #coding=utf-8 3 import pandas as pd 4 from sklearn import svm,preprocessing 5 import matplotlib.pyplot as plt 6 origDf=pd.read_csv('D:/stockData/ch13/6035052018-09-012019-05-31.csv',encoding='gbk') 7 df=origDf[['Close', 'Low','Open' ,'Vol','Date']] 8 #diff列表示本日和上日收盤價的差 9 df['diff'] = df["Close"]-df["Close"].shift(1) 10 df['diff'].fillna(0, inplace = True) 11 #up列表示本日是否上漲,1表示漲,0表示跌 12 df['up'] = df['diff'] 13 df['up'][df['diff']>0] = 1 14 df['up'][df['diff']<=0] = 0 15 #預測值暫且初始化為0 16 df['predictForUp'] = 0
第6行裡,我們從指定檔案讀取了包含股票資訊的csv檔案,該csv格式的檔案其實是從網路資料介面獲取得到的,具體做法可以參考前面博文。
從第9行裡,我們設定了df的diff列為本日收盤價和前日收盤價的差值,通過第12行到第14行的程式碼,我們設定了up列的值,具體是,如果當日股票上漲,即本日收盤價大於前日收盤價,則up值是1,反之如果當日股票下跌,up值則為0。
在第16行裡,我們在df物件裡新建了表示預測結果的predictForUp列,該列的值暫且都設定為0,在後繼的程式碼裡,將根據預測結果填充這列的值。
17 #目標值是真實的漲跌情況 18 target = df['up'] 19 length=len(df) 20 trainNum=int(length*0.8) 21 predictNum=length-trainNum 22 #選擇指定列作為特徵列 23 feature=df[['Close', 'High', 'Low','Open' ,'Volume']] 24 #標準化處理特徵值 25 feature=preprocessing.scale(feature)
在第18行裡,我們設定訓練目標值是表示漲跌情況的up列,在第20行,設定了訓練集的數量是總量的80%,在第23行則設定了訓練的特徵值,請注意這裡去掉了日期這個不相關的列,而且,在第25行,對特徵值進行了標準化處理。
26 #訓練集的特徵值和目標值 27 featureTrain=feature[1:trainNum-1] 28 targetTrain=target[1:trainNum-1] 29 svmTool = svm.SVC(kernel='liner') 30 svmTool.fit(featureTrain,targetTrain)
在第27行和第28行裡,我們通過擷取指定行的方式,得到了特徵值和目標值的訓練集,在第26行裡,以線性核的方式建立了SVM分類器物件svmTool。
在第30行裡,通過fit方法,用特徵值和目標值的訓練集訓練svmTool分類物件。從上文裡我們已經看到,訓練所用的特徵值是開盤收盤價、最高最低價和成交量,訓練所用的目標值是描述漲跌情況的up列。在訓練完成後,svmTool物件中就包含了能劃分股票漲跌的相關引數。
31 predictedIndex=trainNum 32 #逐行預測測試集 33 while predictedIndex<length: 34 testFeature=feature[predictedIndex:predictedIndex+1] 35 predictForUp=svmTool.predict(testFeature) 36 df.ix[predictedIndex,'predictForUp']=predictForUp 37 predictedIndex = predictedIndex+1
在第33行的while迴圈裡,我們通過predictedIndex索引值,依次遍歷測試集。
在遍歷過程中,通過第35行的predict方法,用訓練好的svmTool分類器,逐行預測測試集中的股票漲跌情況,並在第36行裡,把預測結果設定到df物件的predictForUp列中。
38 #該物件只包含預測資料,即只包含測試集 39 dfWithPredicted = df[trainNum:length] 40 #開始繪圖,建立兩個子圖 41 figure = plt.figure() 42 #建立子圖 43 (axClose, axUpOrDown) = figure.subplots(2, sharex=True) 44 dfWithPredicted['Close'].plot(ax=axClose) 45 dfWithPredicted['predictForUp'].plot(ax=axUpOrDown,color="red", label='Predicted Data') 46 dfWithPredicted['up'].plot(ax=axUpOrDown,color="blue",label='Real Data') 47 plt.legend(loc='best') #繪製圖例 48 #設定x軸座標標籤和旋轉角度 49 major_index=dfWithPredicted.index[dfWithPredicted.index%2==0] 50 major_xtics=dfWithPredicted['Date'][dfWithPredicted.index%2==0] 51 plt.xticks(major_index,major_xtics) 52 plt.setp(plt.gca().get_xticklabels(), rotation=30) 53 plt.title("通過SVM預測603505的漲跌情況") 54 plt.rcParams['font.sans-serif']=['SimHei'] 55 plt.show()
由於在之前的程式碼裡,我們只設置測試集的predictForUp列,並沒有設定訓練集的該列資料,所以在第39行裡,用切片的手段,把測試集資料放置到dfWithPredicted物件中,請注意這裡切片的起始和結束值是測試集的起始和結束索引值。至此完成了資料準備工作,在之後的程式碼裡,我們將用matplotlib庫開始繪圖。
在第43行裡,我們通過subplots方法設定了兩個子圖,並通過sharex=True讓這兩個子圖的x軸具有相同的刻度和標籤。在第44行程式碼裡,在axClose子圖中,我們用plot方法繪製了收盤價的走勢。在第45行程式碼裡,在axUpOrDown子圖中,我們繪製了預測到的漲跌情況,而在第46行裡,還是在axUpOrDown子圖裡,繪製了這些天的股票真實的漲跌情況。
在第49行到第52行的程式碼裡,我們設定了x標籤的文字以及旋轉角度,這樣做的目的是讓標籤文字看上去不至於太密集。在第53行裡,我們設定了中文標題,由於要顯示中文,所以需要第54行的程式碼,最後在55行通過show方法展示了圖片。執行上述程式碼,能看到如下圖所示的效果。
其中上圖展示了收盤價,下圖的藍色線條表示真實的漲跌情況,0表示跌,1表示上漲,而紅色則表示預測後的結果。
4 結論
對比一下,雖有偏差,但大體相符。綜上所述,本案例是數學角度,演示了通過SVM分類的做法,包括如果劃分特徵值和目標值,如何對樣本資料進行標準化處理,如何用訓練資料訓練SVM,還有如何用訓練後的結果預測分類結果。
5 總結和版權說明
本文是給程式設計師加財商系列,之前還有兩篇博文
用python的matplotlib和numpy庫繪製股票K線均線和成交量的整合效果(含量化驗證交易策略程式碼) 用python的matplotlib和numpy庫繪製股票K線均線的整合效果(含從網路介面爬取資料和驗證交易策略程式碼) 本文的內容即將出書,在出版的書裡,是用股票案例和大家講述Python入門時的知識點,敬請期待有不少網友轉載和想要轉載我的博文,本人感到十分榮幸,這也是本人不斷寫博文的動力。關於本文的版權有如下統一的說明,抱歉就不逐一回復了。
1 本文可轉載,無需告知,轉載時請用連結的方式,給出原文出處,別簡單地通過文字方式給出,同時寫明原作者是hsm_computer。
2 在轉載時,請原文轉載 ,謝絕洗稿。否則本人保留追究法律責任的權利。
&n