投資大師與量化選股策略


實現專業投資人的量化選股投資策略

以初學者都能懂的python語法搭配TEJ資料庫API與財金計算工具,實現專業投資人的量化選股投資策略,並進行驗證。

 

投資大師是誰?

 

如華倫·巴菲特(Warren Edward Buffett)被台灣人認為是一代股神,常被稱為奧哈瑪的先知(The Oracle of Omaha),原因就在於他所提倡的以股東權益報酬率評估公司好壞的方法,不但帶給他長期而穩定的投資績效,更樹立了以股東權益報酬率來選股的典範,幾乎沒有投資學教科書不提到這個選股觀念。

 

但除了巴菲特以外,有許多獲取長期優異績效的投資者,為規模龐大的知名共同基金擬定投資戰略。如班傑明.葛拉漢(Benjamin Graham)與彼得.林區(Peter Lynch)就是在國內較有知名度,以價值型投資為主的專業投資人,班傑明.葛拉漢甚至被譽為價值型投資之父,華爾街眾多以價值型投資為準則的經理人,半數以上是班傑明.葛拉漢的徒子徒孫;而彼得.林區則曾在麥哲倫基金(Magellan Fund)出任基金經理人,13年內讓麥哲倫基金的規模不斷成長,年平均報酬率接近30%。

 

像這樣以價值型投資法為主的知名投資大師,國內或許可以找到針對其事蹟的介紹、也有以文字來描述其投資策略,但卻甚少有直接以實際的市場狀況,將其投資策略轉換為量化指標進行選股,實際重現其投資策略,並以回顧測試(back test)的方式,驗證其投資策略是否能在台灣證券市場,發揮一樣的功力。

 

在本系列文章中,TEJ將示範以資料庫API直接介接python程式,建構一個標準的量化選股投資完整流程,並進行回顧測試,驗證這些以價值型投資法為主的投資方式,若改以台股為投資標的,是否仍能展現出優異的投資績效。

投資策略建構流程

 

以巴菲特為例,其選股策略最著名的部分,就是強調公司經營者必需把股東權益報酬率放在心上,但並沒有多加著墨-比如,股東權益報酬率要多高才好?股東權益報酬是要佔整個市場排名前幾名,還是只要比平均值高就好?又若是該公司產業一時之間因為產業景氣循環而使股東權益報酬變差,是否要為此出售該公司股票?

 

這些疑問如何解決,就會反應在建構量化指標上面。當我們將股東權益報酬率的門檻設得越高、自然會讓大部份的股票被篩選掉,甚至可能陷入無股可買的問題;而如何針對公司一時的績效衰退設定指標,給予其一定的容忍度,更能避免我們陷入追高殺低的循環裡。

 

因此,投資策略的建構流程第一步,就是計算出各種量化的指標,這些指標都有其對應的「經濟意涵」,也就是這些指標有著經濟學觀念為依歸,能用來協助我們評估這些公司是否為具有長期投資價值的公司。

 

試著建立計算程序

 

我們這邊就先以巴菲特的「把重點集中在股東權益報酬率,而非每股盈餘」的觀念,建構出一組量化的選股指標。

為了符合這樣的觀念,我們選擇以股東權益報酬率來建立以下的標準:

 

  1. 股東權益報酬率 = (近四個季 常續性稅後盈餘 的加總) / 股東權益
  2. 最近年度股東權益報酬率>平均值(市場及產業)
  3. 三年平均股東權益報酬率>15%

 

這邊可以注意到我們使用「常續性稅後盈餘」一詞,取代一般常見的稅後盈餘。這是因為在IFRS實施後,由於部分業外損益將會因為不同的原因實現在損益表,而這些損益並不會是該公司本業經常能有的收益,因此TEJ會將這些非常續性的項目扣除,計算出常續性稅後盈餘,比一般的稅後盈餘更適合用在公司基本面的評估上。

 

接著,由於巴菲特並沒有明示過應該以平均值或特定數值為門檻來進行選股,似乎使我們陷入了困境。但這並不會是一個大問題,因為就算巴菲特過去的投資方式有脈絡可以循,可以反推其選股,以及股東權益報酬率平均來說要在什麼水平,但那也是美國股票的選股標準,並不見得適用於台灣市場。因此我們可以先暫定一個數值為水平,如上面的選股標準以當年度大於市場平均、過去五年平均股東權益報酬率要大於15%為標準。

 

先以這個暫定數值建立的標準進行選股,然後測試其績效,由於整個選股回測流程都是透過tej所建構的python程式來執行,只要設定選股指標的計算,就能半自動地完成,因此我們可以任意地替換不同的數值標準,比如:15%也許太高、也許太低,我們可以試著進行多次回顧測試,每次都以不同的標準計算(改為10%、或20%、或更高),看看績效以何者為佳,透過大規模量化測試,就能得出更適合台灣市場的量化選股指標設定值。

 

這些指標的計算,有些可能牽涉較為複雜的python語法,無法以普通的加減乘除完成,或是現有的知名函式庫如numpy沒有支援那樣的計算,我們為了簡化並方便後續其他策略可能可以重覆使用,就會將這些計算方法包裝成一個標準函式,讓使用者需要決定參數,就可以進行計算、回傳計算結果。不但可以讓整個選股指標的計算過程更容易閱讀,也可以透過優化這些函式來提高計算效率。

 

回測各指標

 

指標建構完成之後,就直接觀察該指標計算的結果,是否符合我們認為該有的樣子,而最好的方法,就是以市場上知名表現良好的公司來觀察,這些知名公司在這些選股指標上的表現如何。

 

這邊以台積電(2330)為例,觀察其最近一年股東權益報酬率與其近三年平均股東權益報酬率的水準如何:

 

 

 

