利用Machine Learning 選股新手教學

最近一直在弄Machine Learning,都快忘記寫blog了,哈!

其實要machine選股真的很簡單!這篇blog就會帶大家從頭開始,用最簡單的方式,將Machine Learning實做!這邊只是給大家一個簡單的架構,可以自己去嘗試優化,讓它更聰明!以下是用mac或是linux的command line完成的,假如有任何錯誤或不懂的地方歡迎聯絡我喔~

1. 免費取得資料

取得資料的方法很簡單,幫冷清的寒舍小小宣傳一下:

  1. 分享任一你覺得很有趣的FinLab文章於FB
  2. 將分享截圖傳到 [email protected]
  3. 一兩天內即可獲得 data.csv!

依照本blog的含金量、data.csv的完整程度,你一定不會後悔的!

2. 架設環境

假如你已經會使用python了,那可以直接跳過這個步驟,假如不會的話,可以照著下面的步驟完成:

  1. 官網下載Python3,並且安裝
  2. 安裝pip
  3. 安裝virtualenv

為何要安裝pip呢?

pip可以幫我們下載Machine Learning所需要的package(也就是python的libraries)。

為何要安裝 virtualenv 呢?

virtualenv可以幫你產生project的環境,每一個project用自己的libraries,這樣比較不容易有衝突。

3. 建置project

首先,先用virtualenv創建project

create project
1
2
virtualenv finance_ml
cd finance_ml

接下來必須要開啟工作環境:

activate and deactivate project
1
2
source bin/activate
deactivate

這邊有兩行,一行是開啟環境,一行是結束環境!假如你還要繼續,先不要輸入第二行。
將data.csv複製到當前資料夾,並且安裝python packages

install python packages
1
2
3
4
pip install jupyter
pip install pandas
pip install sklearn
pip install matplotlib

4. 開工!

首先就是開啟jupyter notebook,並開一個python的環境

start notebook
1
jupyter notebook

這樣會開啟一個網頁版的GUI介面,只要新增python的notebook就可以用了!
接下來進入我們的主題:機器學習程式碼!

A. 讀入資料

這邊我們用 pandas 讀入所需要的資料,index_col可以設定要哪一個columns當作index。這邊的index選擇在 data.csv 中,第一個未命名的column。

read data
1
2
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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
1
2
3
4
5
6
7
8
9
10
11
%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,是否可以選到更好的股票呢?就留給各位慢慢玩!以下是可以改進的地方:

  1. feature engineering:將features做修正、刪除、normalize等
  2. 篩選能獲利X%的股票
  3. classification vs regression:可以兩種都試試看
  4. 不同的model,可以試試SVM、NN、XGBoost等等
  5. 不同的model都有可以調整超多參數來達到優化
  6. 利用early stop 來預防overfitting。

我只是列出最基本的,還有很多可以玩的,這也是我這禮拜正在弄的東西,害我都沒時間寫網誌XDD

假如覺得文章不錯,那更不能錯過我們的影音課程喔!
或我們按個 鼓勵一下吧!