Skip to main content

【程式交易實戰 02】策略績效度量的方法(上)

· 13 min read

歡迎來到 程式交易實戰 的第二堂課,上堂課我們學習到交易策略的基本組成以及簡單的當沖策略,但將想法轉換成程式碼後,我們還需要透過回測驗證及調整,才能夠確保策略的可行性,進而提升實單交易的信心。那到底該如何評估策略是否適合我們呢?

讀完本篇文,您將學會...

  • 熟悉衡量策略績效的方法:報酬率、勝率、賺賠比、獲利因子
  • 實作當沖策略的績效回測

如何衡量策略績效

衡量策略績效的方法有許多,通常會關心策略的「獲利」、「風險」、「交易週期」等數據,本篇文章將介紹獲利評估部分,包含:報酬率、勝率、賺賠比、獲利因子等基礎衡量策略的指標,並依序說明。

報酬率

獲利是投資人最直接的評估面向,「報酬率」通常是第一個被檢視的指標,為一筆交易中所得到的損益和投入的本金相除得出的結果,其公式如下:

報酬率=所得淨利投入本金報酬率 = \frac {所得淨利}{投入本金}

報酬率可以幫助我們了解策略在一段固定時間產生獲利的效率為何,當需要比較其他不同週期、不同策略的報酬率時,我們會將其年化,方便檢視策略結果。但不論是報酬率或是年化報酬率都只能反應「開始」和「結束」兩個時間點資金淨值成長幅度,我們無法了解資金在其中變化的過程。舉例來說:

小婷使用了一個策略在過去三年中將本金從 100 萬變成 300 萬,報酬率 200%,十分優秀吧? 但我們看了資金變化的紀錄發現,第一年她就賺了 1000 萬,然後後兩年賠了 700 萬,也就是獲利回吐了 70%,那我們還會覺得這個策略是好的嗎?

由這個情境我們可以知道,報酬率無法完全反映出策略的好壞,必須搭配其他指標一起評估,才能確保策略的可行性!

勝率

勝率可以表現出一個交易策略在每次交易時獲利的機率為何,其公式如下:

勝率=獲利次數總交易次數勝率 = \frac {獲利次數}{總交易次數}

我們設想一個情境,如果有一個策略宣稱「當沖勝率 90%」,那這個策略應該很棒吧?

每天買每天賺,十次只輸一次呢! 但萬一這十次交易中,前九次都贏了 1 萬元、最後一次輸 20 萬,總虧損是 11 萬元。 由此情境可以發現,高勝率不代表高報酬,更無法透過單一指標反應策略好壞!

賺賠比(賠率)

由上一個例子可以發現勝率不是一個絕對重要的指標,我們也可以觀察賺賠比,也就是賠率,其公式如下:

賺賠比=交易平均獲利|交易平均虧損|賺賠比 = \frac {交易平均獲利}{|交易平均虧損|}

假設有一個策略賺賠比是 5,就代表如果有虧損的情況發生,將平均虧損的值作為 1 個單位,有獲利的情況產生時,平均可以賺 5 個單位。但我們發現,此邏輯沒有考量到虧損、獲利的「次數」;假設獲利的次數很少,虧損的次數很多,看似較高的賺賠比,實際上的報酬卻是虧損的。

舉一組賺賠比為 5 的損益為例: -100, -100, -100, -100, 500, -100, -100, -100, -100, -100

最後結算發現損益金額虧損 400 元 ,由此可知,即使是高賺賠比,也未必是個可以賺錢的好策略,但策略結果為高賺賠比同時勝率也較高時,會是一個相當不錯的策略。

我們可以從中了解,勝率與賺賠比有著互補的關係:

  • 當勝率較高(> 60%)時,若賺賠比為 1 左右,高機率會產生不錯的策略
  • 當勝率較低(< 40%)時,需要有高賺賠比 (> 3) ,才有機會產生不錯的策略

因此,將賺賠比與上一小節的勝率一起搭配,能夠更容易評估策略好壞!

獲利因子

獲利因子是評估策略品質非常重要的指標!分子是損益紀錄中獲利的總和;分母則是虧損的總和(取絕對值)。可以把它想成「如果我今天賠了一塊錢,我可以賺回多少錢!」,通常獲利因子越高越好,公式如下:

獲利因子=獲利總和|虧損總和|獲利因子 = \frac {獲利總和}{|虧損總和|}

以這個損益紀錄做為舉例: -10, 20, -5, 30, -10, 20, -5, -5, -10, 20

  • 勝率:40% = (4/10)
  • 平均賺:22.5 = (20+30+20+20)/4
  • 平均賠:7.5 = (10+5+10+5+5+10)/6
  • 賺賠比:3 = 22.5/7.5
  • 獲利因子:2 = (20+30+20+20)/(10+5+10+5+5+10)

獲利因子通常越高越理想,以上述為例,即使勝率不到一半但賺賠比有 3 且獲利因子達到 2,這就代表每輸 1 元,就會賺回 2 元。經由這個例子可以發現,低勝率也可能有高獲利因子;因此獲利因子是能夠反應策略品質的重要指標之一!

實作策略績效 - 以開盤買收盤賣為例

還記得上週 當沖策略 - 開盤買收盤賣 的範例嗎? 我們現在就透過富果提供的歷史股價資料 Candles API 來回測結果如何吧!

資料準備

在回測之前,我們需要先載入相關套件以及輸入行情 API Token,方便後續程式碼的運行!