我們可以看到,台積的股東權益報酬率隨著財報的公佈,在近一年來是先維持在高檔,然後下挫;這是因為股東權益報酬率的分子是稅後盈餘,而台積電確實在最近一季稅後盈餘表現較差,因此過去四個財報季度的合計稅後盈餘就變差了。

 

但就算是如此,仍然在15%以上,有著15.84%的水準,似乎我們暫定使用的15%是個不錯的開始。

 

另外,這邊使用了TEJ自行撰寫的計算工具的函式calculate_moving()來計算股東權益報酬率的平均值,由於股東權益報酬率是隨財報更新的數值,這個函式可以自行判斷此欄位是否為財報欄位,進而決定計算平均時要以日為基礎,或是以財報不重覆質為基礎去計算平均;如此一來,就可以產生像圖中這樣,只要一更新最新財報,數值就會產生劇烈變化的效果。

 

以選股策略建構投資組合,並進行回測

 

後續的回顧測試中,為了避免大型股(如大立光)無法買入整數股的問題,我們會以假定一億新台幣為起始資金,將符合選股條件的股票,在進行回測的各個日期以等投資金額權重的方式,假定以當天收盤價買進,並以次一日的收盤價計算整個投資組合的損益。

從回顧的起始日(2018-05-02)開始,每天重新計算選股指標、進行選股,然後將不符合的股票剔除、買入符合的股票;若是原本通過選股指標挑選的股票,在之後變得不符合,則將其從投資組合中移除,並且把空出的資金額度平均分配給剩餘留在投資組合中的股票。

 

藉由這種相同而簡單的選股配重計算方式,將各個投資策略拉到相同的基準點上,避免因為擇時或配重方式不同,影響其投資策略的績效,而導致不同策略之間無法評估好壞。

 

到這邊,我們就可以明白,一個完整的量化投資策略流程將會是這個樣子:

 

 

我們後續就將按照這個標準流程,建構並驗證不同的投資策略。

 

回測損益的觀察

 

每次針對投資策略進行回顧測試時,會假設以一億元資金開始進行投資,並且與大盤(加權指數,但為調整除權息效果的報酬指數)的績效進行比較,如前面用股東報酬率進行簡單篩選的策略,回顧測試結果如下:

 

 

 

我們可以看到,奧哈馬的先知巴菲特先生簡單、直覺的「專注在股東權益報酬率」的選股方式,輕易地在回顧測試期間打敗了大盤績效。藉由回顧測試過程每日損益的觀察,也可以觀察到特定期間內,大盤可能受到特殊事件影響而劇烈震盪,看看以投資策略建構的投資組合,在特殊事件期間,損益的變化。

 

TEJ在進行投資策略的回顧測試時,亦會同時記錄回顧日各個日期,持股的清單與權重,可以進行投資調性的分析,這會在後續有專文介紹。

 

結語

 

總和以上說明,TEJ將會以這樣詳細講解各步驟的模式,每周定期刊出一篇專文,將有過優異績效的專業投資人、基金經理人的投資策略,建構為量化的投資指標,以台股為範例進行選股、績效計算,如此反覆每日驗證與執行,進行一年期的回顧測試。

 

藉由這一系列的示範,讓python能力僅有初學者程度的人,甚至尚未學習過python的人,都能透過python這個程式語言的特色:簡潔明瞭好閱讀的程式碼,加上程式碼中的註解,都能理解每個基於基本面的量化投資策略是如何執行的。

 

附錄:python程式範例

 

最後,每篇測試將會附上計算過程的python程式碼,並說明本次計算中用到的功能函式以及所使用到得TEJ API資料庫,以方便TEJ的使用者可以了解重現該策略的過程所需具備的工具與資料。以本篇簡易範例而言,用到了能計算全市場/產業平均的函式calculate_crossing()以及計算各股移動窗口時序列的calculate_moving()函式,以計算全市場的股東報酬率平均值,以及個別股票的移動三年股東權益平均值。

TEJ API Pyhton程式碼:

#進行各指標計算
def calculate(tejtool,param):
    
    tejtool.data['股東權益報酬率'] = tejtool.data['常續性稅後淨利移動四季合計'] /tejtool.data['母公司股東權益合計']
    tejtool.data['股東權益報酬率全平均'] = tejtool.calculate_crossing('股東權益報酬率')
    tejtool.data['股東權益報酬率移動三年均值'] = tejtool.calculate_moving('股東權益報酬率',window=3,not_duplicate=True,col_kind='mean')
    
    #檢查股東權益報酬率是否在目標範圍內
    tejtool.data['門檻條件'] = 0.15
    tejtool.data['股東權益報酬率檢查'] = tejtool.check_above('股東權益報酬率移動三年均值','門檻條件',1)
    tejtool.data['股東權益報酬率平均檢查'] = tejtool.check_above('股東權益報酬率','股東權益報酬率全平均',1)

   
    return tejtool.data
#設定要輸出觀測的各指標時序列圖(以設定的觀察個股為例進行繪圖)
def output(tejtool,param): 
    #最多輸出一張表,三張圖,一張圖裡最多可以塞三條線
    
    tejtool.output_indicator(['股東權益報酬率'])
    tejtool.output_indicator(['股東權益報酬率全平均'])
    tejtool.output_indicator(['股東權益報酬率移動三年均值'])


#控制選股與否、投資比重等
def evaluate(tejtool,param):
    
    #以條件判斷哪些股票要買或不買,然後以均等投資金額來決定持股股數
    tejtool.data['購入'] = tejtool.check_condition(['股東權益報酬率檢查','股東權益報酬率平均檢查'],'and')

    #使用均等投資金額來分配投資比重
    tejtool.data['投資比重'] = tejtool.equal_pv()
    return tejtool.data