2013年4月20日 星期六

EXCEL計算最大連續虧損

最近在上程式交易的課程,碰巧有遇到要使用EXCEL 計算「最大連續虧損」的情況
以前聽過朋友介紹過這個概念後也曾經想過要如何才能使用EXCEL Automate 這個問題,但發現實在比想像中難,最後也不了了之。

因為碰巧在另一本關於數據結構與演算法 (Data Structure and Algorithm Analysis) 的書中見到關於如何解決最大連續和 (Maximum Sequence Sum) 的問題,因此乾脆一不做二不休,將這個問題給徹底解決掉。

首先定義什麼是最大連續和問題:

定義序列:


定義連續和為:


求  中, 的最大值


換而言之

若一序列為



則其最大連續和為18,如下圖所示:


但是每次都要建立一個 n*n 的矩陣去計算這個問題實在是太浪費位置又沒有效率了,那到底有沒有方法可以只需要一個方程就能傳回一個列陣 (array) 中的最大連續和呢?

答案是有的,但看正確答案前先看一下錯的答案:

1. 貼一個在網上看到的答案:

=MAX(SUBTOTAL(9,OFFSET(A1,ROW(A1:A10001)-1,,-TEXT(
 FREQUENCY(ROW(A1:A10000),(A1:A10000*A2:A10001<=0)*
 ROW(A1:A10000)),"0;;1;"))))\
(Ctrl + Shift + Enter)

我小試了一下,發現陣列傳回的答案是15,而非18

原因是方程中的 A1:A10000*A2:A10001<=0 計算了當元素轉向時的資料(如-2 -> 3為一個轉向、1->-8為一個轉向),並將每個轉向視為一次斷點。而後使用subtotal 時則將每個轉向點至上一個轉向點之和相加,傳回 {-2, NA, NA, 10, -8, NA, NA, 15, -4, 5},再取最大值傳回15。

這個公式計算了在任何一次盈利前的累積虧損,但如果每次於虧損後都有一些盈利呢?

舉例而言,考慮這個情況:


資本累積圖





淨回報圖

使用上述公式算出來的最大連續虧損為 -10,大約是出現在第 34-38 個元素,連續虧損了三次 (-5,-3,-2)。然而,若從資本的最高點 14 到最低點 -35 來看,我整整虧損了49 點之多。

因此,該公式並非我所需要的公式。(而且當資料一多,其運算速度將會變得非常的慢)


2. 先將所有回報 (Profits) 相加得出資本累積

再輸入下列公式:

= MAX(資本累積) - MIN(資本累積)

資本累積圖



則公式傳回最高點減最低點的值。

然而,這個方法未考慮到最低點有可能出現在最高點之前,如圖所示:

資本累積圖

那麼算出來的答案就是最大連續回報而非最大連續虧損了。



*************************************************************************

那麼,要如何才能做到最大連續虧損的計算呢?

方法一:

假設回報數列在 Column A,那麼在Column B 輸入下列公式:

= $A$1................................................................................. (for B1)
= IF($B1+$A2 > 0, 0, $B1+$A2).........................................(for B2, 然後往下拉)

最後,在任意一個地方輸入:
= MIN(B:B)

即為最大連續虧損。

具體如圖所示:



或許有人覺得,要額外開一行出來太浪費位置了,有辦法可以再省位置一些來計算嗎?

方法二:

如果不想再開一行,那無法避免要使用到VBA了。

在模組一加入下方函數:


Function MAXDD(profit)

    Dim ThisSum, MaxSum
    Dim i As Long
    
    ThisSum = 0
    MaxSum = 0
    
    For i = 1 To profit.Rows.Count
    
        ThisSum = ThisSum + profit(i)
    
        If ThisSum <= MaxSum Then
            
           MaxSum = ThisSum
        
        ElseIf ThisSum >= 0 Then
        
           ThisSum = 0
        
        End If
    
    Next i
    
    MAXDD = MaxSum

End Function

然後使用 =MAXDD(指定範圍) 呼叫函數,如圖所示:



這樣一來就可以輕鬆計算最大連續虧損了。

除此以外,最大連續虧損周期可以下列公式計算:

Function MAXDD_P(profit)

    Dim ThisSum, MaxSum
    Dim i As Long
    Dim j As Long
    
    ThisSum = 0
    MaxSum = 0
    j = 0
    MaxP = 0
    
    For i = 1 To profit.Rows.Count
    
        ThisSum = ThisSum + profit(i)
        j = j + 1
    
        If ThisSum <= MaxSum Then
            
           MaxSum = ThisSum
           MaxP = j
        
        ElseIf ThisSum >= 0 Then
        
           ThisSum = 0
           j = 0
        
        End If
    
    Next i
    
    MAXDD_P = MaxP

End Function


然後使用 =MAXDD_P(指定範圍) 呼叫函數,得出最大連續虧損發生所需的周期。

3 則留言:

  1. 沒想到您的方法一, 可以僅用IF函數,短短幾行就計算出最大連續虧損, 勵害!

    回覆刪除