Forum Discussion
Rolling XIRR Calculation
- 9 years ago
Hi v-ljerr-msft,
Thank you very much for your help!
The formula works great, although I have made a few tweaks to include:
- a terminal value (from the [equity repayment/(investment) on sale] column) to be calculated at the end of each period and calculated in the XIRR calc (i.e. if I sold the investment now, what would my XIRR be), and
- a check to ensure that there is at least one positive cashflow (another requirement of the XIRR formula along with the first periof being negative).
see my code as follows fyi....
ROLLING XIRR = VAR countpos = CALCULATE( COUNT('INVESTMENT RETURNS'[totalcashflow]), FILTER(ALL('INVESTMENT RETURNS'), 'INVESTMENT RETURNS'[totalcashflow]>0 && EARLIER ('INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index] && 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) VAR minIndex = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[Index] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) VAR firstValue = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD (excl. sale)] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) && 'INVESTMENT RETURNS'[Index] = minIndex ) ) RETURN IF ( 'INVESTMENT RETURNS'[Index] > minIndex && firstValue < 0 && countpos >= 1 , XIRR ( UNION( SUMMARIZE( FILTER(ALL ( 'INVESTMENT RETURNS' ), EARLIER ('INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index] && 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] )) ,'INVESTMENT RETURNS'[Index], "DATE1",MAX('INVESTMENT RETURNS'[DATE]), "CASHFLOW",MAX('INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD (excl. sale)]) ), SUMMARIZE( FILTER(ALL ( 'INVESTMENT RETURNS' ), EARLIER ('INVESTMENT RETURNS'[Index] ) = 'INVESTMENT RETURNS'[Index] ), 'INVESTMENT RETURNS'[Index], "DATE1",MAX('INVESTMENT RETURNS'[DATE]), "CASHFLOW",MAX('INVESTMENT RETURNS'[EQUITY REPAYMENT/(INVESTMENT) ON SALE]) ) ), [CASHFLOW], [DATE1] ) )Thanks again for all your help. Much appreciated.
MJ
Hey there!
Thanks, the code worked great. However, I just realised that I will actually need another filter on the table for company name, as there will be multiple companies that an XIRR will need to be calculated for. See updated data below. Could you still help me?
| Name | Index | FREE CASHFLOW FOR PERIOD | DATE |
| Company A | 42 | -7,531,293.00 | 30/06/2013 |
| Company A | 43 | 859,425.00 | 30/06/2014 |
| Company A | 44 | 901,305.00 | 30/06/2015 |
| Company A | 45 | 951,189.00 | 30/06/2016 |
| Company A | 46 | 7,742,641.00 | 30/06/2017 |
| Company A | 47 | 1,498,289.00 | 30/06/2018 |
| Company B | 48 | -8401918 | 30/06/2014 |
| Company B | 49 | 949747 | 30/06/2015 |
| Company B | 50 | 942388 | 30/06/2016 |
| Company B | 51 | 943756 | 30/06/2017 |
| Company B | 52 | 1049089 | 30/06/2018 |
Hi mjfigg,
Sure! The formula below should work in this new scenario. :smileyhappy:
ROLLING IRR =
VAR minIndex =
CALCULATE (
MIN ( 'INVESTMENT RETURNS'[Index] ),
FILTER (
ALL ( 'INVESTMENT RETURNS' ),
'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] )
)
)
RETURN
IF (
'INVESTMENT RETURNS'[Index] > minIndex,
CALCULATE (
XIRR (
'INVESTMENT RETURNS',
'INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD],
'INVESTMENT RETURNS'[DATE]
),
FILTER (
'INVESTMENT RETURNS',
EARLIER ( 'INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index]
&& 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] )
)
)
)
Regards
- mjfigg9 years agoFrequent Visitor
Hi v-ljerr-msft,
Apologies to keep on bothering you... however I cannot seem to get your formula to work on my actual data set. I have copied this below so we can see if you have any issues either. Thanks so much.
MJ
Name FINANCIAL YEAR DISTRIBUTIONS EQUITYtemp EQUITY BALANCE ROI NET ASSET VALUE ON SALE Index ACTUAL EQUITY MOVEMENTS EQUITY REPAYMENT/(INVESTMENT) ON SALE FREE CASHFLOW FOR PERIOD DATE Company A 2012 220,000.00 9629572 9,629,572 2.30% 8,544,134.21 0 -9,629,572 -1,085,438 -9,409,572 30/06/2012 Company A 2013 1,309,598.00 9,629,572 13.60% 8,279,143.54 1 0 -1,350,428 1,309,598 30/06/2013 Company A 2014 1,748,073.00 9,629,572 18.20% 8,250,943.49 2 0 -1,378,629 1,748,073 30/06/2014 Company A 2015 2,865,402.00 ############ 11,450,400 25.00% 25,753,143.93 3 -1,820,828 14,302,744 1,044,574 30/06/2015 Company A 2016 3,627,947.00 9,629,572 37.70% 26,247,601.43 4 1,820,828 16,618,029 5,448,775 30/06/2016 Company A 2017 3,326,656.00 9,629,572 34.50% 65,531,598.87 5 0 55,902,027 3,326,656 30/06/2017 Company A 2018 4,336,035.00 9,629,572 45.00% 65,463,524.70 6 0 55,833,953 4,336,035 30/06/2018 Company A 2019 4,618,150.00 9,629,572 48.00% 65,473,159.83 7 0 55,843,588 4,618,150 30/06/2019 Company A 2020 5,275,995.00 9,629,572 54.80% 65,471,361.84 8 0 55,841,790 5,275,995 30/06/2020 Company A 2021 5,323,785.00 9,629,572 55.30% 65,471,209.61 9 0 55,841,638 5,323,785 30/06/2021 Company A 2022 4,949,933.00 9,629,572 51.40% 65,471,339.58 10 0 55,841,768 4,949,933 30/06/2022 Company B 2011 - 19/02/9566 2,800,000 0.00% 2,668,345.50 11 -2,800,000 -131,655 -2,800,000 30/06/2011 Company B 2012 266,730.00 2,800,000 9.50% 2,646,045.08 12 0 -153,955 266,730 30/06/2012 Company B 2013 267,272.00 2,800,000 9.50% 2,846,349.35 13 0 46,349 267,272 30/06/2013 Company B 2014 301,676.00 2,800,000 10.80% 2,868,516.18 14 0 68,516 301,676 30/06/2014 Company B 2015 320,209.00 2,800,000 11.40% 3,711,889.98 15 0 911,890 320,209 30/06/2015 Company B 2016 422,263.00 2,800,000 15.10% 3,724,043.17 16 0 924,043 422,263 30/06/2016 Company B 2017 441,096.00 2,800,000 15.80% 3,691,333.20 17 0 891,333 441,096 30/06/2017 Company B 2018 261,140.00 2800000 2,800,000 9.30% 5,966,728.35 18 0 3,166,728 261,140 30/06/2018 Company B 2019 189,619.00 2800000 2,800,000 6.80% 6,156,209.63 19 0 3,356,210 189,619 30/06/2019 Company B 2020 20,898.00 2800000 2,800,000 0.70% 6,306,108.41 20 0 3,506,108 20,898 30/06/2020 Company B 2022 500,000.00 2800000 2,800,000 17.90% 6,242,283.16 21 0 3,442,283 500,000 30/06/2022 Company C 2011 659,079.00 100 100 659079.00% 9,331,458.81 22 -100 9,331,359 658,979 30/06/2011 Company C 2012 540,616.00 100 540616.00% 9,277,099.06 23 0 9,276,999 540,616 30/06/2012 Company C 2013 742,004.00 159820 159,820 464.30% 9,258,662.81 24 -159,720 9,098,843 582,284 30/06/2013 Company C 2014 845,771.00 100 845771.00% 9,265,568.34 25 159,720 9,265,468 1,005,491 30/06/2014 Company C 2015 1,073,678.00 100 1073678.00% 11,398,818.49 26 0 11,398,718 1,073,678 30/06/2015 Company C 2016 1,121,581.00 100 1121581.00% 11,434,088.18 27 0 11,433,988 1,121,581 30/06/2016 Company C 2017 1,316,995.00 100 1316995.00% 11,394,817.59 28 0 11,394,718 1,316,995 30/06/2017 Company C 2018 1,557,526.00 100 100 1557526.50% 11,396,678.18 29 0 11,396,578 1,557,526 30/06/2018 Company D 2013 68,707.00 7600000 7,600,000 0.90% 7,292,257.58 42 -7,600,000 -307,742 -7,531,293 30/06/2013 Company D 2014 859,425.00 7,600,000 11.30% 7,345,734.20 43 0 -254,266 859,425 30/06/2014 Company D 2015 901,305.00 7,600,000 11.90% 7,375,734.52 44 0 -224,265 901,305 30/06/2015 Company D 2016 951,189.00 7,600,000 12.50% 9,588,364.56 45 0 1,988,365 951,189 30/06/2016 Company D 2017 4,428,202.00 4285561 4,285,561 103.30% 3,997,812.72 46 3,314,439 -287,748 7,742,641 30/06/2017 Company D 2018 1,498,289.00 4,285,561 35.00% 0 47 0 -4,285,561 1,498,289 30/06/2018 Company E 2014 273,082.00 8675000 8,675,000 3.10% 8,398,839.45 48 -8,675,000 -276,161 -8,401,918 30/06/2014 Company E 2015 949,747.00 8,675,000 10.90% 8,642,316.32 49 0 -32,684 949,747 30/06/2015 Company E 2016 942,388.00 8,675,000 10.90% 8,846,768.55 50 0 171,769 942,388 30/06/2016 Company E 2017 943,756.00 8,675,000 10.90% 9,870,640.33 51 0 1,195,640 943,756 30/06/2017 Company E 2018 1,049,089.00 8675000 8,675,000 12.10% 12,085,226.38 52 0 3,410,226 1,049,089 30/06/2018 Company E 2019 1,119,677.00 8675000 8,675,000 12.90% 11,969,884.17 53 0 3,294,884 1,119,677 30/06/2019 Company E 2020 625,193.00 8675000 8,675,000 7.20% 11,849,969.14 54 0 3,174,969 625,193 30/06/2020 Company E 2021 871,440.00 8675000 8,675,000 10.00% 11,702,695.72 55 0 3,027,696 871,440 30/06/2021 Company E 2022 1,069,488.00 8675000 8,675,000 12.30% 11,515,814.91 56 0 2,840,815 1,069,488 30/06/2022 Company F 2015 218,605.00 3736500 3,736,500 5.90% 4,251,481.98 57 -3,736,500 514,982 -3,517,895 30/06/2015 Company F 2016 160,000.00 3,736,500 4.30% 4,677,717.90 58 0 941,218 160,000 30/06/2016 Company F 2017 190,000.00 3,736,500 5.10% 4,840,240.82 59 0 1,103,741 190,000 30/06/2017 Company F 2018 - 3736500 3,736,500 0.00% 5,545,139.51 60 0 1,808,640 0 30/06/2018 Company F 2019 253,741.00 3736500 3,736,500 6.80% 5,544,110.50 61 0 1,807,610 253,741 30/06/2019 Company F 2020 578,817.00 3736500 3,736,500 15.50% 5,543,677.06 62 0 1,807,177 578,817 30/06/2020 Company F 2021 606,588.00 3736500 3,736,500 16.20% 5,543,616.03 63 0 1,807,116 606,588 30/06/2021 Company F 2022 640,160.00 3736500 3,736,500 17.10% 5,543,546.62 64 0 1,807,047 640,160 30/06/2022 - v-ljerr-msft9 years ago
Microsoft Employee
Hi mjfigg,
The value is calculated as the rate that satisfies the following function:
The series of cash flow values must contain at least one positive number and one negative number.
After I a few test, I find the issue is with your data of Company C(there are only positive numbers, but no nagative number).
So you may need to correct your data, or use the the formula below to make it work. :smileyhappy:
ROLLING IRR = VAR minIndex = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[Index] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) VAR firstValue = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) && 'INVESTMENT RETURNS'[Index] = minIndex ) ) RETURN IF ( 'INVESTMENT RETURNS'[Index] > minIndex && firstValue < 0, CALCULATE ( XIRR ( 'INVESTMENT RETURNS', 'INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD], 'INVESTMENT RETURNS'[DATE] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), EARLIER ( 'INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index] && 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) )Regards
- mjfigg9 years agoFrequent Visitor
Hi v-ljerr-msft,
Thank you very much for your help!
The formula works great, although I have made a few tweaks to include:
- a terminal value (from the [equity repayment/(investment) on sale] column) to be calculated at the end of each period and calculated in the XIRR calc (i.e. if I sold the investment now, what would my XIRR be), and
- a check to ensure that there is at least one positive cashflow (another requirement of the XIRR formula along with the first periof being negative).
see my code as follows fyi....
ROLLING XIRR = VAR countpos = CALCULATE( COUNT('INVESTMENT RETURNS'[totalcashflow]), FILTER(ALL('INVESTMENT RETURNS'), 'INVESTMENT RETURNS'[totalcashflow]>0 && EARLIER ('INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index] && 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) VAR minIndex = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[Index] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) ) ) VAR firstValue = CALCULATE ( MIN ( 'INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD (excl. sale)] ), FILTER ( ALL ( 'INVESTMENT RETURNS' ), 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] ) && 'INVESTMENT RETURNS'[Index] = minIndex ) ) RETURN IF ( 'INVESTMENT RETURNS'[Index] > minIndex && firstValue < 0 && countpos >= 1 , XIRR ( UNION( SUMMARIZE( FILTER(ALL ( 'INVESTMENT RETURNS' ), EARLIER ('INVESTMENT RETURNS'[Index] ) >= 'INVESTMENT RETURNS'[Index] && 'INVESTMENT RETURNS'[Name] = EARLIER ( 'INVESTMENT RETURNS'[Name] )) ,'INVESTMENT RETURNS'[Index], "DATE1",MAX('INVESTMENT RETURNS'[DATE]), "CASHFLOW",MAX('INVESTMENT RETURNS'[FREE CASHFLOW FOR PERIOD (excl. sale)]) ), SUMMARIZE( FILTER(ALL ( 'INVESTMENT RETURNS' ), EARLIER ('INVESTMENT RETURNS'[Index] ) = 'INVESTMENT RETURNS'[Index] ), 'INVESTMENT RETURNS'[Index], "DATE1",MAX('INVESTMENT RETURNS'[DATE]), "CASHFLOW",MAX('INVESTMENT RETURNS'[EQUITY REPAYMENT/(INVESTMENT) ON SALE]) ) ), [CASHFLOW], [DATE1] ) )Thanks again for all your help. Much appreciated.
MJ