最近一直在弄Machine Learning,都快忘記寫blog了,哈!
其實要machine選股真的很簡單!這篇blog就會帶大家從頭開始,用最簡單的方式,將Machine Learning實做!這邊只是給大家一個簡單的架構,可以自己去嘗試優化,讓它更聰明!以下是用mac或是linux的command line完成的,假如有任何錯誤或不懂的地方歡迎聯絡我喔~
1. 免費取得資料
取得資料的方法很簡單,幫冷清的寒舍小小宣傳一下:
- 分享任一你覺得很有趣的FinLab文章於FB
- 將分享截圖傳到 [email protected]
- 一兩天內即可獲得 data.csv!
依照本blog的含金量、data.csv的完整程度,你一定不會後悔的!
2. 架設環境
假如你已經會使用python了,那可以直接跳過這個步驟,假如不會的話,可以照著下面的步驟完成:
- 到官網下載Python3,並且安裝
- 安裝pip
- 安裝virtualenv
為何要安裝pip呢?
pip可以幫我們下載Machine Learning所需要的package(也就是python的libraries)。
為何要安裝 virtualenv 呢?
virtualenv可以幫你產生project的環境,每一個project用自己的libraries,這樣比較不容易有衝突。
3. 建置project
首先,先用virtualenv創建project
create project
virtualenv finance_ml
cd finance_ml
接下來必須要開啟工作環境:
activate and deactivate project
source bin/activate
deactivate
這邊有兩行,一行是開啟環境,一行是結束環境!假如你還要繼續,先不要輸入第二行。
將data.csv複製到當前資料夾,並且安裝python packages
install python packages
pip install jupyter
pip install pandas
pip install sklearn
pip install matplotlib
4. 開工!
首先就是開啟jupyter notebook,並開一個python的環境
start notebook
jupyter notebook
這樣會開啟一個網頁版的GUI介面,只要新增python的notebook就可以用了!
接下來進入我們的主題:機器學習程式碼!
A. 讀入資料
這邊我們用 pandas 讀入所需要的資料,index_col可以設定要哪一個columns當作index。這邊的index選擇在 data.csv 中,第一個未命名的column。
read data
import pandas as pd
data = pd.read_csv('data.csv', index_col='Unnamed: 0', parse_dates=['buy_date', 'sell_date'])
B.處理資料
我們將資料分成三類,一類是跑回測用的dbacktest,另一類是機器學習用的dtraning,另外一個是traning完用來評估的dtest。
process data
from sklearn.model_selection import train_test_split
# clear data 將爛資料去掉
data.dropna(how='any', inplace=True)
# 選擇2015年以後的資料作為回測用
dbacktest = data[data['buy_date'] > '2015']
# 將其於的資料再分成兩類:dtrain 跟 dtest
dataTrainTest = data[data['sell_date'] < '2015']
dtrain, dtest = train_test_split(dataTrainTest, test_size=0.10, random_state=42)
# 設定我們的feature要用哪些
features = data.columns[5:-1]
C. 機器學習訓練資料
這邊我們用很簡單的隨機森林,來完成的,可以參考連結來學習怎麼樣調整參數,這應該算是機器學習中,前置作業最少的模型了!
learning
from sklearn.ensemble import RandomForestClassifier
# 創建機器學習的model
rf = RandomForestClassifier(n_estimators=10, criterion='gini',
max_depth=None, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0.0,
max_features='auto', max_leaf_nodes=None,
bootstrap=True, oob_score=False, n_jobs=1,
random_state=None, verbose=0, warm_start=False,
class_weight=None)
# 分類能獲利的股票
rf.fit(dtrain[features], dtrain['獲利'] > 1)
D. 結果
你說這樣就結束了!?對呀結束了。其實machine learning要簡單真的就只是這樣而已!
接下來我們來看一下它預測的准不準:
predict
result = rf.predict(dtest[features])
print('test data')
print('gain before filtered', dtest['獲利'].mean())
print('gain after filtered', dtest['獲利'][result].mean())
print('num stocks', sum(result), '/', len(dtest))
result = rf.predict(dbacktest[features])
print('backtest data')
print('gain before filtered', dbacktest['獲利'].mean())
print('gain after filtered', dbacktest['獲利'][result].mean())
print('num stocks', sum(result), '/', len(dbacktest))
假如一切順利就會看到以下結果:
這邊的gain是指平均的報酬率,也就是所有股票的價格在賣出時是否賺錢,小於一就是虧,大於一就是賺。
結果看起來還滿猛的!竟然有接近7%的報酬率!
但真的是如此嗎?我們把它畫成隨著時間,本金成長的獲利圖:
backtest
%matplotlib inline
dbacktest['預測'] = pd.Series(result, index=dbacktest.index)
dates = list(set(dbacktest['buy_date']))
dates.sort()
history = []
for d in dates:
history.append(dbacktest[(dbacktest['buy_date'] == d) & (dbacktest['預測'])]['獲利'].mean())
pd.Series(history, index=dates).cumprod().plot()
發現其實沒有想像中那麼好。這是意料之中的結果,畢竟我們的learning時間才幾秒鐘,假如增加n_estimator這個變數,是否可以讓結果更好?假如使用Regression會不會更好?假如改變一下機器學習的參數、或修改一下features,是否可以選到更好的股票呢?就留給各位慢慢玩!以下是可以改進的地方:
- feature engineering:將features做修正、刪除、normalize等
- 篩選能獲利X%的股票
- classification vs regression:可以兩種都試試看
- 不同的model,可以試試SVM、NN、XGBoost等等
- 不同的model都有可以調整超多參數來達到優化
- 利用early stop 來預防overfitting。
我只是列出最基本的,還有很多可以玩的,這也是我這禮拜正在弄的東西,害我都沒時間寫網誌XDD