我們延續上週的範例,選擇長榮 (2603.tw) 這檔標的,回測時間為 2022 年 8 月的所有交易日,程式碼如下:

# 載入相關套件
from fugle_marketdata import RestClient
import numpy as np

# 設定相關參數
symbol = "2603"
start_date = "2022-08-01" # 選擇資料起始日期
end_date = "2022-08-31" # 選擇資料結束日期

# 透過自己的行情 API key 取得歷史資料
client = RestClient(api_key = 'INPUT_YOUR_API_KEY')
stock = client.stock

# 取得歷史資料
history_options = {"symbol": symbol, "from": start_date, "to": end_date, "timeframe":"D"}
historical_data = stock.historical.candles(**history_options)

績效指標計算

取得歷史資料後,我們在每個交易日以開盤價買進一張並於收盤價賣出進行回測,指標計算已考量交易成本,程式碼如下:

# 損益金額  = 計算開盤買收盤賣的價差 * 1張
profit_loss = list(map(lambda x:round((x['close']-x['open'])*1000), historical_data['data']))

# 以手續費 2.8 折、交易稅減半來計算
trade_fee = 0.001425*0.28
trade_tax = 0.003/2

# 交易成本
trade_cost = list(map(lambda x:round((x['close']+x['open'])*1000*trade_fee+(x['close'])*1000*trade_tax),historical_data['data']))

# 所得淨利 = 損益金額 - 交易成本
profit_loss_record = (np.array(profit_loss)-np.array(trade_cost)).tolist()

# 投入本金
buy_cost = list(map(lambda x:round((x['open'])*1000), historical_data['data']))

我們透過上述的程式碼找到「所得淨利」以及「投入本金」後,即可計算出每筆交易的報酬率囉!

# 記錄每筆報酬率(已考量交易成本)
return_record = (np.array(profit_loss_record) / np.array(buy_cost)).tolist()
# 將報酬率簡化為小數點第四位內
return_record = list(map(lambda x:round(x*100,2),return_record))
print(return_record)

Response Example

# 每筆交易的報酬率
[1.03, -0.34, -0.34, -1.08, -0.12, -3.38, 0.3, -1.58, -0.94, -0.33, 0.08, -2.15, -3.15, 0.25, -2.13, -1.19, 3.72, 2.62, 2.88, 0.63, -1.5, -2.02, 0.5]

上述結果是每筆交易日期由新到舊排序的報酬率。計算完報酬率後,我們接著透過「所得淨利」來計算「勝率」、「賺賠比」、「獲利因子」!

# 勝率
# 先篩選損益大於 0 的次數
profit_list = list(filter(lambda x : x > 0, profit_loss_record))
# 勝率 = 損益大於 0 的次數 / 交易總數
win_rate = len(profit_list) / len(profit_loss_record)
print("勝率:",win_rate)

# 賺賠比
# 篩選損益小於 0 的結果
loss_list = list(filter(lambda x : x <= 0, profit_loss_record))
# 賺賠比 = 平均賺 / 平均賠
odds = (sum(profit_list) /len(profit_list)) / abs(sum(loss_list)/len(loss_list))
print("賺賠比:",odds)

# 獲利因子
# 獲利因子 = 賺總和 / 賠總和
profit_factor = sum(profit_list) / abs(sum(loss_list))
print("獲利因子",profit_factor)

Response Example

# 長榮(2603.tw)回測結果
勝率:39.13 %
賺賠比:0.91
獲利因子:0.59

若以長榮這檔股票來說,勝率 < 50%、賺賠比 < 1、獲利因子 < 1,很顯然此策略還有很大的優化空間!但千萬別灰心,研發一個好的當沖策略本來就不是太容易,我們換一檔最近 關鍵報告 研究的標的 - M31 (6643.tw) 試試:

Response Example

# M31 (6643.tw)回測結果
# 每筆交易的報酬率
[8.25, 0.68, 3.94, -4.28, 3.27, -1.74, -1.14, -2.89, -3.8, 3.2, 2.79, -2.87, 5.46, 10.38, 6.79, 1.26, 4.41, 0.16, 0.57, -1.23, -2.98, -1.22, -2.15]

勝率:56.52 %
賺賠比:1.56
獲利因子:2.03

從 Response Example 發現, M31 這檔股票近期相當適合使用此策略,我們也可以從中了解單一策略難以適用於所有標的,因此後續課程也會帶大家學習如何精進策略的部分,您也可以動手試試您手上庫存的個股或嘗試其他交易策略,回測看看結果如何!

結語

本週課程我們學習到策略評估指標的計算方法、意義、盲點,可以發現衡量策略會根據不同風險屬性的交易者而產生不同的衡量基準:

  • 若您是個能夠承受一兩次大賺但無數次小賠的交易者,那就不太需要參考勝率,可以將重心聚焦在獲利因子上。
  • 若您希望每筆交易盡量都能獲利時,那高勝率且賺賠比為 1 左右的策略,就相當適合您!

未來的課程我們也將圍繞在優化指標的方法及嘗試更多不同的策略,讀者可將策略中使用的指標視為一個一個積木,或許將不同指標堆疊在一起產生出的訊號會比只使用一種更加穩固!

下堂課,我們將帶大家認識市場上更多進階的衡量策略績效指標以及回測常見的波段交易策略,請大家持續鎖定,敬請期待!

若想了解更多評估績效的指標,也可參考 【關鍵報告】程式交易 Part 2:如何評估策略績效?