|
本帖最后由 d11yushi 于 2019-5-16 20:53 编辑
楼主你好,已经帮你编了一个自定义函数,代码如下:- Function MaxDrawdown(InvestReturn) As Double Dim max As Double, mdd As Double
- Dim InvestArr(), MaxArr(), MinArr(), Temp(), Drawdown(), Drawdown2D()
- Dim i As Long, j As Long, k As Long, BM As Long, l As Long, i1 As Long, x As Long, y As Long
- Dim step%
- ' Dim Peak As String, Through As String, MDDvalue As String
- ' Peak = "M3"
- ' Through = "M4"
- ' MDDvalue = "M5"
- InvestArr = Range2Arr(InvestReturn)
- j = 1
- k = 0
- step = 1
- ReDim Preserve MaxArr(1 To 2, 1 To 1)
- MaxArr(1, 1) = InvestArr(1)
- MaxArr(2, 1) = 1
- For i = 2 To UBound(InvestArr) - 1
- If InvestArr(i + step) <= InvestArr(i) And InvestArr(i - step) <= InvestArr(i) Then
- j = j + 1
- ReDim Preserve MaxArr(1 To 2, 1 To j)
- MaxArr(1, j) = InvestArr(i)
- MaxArr(2, j) = i
- End If
- If InvestArr(i) <= InvestArr(i + step) And InvestArr(i) <= InvestArr(i - step) Then
- k = k + 1
- ReDim Preserve MinArr(1 To 2, 1 To k)
- MinArr(1, k) = InvestArr(i)
- MinArr(2, k) = i
- End If
- Next i
- ReDim Preserve MinArr(1 To 2, 1 To k + 1)
- MinArr(1, k + 1) = InvestArr(i)
- MinArr(2, k + 1) = i
- Temp = MaxArr
- ReDim MaxArr(1 To j, 1 To 2)
- MaxArr = Application.WorksheetFunction.Transpose(Temp)
- Temp = MinArr
- ReDim MinArr(1 To k, 1 To 2)
- MinArr = Application.WorksheetFunction.Transpose(Temp)
- ReDim Drawdown(1 To UBound(MaxArr), 1 To UBound(MinArr), 1 To 3)
- For i1 = 1 To j
- BM = BenchMark(MinArr, MaxArr(i1, 2)) '获取样本序列中MaxArr(i1,1)之后的波谷横坐标
- For l = BM To k + 1
- Drawdown(i1, l, 1) = (MaxArr(i1, 1) - MinArr(l, 1)) / MaxArr(i1, 1) '获取最大回撤
- Drawdown(i1, l, 2) = MaxArr(i1, 2) '获取波峰的横坐标
- Drawdown(i1, l, 3) = MinArr(l, 2) '获取波谷的横坐标
- Next l
- Next i1
- ReDim Drawdown2D(1 To UBound(Drawdown, 1), 1 To UBound(Drawdown, 2))
- For i = 1 To UBound(Drawdown, 1)
- For j = 1 To UBound(Drawdown, 2)
- Drawdown2D(i, j) = Drawdown(i, j, 1)
- Next j
- Next i
- mdd = Application.WorksheetFunction.max(Drawdown2D)
- ' ReDim Temp(1 To 2)
- ' Temp = SearchCoordinates(mdd, Drawdown2D)
- ' x = Drawdown(Temp(1), Temp(2), 2)
- ' y = Drawdown(Temp(1), Temp(2), 3)
- ' MsgBox "最大回撤的两个坐标分别是:" & x & "和" & y & "。"
- ' Range(Peak).Value = x
- ' Range(Through).Value = y
- ' Range(MDDvalue).Value = mdd
- MaxDrawdown = mdd
- End Function
- Function Range2Arr(Range1) As Variant
- Dim arr()
- Dim i As Long, n As Long
- n = Range1.Rows.Count
- ReDim arr(1 To n)
- For i = 1 To n
- arr(i) = Range1(i)
- Next i
- Range2Arr = arr
- End Function
- Function BenchMark(arr, bm0) As Long
- Dim i As Long
- For i = 1 To UBound(arr)
- If arr(i, 2) > bm0 Then
- Exit For
- End If
- Next i
- BenchMark = i
- End Function
- Function MaxDrawdown2(InvestReturn) As Double
- Dim max As Double, mdd As Double
- Dim InvestArr(), MaxArr(), MinArr(), Temp(), Drawdown(), Drawdown2D()
- Dim i As Long, j As Long, k As Long, BM As Long, l As Long, i1 As Long, x As Long, y As Long
- Dim step%
- Dim Peak As String, Through As String, MDDvalue As String
- Peak = "M3"
- Through = "M4"
- MDDvalue = "M5"
- InvestArr = InvestReturn
- j = 1
- k = 0
- step = 1
- ReDim Preserve MaxArr(1 To 2, 1 To 1)
- MaxArr(1, 1) = InvestArr(1, 1)
- MaxArr(2, 1) = 1
- For i = 2 To UBound(InvestArr) - 1
- If InvestArr(i + step, 1) <= InvestArr(i, 1) And InvestArr(i - step, 1) <= InvestArr(i, 1) Then
- j = j + 1
- ReDim Preserve MaxArr(1 To 2, 1 To j)
- MaxArr(1, j) = InvestArr(i, 1)
- MaxArr(2, j) = i
- End If
- If InvestArr(i, 1) <= InvestArr(i + step, 1) And InvestArr(i, 1) <= InvestArr(i - step, 1) Then
- k = k + 1
- ReDim Preserve MinArr(1 To 2, 1 To k)
- MinArr(1, k) = InvestArr(i, 1)
- MinArr(2, k) = i
- End If
- Next i
- ReDim Preserve MinArr(1 To 2, 1 To k + 1)
- MinArr(1, k + 1) = InvestArr(i, 1)
- MinArr(2, k + 1) = i
- Temp = MaxArr
- ReDim MaxArr(1 To j, 1 To 2)
- MaxArr = Application.WorksheetFunction.Transpose(Temp)
- Temp = MinArr
- ReDim MinArr(1 To k, 1 To 2)
- MinArr = Application.WorksheetFunction.Transpose(Temp)
- ReDim Drawdown(1 To UBound(MaxArr), 1 To UBound(MinArr), 1 To 3)
- For i1 = 1 To j
- BM = BenchMark(MinArr, MaxArr(i1, 2)) '获取样本序列中MaxArr(i1,1)之后的波谷横坐标
- For l = BM To k + 1
- Drawdown(i1, l, 1) = (MaxArr(i1, 1) - MinArr(l, 1)) / MaxArr(i1, 1) '获取最大回撤
- Drawdown(i1, l, 2) = MaxArr(i1, 2) '获取波峰的横坐标
- Drawdown(i1, l, 3) = MinArr(l, 2) '获取波谷的横坐标
- Next l
- Next i1
- ReDim Drawdown2D(1 To UBound(Drawdown, 1), 1 To UBound(Drawdown, 2))
- For i = 1 To UBound(Drawdown, 1)
- For j = 1 To UBound(Drawdown, 2)
- Drawdown2D(i, j) = Drawdown(i, j, 1)
- Next j
- Next i
- mdd = Application.WorksheetFunction.max(Drawdown2D)
- ReDim Temp(1 To 2)
- Temp = SearchCoordinates(mdd, Drawdown2D)
- x = Drawdown(Temp(1), Temp(2), 2)
- y = Drawdown(Temp(1), Temp(2), 3)
- ' MsgBox "最大回撤的两个坐标分别是:" & x & "和" & y & "。"
- Range(Peak).Value = x
- Range(Through).Value = y
- Range(MDDvalue).Value = mdd
- MaxDrawdown2 = mdd
- End Function
- Sub mdd()
- Dim Period As String, arr()
- Dim Peak As String, Through As String, MDDvalue As String
- Peak = "M3"
- Through = "M4"
- MDDvalue = "M5"
- Period = Range("M2").Value
- arr = Range(Period)
- Call MaxDrawdown2(arr)
- ActiveSheet.Shapes.AddChart2(227, xlLine).Select
- ActiveChart.SetSourceData Source:=Range(Period)
- ActiveChart.SetElement (msoElementDataLabelTop)
- End Sub
- Function SearchCoordinates(Goal As Double, arr) As Variant
- Dim i As Long, j As Long
- Dim brr(1 To 2)
- ' ReDim SearchCoordinates(1 To 2)
- For i = 1 To UBound(arr, 1)
- For j = 1 To UBound(arr, 2)
- If arr(i, j) = Goal Then
- GoTo 100
- End If
- Next j
- Next i
- MsgBox "未找到"
- Exit Function
- 100:
- brr(1) = i
- brr(2) = j
- SearchCoordinates = brr
- End Function
复制代码
此外,为楼主编了个宏,可以定位最大回撤波峰、波谷的坐标,并且绘制折线图,便于检验。详见附件。
|
|