2016年9月9日 星期五

[機器學習練習] [Machine Learning Practice] 用 Scikit 學習台灣指數趨勢(七)- 回測與討論

上一集已經把機器訓練好了,

為了驗證機器的預測是否可以拿來當作投資依據,

我們要跑一跑回測。

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

Step 9 : BACKTEST

我回測是從 2009 年開始,你也可以從 2000 年開始,結果應該差不多。

讓我們在剛剛的程式碼底下,寫一個回測的方法如下,


def backtest(dataframe, startday, classifier):

    # 先取出要回測的資料

    df_backtest = dataframe.loc[startday:]

    # 匯入特徵值
    X_backtest = np.array(df_backtest[['y_K9', 'y_D9', 'y_close_mvag5', 'y_close_mvag20']])
    X_backtest = preprocessing.scale(X_backtest)


    # 讓機器預測
    forecast = classifier.predict(X_backtest)

    # 假設初始金錢為 100000
    deposit = 100000
    deposits = []
    right_call = 0
    right_put = 0
    wrong_call = 0
    wrong_put = 0

    # 開始跑從 2009 到今天,每一天的交易情形
    for i in range(len(df_backtest.index)):

        if forecast[i] == 1:

            # 因為是假設買一口大台,一點的賺賠是 200 元
            deposit += (df_backtest['long'][i] * 200)
            print ('%d, %s long, because forecast is: %d, you earn: %d' %(df_backtest['open'][i], df_backtest.index[i].isoformat() , forecast[i], df_backtest['long'][i]))
            if df_backtest['long'][i] > 0:
                right_call +=1
            else:
                wrong_call +=1
        elif forecast[i] == 0:
            deposit += (df_backtest['short'][i] * 200)
            print ('%d, %s short, because forecast is: %d, you earn: %d' %(df_backtest['open'][i], df_backtest.index[i].isoformat() , forecast[i], df_backtest['short'][i]))
            if df_backtest['short'][i] > 0:
                right_put +=1
            else:
                wrong_put +=1
        deposits.append(deposit)
        print (deposit)

    # 這邊基本上只是賺賠結果視覺化
    df_backtest['deposits'] = pd.Series(deposits, index= df_backtest.index)
    right_score = right_put + right_call
    wrong_score = wrong_put + wrong_call
    call_accuracy = right_call / float(right_call + wrong_call)
    put_accuracy = right_put / float(right_put + wrong_put)
    accuracy = right_score/float(right_score + wrong_score)

    print ('your final deposit is %d' %(deposit))
    print ('right call & put:', right_call, right_put, 'wrong call & put:', wrong_call, wrong_put)
    print ('call_accuracy: %f , put_accuracy: %f , accuracy: %f' %(call_accuracy, put_accuracy, accuracy))


    ax1 = plt.subplot2grid((2,1),(0,0))
    ax2 = plt.subplot2grid((2,1),(1,0), sharex= ax1)
    df_backtest[['close', 'close_mvag5', 'close_mvag20']].plot(ax= ax1, linewidth=3, color=['k','r','g','b'])
    df_backtest['deposits'].plot(ax= ax2, linewidth=3, color='k')
    plt.show()

backtest(df,date(2009,1,1),clf)


好,這邊要講一下我們假設,

因為我們機器只是預測今天漲跌,也就是開盤和收盤價差,

那我們投資期指的假設,就也是開盤下單,收盤平倉這樣簡單的交易,

而且無論如何,就是每天只下一口大台指

機器判斷 1 我們就做多,第 i 天賺賠就是 df['long'][i] * 200,

機器判斷 0 我們就做空,第 i 天賺賠就是 df['short'][i] * 200。

大概是這樣,讓我們在終端機輸入 python twfuture.py 看一看結果。






























神一般的圖形對吧?


從 2009 年 1 月 1 號開始投入十萬元,到今天居然有 5872200 元!

5000 % 的投資報酬率,又超級美麗的近乎直線,沒什麼大波動,

好,大家可以遞辭呈或是休學,準備環遊世界了。







半個月前我看到這個的時候,已經完全不擔心找工作的事情,

開始幻想退休生活要做什麼了。

但是事情絕對不是我們想得這麼簡單。

當初那種超低的準確率,憑什麼回測可以跑出這種實力,

準確率還提高到六成五。



做夢先做到這,回想一下,剛剛訓練機器的時候,是拿什麼資料。

2000 ~ 2015,而我們現在又是拿 2009 到 2015 的資料給他跑回測,

這就等於,考了考古題的概念,所以真正能判斷你的機器準與不準的,

只有 2016 年這一年的獲利率以及準確率,

因為機器沒有學到今年的狀況。



所以讓我們把 backtest(df,date(2009,1,1), clf) 改成 backtest(df,date(2016,1,1),clf)

再來看一看悲劇的預測結果,

多悲劇我就不貼上來,大家走到這一步的可以自己看自己多悲劇。

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

Step 10 : 結果討論

到這邊,我們已經走完全部步驟,從

瞭解期貨 -> 爬取資料 -> 資料前處理 -> 決定特徵與演算法 ->

資料處理 -> Training -> Backtest -> Forecast



這邊先跟大家說一下,千萬不要灰心

回測結果或許很糟糕,但不好的結果就代表有巨大的改進空間,

代表無論我們做什麼改善,都可以進步!

而且,至少我們從頭到尾,走過了一次用機器學習預測台股期指的流程。



下面討論一下可以改進的地方,

首先,我們可能要衡量一下訓練資料與回測資料的衝突

因為台指期貨只有不到 20 年歷史,回測想跑很久,拿來學習的資料就不能太長,

這算是機器學習先天上的一個缺點。

這邊列一下幾個可以改進的地方,

1. 選擇的特徵

可以選用其他技術指標或甚至再去爬取自己想要的資料( Ex 摩台指、台幣美金匯率)

2. 訓練的時間長度

在訓練的時間長度上,也可以有所改變。

3. 選擇的演算法

這就不用多說,可以測試新演算法或是在 最近鄰居法 上,作些微修改。

4. 定義 Label

改變我們定義的 Label 或許可以更加準確的預測。



基本上,上面的事情,我都做了,也確實得到不錯的改善,

有興趣的人,可以繼續做做看,有問題也可以一起討論。

如果有人不小心試出了一個超屌的模型,也要記住,投資有賺有賠

阿如果不小心用這個訓練的流程賺到錢,也歡迎捐錢給我 ><



最後,講一下這個機器學習預測期指的未來計劃,

在預測中,我們只有一個觀念的轉換,其實處理這類訊號的時候,

很需要非線性轉換,所以用深度學習的觀念,可以更加完好地詮釋複雜的判斷邏輯。

除此之外,可以多搭配幾種金融衍伸興商品作避險,如:

台幣美金匯率、ETF、選擇權......等等。

前提當然是要把深度學習好好地學好



最後,給大家看一個東西,




























這是一張外資累積多空口數,我覺得很酷,分享給大家。

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

Reference

[1] 期貨 wikipedia

[2] 股票指數 wikipedia

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

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


2 則留言:

  1. 想請教最後backtest出來的結果,也是拿現有的資料進去predict然後驗證

    那如果我想predict的是明天會漲或跌呢,就沒有KD或其他參考值可以丟進去了

    求解Q_Q

    回覆刪除
    回覆
    1. 我跑回測的時候,是有把 label 做一天的 shift,
      所以本來就是用昨天看到的KD值預測今天的漲跌,
      因此,預測明天就是用今天的KD值這樣子。

      刪除