[量化投資基本功] 如何回測最大跌幅? 在Python中要怎麼快速計算?

在做策略回測時,除了考量報酬外,風險的考量更是重要。有些策略可以為我們帶來很高的報酬,但過程中同時也有可能要忍受巨大的風險,比方說過程中虧損超過70%,或是連續1年以上都是不賺錢的等等。因此,在採用一個策略前,了解策略的風險屬性是非常重要的。我們必須選擇適合自己風險忍受程度的策略,才能夠享受到策略最後甜美的果實,不然有很大的機會,策略的精神尚未顯現,我們已經因虧損超過我們的忍受程度而停損出場,最後與甜美的果實擦肩而過。話不多說,本支影片簡單介紹最大跌幅的計算方式,並分享如何在Python中有效率的實作最大跌幅回測。

什麼是最大跌幅?

最大跌幅(Max Drawdown)只的是投資組合(或標的)從最高點跌落至最低點的下跌百分比。在一張走勢圖上,我們可以透過肉眼快速地找出高低點,進而計算最大跌幅。然而在程式中,如果直接取區間最大跟區間最小,可能會出現最高值出現在最小值後面的問題,表示這段期間標的是在成長而非下跌。為了解決這樣的問題,我們便會透過累積報酬的轉換來計算最大跌幅。

$$MDD=\frac{1+r}{cummax(1+r)}-1$$

其中,r指的是累計報酬率。

如何在Python中計算最大跌幅?

整體而言,我們依照上述公式寫進python裡,並包裝成function的形式以方便後續的使用。詳細過程解說歡迎參考影片,這邊我們直接來看到最後的程式碼部分。

首先,第一步,我們一樣要引入pandas模組。

import pandas as pd

接下來,在計算最大跌幅的部分,我們會利用累積報酬率來找到最高點,並用上述公式找到最大跌幅,最後再透過反函數找到事件發生的時間點,以計算最後的事件發生期間。(顯現時縮排好像會跑掉,def下面記得都要縮排唷! 亦歡迎直接下載程式檔取用。)

def MDD(df):
dr=df.pct_change(1)
r=dr.add(1).cumprod()
dd=r.div(r.cummax()).sub(1)
mdd=dd.min()
end=dd.idxmin()
start=r.loc[:end[0]].idxmax()
days=end-start
return mdd[0], start[0], end[0], days[0]

今天,我們認識了回測投資組合中考量最大跌幅的重要性,並學會如何在Python中進行實作。下次進行投資策略回測時,別忘了把最大跌幅加進去唷!

程式檔案,歡迎下載Github

Share

4 thoughts on “[量化投資基本功] 如何回測最大跌幅? 在Python中要怎麼快速計算?

  1. 想請教如果我想要產出前五大跌幅要怎麼寫,我目前只想到可以用rank排出跌幅順序,但是start,end,day就不知道怎麼處理!因為我是業餘自學量化,每次看你的部落格都受益良多!

    1. 好問題! 如果是想要看過去歷史下跌的幅度,建議可以直接將時間做切割,比方說每年,再套入這個最大跌幅的function,就可以看到歷史每年度的最大跌幅了。

      1. 應該說,我目前遇到兩個問題
        1.我在做份年度最大跌幅時,有時候跌幅會跨年度,這時Starr,end,date就會失真。
        2.可能發生同年大回檔多次,所以想說有沒有辦法計算前幾大跌幅。
        不知道Pylnvest有沒有好的建議~

        1. 理解理解~
          若要看過去幾個重大跌幅,一般業界會採用事件回測法,因為大部分的重大損失都發生在系統性風險時,因此可以由定義事件發生的起迄日期,帶入這個function,即可得到過去不同事件下的最大跌幅。
          而對於一般策略回測來說,我們主要關注的都是過去最大的跌幅。而如果是要看某個策略過去的前幾大跌幅,在這樣的框架下,基本上是很難達成的,因為大型跌幅往往遠超過小型跌幅,因此會偵測不出來。這個用肉眼來看反而相對很簡單的多! 所以說,建議可以先繪製累積損益圖,看看那些區段有較大的跌幅,然後依照事件回測法的方式自訂起訖日,帶入function來看到這些區間的最大跌幅,最後再排序,就可以完成了!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *