如何在 excel 和 google 工作表中动态计算 XIRR

how to calculate XIRR dynamically in excel and in google sheets

我正在尝试为我拥有的以下格式的数据计算 XIRR

    PurchaseDate    Script  No.ofunits  PurchNAVrate    NetAmount            ForXIRR    TotalReturn
    17/11/2014          A   2241            33              75000           -75000          96000
    8/1/2015            B   53              649             35000           -35000          43000
    14/1/2015           B   75              658             50000           -50000          61500
    14/10/2014          C   2319            32              75000           -75000          108000
    8/1/2015            D   318             109             35000           -35000          40000
    14/1/2015           D   450             110             50000           -50000          57000
    8/6/2015            D   175             114             20000           -20000          22000

我尝试了很多不同的排列和组合,但无法计算每个基金的 XIRR。有没有办法可以使用偏移量或搜索来做到这一点。 这是一个动态列表,它会根据买入或卖出的新基金不断变化

Values for Fund A should be around 14%  
Values for Fund B should be around 13%
Values for Fund C should be around 21%
Values for Fund D should be around 8%

更新 鉴于@xor-lx 提到的解决方案在 ms excel 但在 google 工作表中工作得很好,我现在已经根据 @kyle 的建议修改了我的数据结构,现在我可以计算 XIRR每个基金作为一个整体很容易。参考以下

PurchaseDate    Today       Script  No.ofunits  PurchNAVrate    NetAmount   ForXIRR TotalReturn     XIRR
17/11/14        31/08/2016  A       2241        33              75000       -75000  96000           "=XIRR(G2:H2,A2:B2)"
                            Total for above fund                                                    "=XIRR(G2:H3,A2:B3)"
8/1/2015        31/08/2016  B       53          649             35000       -35000  43000           "=XIRR(G4:H4,A4:B4)"
14/1/2015       31/08/2016  B       75          658             50000       -50000  61500           "=XIRR(G5:H5,A5:B5)"
                            Total for above fund                                                    "=XIRR(G4:H6,A4:B6)"
14 Oct 14       31/08/2016  C       2319        32              75000       -75000  108000          "=XIRR(G7:H7,A7:B7)"
                            Total for above fund                                                    "=XIRR(G7:H8,A7:B8)"
8 Jan 15        31/08/2016  D       318         109             35000       -35000  40000           "=XIRR(G9:H9,A9:B9)"
14 Jan 15       31/08/2016  D       450         110             50000       -50000  57000           "=XIRR(G10:H10,A10:B10)"
8/6/2015        31/08/2016  D       175         114             20000       -20000  22000           "=XIRR(G11:H11,A11:B11)"
                            Total for above fund                                                    "=XIRR(G9:H12,A9:B12)"

我会根据你的 table 假设日期是 A 列,基金(或 "Script")是 B 列,"ForXIRR" 是 F 列。下面将为你做:

{=XIRR(IF(B:B="A",F:F,0),IF(B:B="A",A:A,0))}

确保使用 Shift + Ctrl + Enter 输入它,因为它是一个数组公式。

注意:以上将为 "A" 计算,但将公式的该部分替换为任何其他基金,或使用单元格引用为其他基金计算。

编辑:

我意识到上面的方法只适用于序列中的第一个字母,请使用下面的方法,然后再次将 "B" 调整为您需要的任何值。这将适用于任何出现的字母。此外,调整所有范围以满足您的需要,我只做了行 1:10 用于测试目的。下面调整范围的开始,因此它始终是输入的基金的第一个值(即 "A"、"B"、"C")以允许计算。如果不进行此更改,除非它是列表中的第一个("A" 在 OP 示例中),否则上面的内容将始终以零开头,并且 XIRR 仅使用负数作为第一个值进行计算。

=XIRR(IF(OFFSET($B:$B,MATCH("B",$B:$B,0)-1,0,ROWS($B:$B)-MATCH("B",$B:$B,0)+1,1)="B",OFFSET($F:$F,MATCH("B",$B:$B,0)-1,0,ROWS($B:$B)-MATCH("B",$B:$B,0)+1,1),0),IF(OFFSET($B:$B,MATCH("B",B1:B10,0)-1,0,ROWS($B:$B)-MATCH("B",$B:$B,0)+1,1)="B",OFFSET($A:$A,MATCH("B",$B:$B,0)-1,0,ROWS($B:$B)-MATCH("B",$B:$B,0)+1,1),0))

假设您的 table 在 A1:G8 中(第 1 行中有 headers),并且您选择的基金,例如"B",在J2,数组公式**:

=XIRR(INDEX(F:G,N(IF(1,MODE.MULT(IF(B:B=J2,{1,1}*ROW(B:B))))),N(IF(1,{1,2}))),CHOOSE({1,2},INDEX(A:A,N(IF(1,MODE.MULT(IF(B:B=J2,{1,1}*ROW(B:B)))))),TODAY()))

向下复制以给出 J3J4 等基金的类似结果

与涉及 OFFSET 的 set-ups 相比,我更喜欢这个;它不仅更简洁(因此更有效率),而且更重要的是,non-volatile.

感兴趣的可以看这里:

https://excelxor.com/2016/02/16/criteria-with-statistical-functions-growth-linest-logest-trend/

此致

**数组公式的输入方式与 'standard' 公式不同。您不是只按 ENTER,而是先按住 CTRL 和 SHIFT,然后再按 ENTER。如果操作正确,您会注意到 Excel 在公式周围放置了大括号 {}(但不要尝试自己手动插入)。

XIRR 需要两个参数数组——值和日期(带有可选的第三个 "guess" 参数)。要尝试将来自购买日期、总计 returns、购买金额和 "today's dates" 数量的非连续范围的数组拼接在一起,对于 Excel 公式来说将是一个相当大的挑战。因此,我提供了一个用 VBA.

编写的用户定义函数

该函数的参数是基金或脚本 (sFund) 和您的数据 table 范围,如上例所示。

正如您在其中一条评论中所建议的,我使用 TODAY 作为对应于 Total Return 列的日期。如果不是这种情况,则很容易更改。

另外请注意,我没有使用 "forXIRR" 列,而只是使用了 NetAmount 列的负数。如果删除 forXIRR 列,则需要将引用更改为 .TotalReturn

我创建了一个自定义 Class 以使事情更容易理解。

插入 Class 模块后,必须重命名 cFUND

Class 模块

Option Explicit
'Rename cFUND

Private pFund As String

Private pPurchDt As Date
Private pPurchDts As Collection

Private pPurchAmt As Double
Private pPurchAmts As Collection

Private pTotalReturn As Double
Private pTotalReturns As Collection

Public Property Get Fund() As String
    Fund = pFund
End Property
Public Property Let Fund(Value As String)
    pFund = Value
End Property

Public Property Get PurchDt() As Date
    PurchDt = pPurchDt
End Property
Public Property Let PurchDt(Value As Date)
    pPurchDt = Value
End Property
Public Function ADDPurchDt(Value As Date)
    pPurchDts.Add Value
End Function
Public Property Get PurchDts() As Collection
    Set PurchDts = pPurchDts
End Property

Public Property Get PurchAmt() As Double
    PurchAmt = pPurchAmt
End Property
Public Property Let PurchAmt(Value As Double)
    pPurchAmt = Value
End Property
Public Function ADDPurchAmt(Value As Double)
    pPurchAmts.Add Value
End Function
Public Property Get PurchAmts() As Collection
    Set PurchAmts = pPurchAmts
End Property

Public Property Get TotalReturn() As Double
    TotalReturn = pTotalReturn
End Property
Public Property Let TotalReturn(Value As Double)
    pTotalReturn = Value
End Property
Public Function ADDTotalReturn(Value As Double)
    pTotalReturns.Add Value
End Function
Public Property Get TotalReturns() As Collection
    Set TotalReturns = pTotalReturns
End Property

Public Function CalcXIRR()
    Dim v, d, w
    Dim I As Long
    With Me
        ReDim d(.PurchDts.Count * 2 - 1)
        ReDim v(UBound(d))

        I = 0
        For Each w In .PurchAmts
            v(I) = w
            I = I + 1
        Next w
        For Each w In .TotalReturns
            v(I) = w
            I = I + 1
        Next w

        I = 0
        For Each w In .PurchDts
            d(I) = w
            I = I + 1
        Next w
        Do Until I > UBound(d)
            d(I) = Date
            I = I + 1
        Loop
    End With

    CalcXIRR = WorksheetFunction.XIRR(v, d)
End Function
Private Sub Class_Initialize()
    Set pPurchDts = New Collection
    Set pPurchAmts = New Collection
    Set pTotalReturns = New Collection
End Sub

常规模块

Option Explicit
Function fundXIRR(sFund As String, rTable As Range) As Double
    Dim vSrc As Variant
    Dim cF As cFUND
    Dim I As Long

vSrc = rTable

Set cF = New cFUND
For I = 2 To UBound(vSrc, 1)
    If vSrc(I, 2) = sFund Then
        With cF
            .PurchDt = vSrc(I, 1)
            .ADDPurchDt .PurchDt
            .Fund = vSrc(I, 2)
            .PurchAmt = -vSrc(I, 5)
            .ADDPurchAmt .PurchAmt
            .TotalReturn = vSrc(I, 7)
            .ADDTotalReturn .TotalReturn
        End With
    End If
Next I

fundXIRR = cF.CalcXIRR

End Function

根据上面的数据,BXIRR 将计算为:

XIRR({-35000;-50000;43000;61500},{"1/8/2015";"1/14/2015";"8/29/2016";"8/29/2016"}

以下是您上述数据的结果: