2016年9月8日 星期四

[機器學習練習] [Machine Learning Practice] 用 Scikit 學習台灣指數趨勢(五)- 資料處理

上一集我們決定了要使用的特徵以及演算法

這一集將會用程式碼去實現均線和 KD 值處理,

開始吧!

------------------------------------------------------------------------------------------------------------

Step 7 : 資料前處理

第三集中,我們成功地爬完全部資料,並且也把資料用 Pickle 存起來了。

第三集中也有講到如何用 Pickle 呼叫出我們爬的資料並且直接使用。

現在我們在相同資料夾內,創建一個新的 Python 檔案,名稱叫做 twfuture.py

在檔案裡面加入以下程式碼,


import pickle
import numpy as np
import pandas  as pd
from sklearn import preprocessing, cross_validation, neighbors
from datetime import date
import matplotlib.pyplot as plt
from matplotlib import style


pickle_in = open('TWfuture.pickle', 'rb')
df = pickle.load(pickle_in)


print (df.tail())


存檔後在終端機中執行該檔案,

(別忘了有沒安裝的 library 要用 pip 去安裝,在這邊有講


 python twfuture.py


就可以看到上次爬下來的資料。



















沒問題後,讓我們開始寫 5 日均線、20 日均線和 KD 值的程式碼吧!


import pickle
import numpy as np
import pandas  as pd
from sklearn import preprocessing, cross_validation, neighbors
from datetime import date


pickle_in = open('TWfuture.pickle', 'rb')
df = pickle.load(pickle_in)


df = df[['open', 'high', 'low', 'settlement', 'volume', 'close', 'open_int', 'close_best_bid', 'close_best_ask']]

df['close_adjusted'] = df['close']
df['close_adjusted'].fillna(df['settlement'], inplace=True)
df['close_best_bid'].fillna(df['settlement'], inplace=True)
df['close_best_ask'].fillna(df['settlement'], inplace=True)



這邊呢,要先處理一些 NaN 的資料

因為台灣指數期貨在每個月的第三個禮拜三結算,所以每週三的 close price 都是 NaN,

這邊我們用 fillna 去處理,並且用當日 settlement price 來取代當天的 close price。

處理完後,我們就可以來寫均線的程式碼,在檔案中繼續加入以下程式碼,


df['close_mvag5'] = df['close_adjusted'].rolling(window=5).mean()
df['close_mvag20'] = df['close_adjusted'].rolling(window=20).mean()


沒錯!就是這麼簡單!

因為 pandas 真的很好用!

再來我們要實現比較麻煩的 KD 值,KD 值的公式如下,





首先解決一下 RSV 到底是什麼

Raw Stochastic Value 也就是未成熟隨機值,如果上一集的連結有點過去看的話,

應該可以知道 Raw Stochastic Value (n) 等於:

100%  *(第 n 日的收盤價 - 過去 n 日中最低價)/(過去 n 日最高價 - 過去 n 日中最低價)

通常取 n = 9,可以發現 RSV 一定介於 0 ~ 100 之間

舉例來說,如果要算在 9 / 8 號的 RSV(9),


台股指數期貨 ( 8/29 ~ 9/8 )
8 / 29 (一) 8 / 30 (二) 8 / 31 (三) 9 / 1 (四) 9 / 2 (五)  9 / 5 (一) 9 / 6 (二) 9 / 7 (三) 9 / 8 (四)
9000 9100 9200 9100 9000 8900 9000 9100 9100


就是取 9 / 5 的價格當做最低值,8 / 31 的價格當作最高值

RSV = ( 9100 - 8900 ) / ( 9200 - 8900 ) = 66.6 %

RSV 代表的意思是,當天收盤價是屬於強勢還是弱勢,100 % 就是強勢,0 % 則反之



Recall KD 的公式,





K 與 D 都是離散遞回方程式,α 是平滑係數,通常設置為 1/3。

把這條公式翻譯成中文就是,

今天的 K 等於 昨天的 K 乘上某係數 加上 今天的 RSV 乘上某係數,

今天的 D 等於 昨天的 D 乘上某係數 加上 今天的 K 乘上某係數。


那這個到底代表什麼意思呢?

我們把 K D 的公式做 z-transform 後就看比較清楚了。












我知道很醜,式一為對 K 做 z-transform 後求出的公式,

式二是移項整理得到的 K,式三是移項整理得到的 D,

把 Z 看作是頻率,可以發現

K 就是 RSV 的低通濾波,D 則是 K 的低通濾波!

所以 K 有點類似 RSV 的均線,D 則像是 K 的均線。

當 K 越大,代表最近股價越來越強勢,當 K 超過 D 通常就是買進的訊號。



理解公式後,就讓我們把 RSV 和 KD 的程式碼實作出來吧。

在均線的程式碼底下,繼續加上以下,


# 計算 RSV
df['RSV'] = 100* (( df['Close'] - df['Low'].rolling(window=9).min() ) / (df['High'].rolling(window=9).max() - df['Low'].rolling(window=9).min()))

df['RSV'].fillna(method='bfill', inplace=True)


data = {'K9':[17],'D9':[39]}

# 計算每一天的 KD

for i in range(1,len(df.index)):
    K9_value = (1/3) * df['RSV'][i] + (2/3) * data['K9'][i-1]
    data['K9'].append(K9_value)
    D9_value = (2/3) * data['D9'][i-1] + (1/3) * data['K9'][i]
    data['D9'].append(D9_value)



# 把 KD 放進 DataFrame
df_KD = pd.DataFrame(data)
df = pd.concat([df, df_KD], axis=1, join_axes=[df.index])


因為我們在算第一天的 K 值時,並不知道昨天的 K 值,

D 值也是相同情況,那股市中都是假設為 50。

到這邊,我們應該就有 K9、 D9 和 5 日、20 日均線的 feature 了!

最後為了方便接下來 training,我們直接把 K9、 D9 和 5 日、20 日均線,都往後 shift 一天。


df[['y_close_mvag5','y_close_mvag20','y_K9','y_D9']] = df[['close_mvag5','close_mvag20','K9','D9']].shift(1)

print (df.tail())


試著在終端機中執行看看,我們現在應該已經都準備好可以開始訓練機器了!

------------------------------------------------------------------------------------------------------------

Reference

[1] 期貨 wikipedia

[2] 股票指數 wikipedia

[3] 台灣期貨交易所, http://www.taifex.com.tw/

[4] Codecademy, https://www.codecademy.com/

1 則留言:

  1. 您好我在查看y_close_mvag5時還是有遇到NAN的狀況,那這樣的話是不是算fillna 沒成功壓?

    回覆刪除