Question

Has anyone developed a financial function XNPV? I am looking for code that will calculate this value. I am not looking to call excel to calculate the value.

Any help would be great, thanks

Was it helpful?

Solution

I believe this is the correct implementation in c#:

public double XNPV(decimal[] receipts,DateTime[] dates, double dRate, DateTime issueDate, decimal cf, int x)
{
    double sum;

    for(int i =0;i<dates.Length;i++)
    {
        TimeSpan ts =  dates[i].Subtract(issuedate);
        sum +=receipts[i] / ((1 + dRate / cf) ^ ((ts.TotalDays / 360) * cf));
    }
    return sum;
}

and this is the equivalent in VB:

Public Function XNPV(ByVal Receipts() As Decimal, ByVal Dates() As Date, ByVal dRate As Double, ByVal IssueDate As Date, ByVal CF As Decimal, ByVal x As Integer) As Double

Dim i As Integer
Dim sum As Double

For i = 0 To UBound(Dates)
    sum = sum + Receipts(i) / ((1 + dRate / CF) ^ ((DateDiff / 360) * CF))

XNPV = sum
End Function

OTHER TIPS

I adapted the code above and included an example of how to call it. It should be easy to adapt to use a variable discount rate instead of .1

Public Function XNPV(ByVal Receipts() As Decimal, ByVal Dates() As Date, ByVal dRate As Double, ByVal StartDate As Date) As Double

    Dim i As Integer = 0
    Dim dXNPV As Double = 0
    Dim dXRate As Double = 1 + dRate
    Dim dDayOfCF As Long = 0
    Dim dAdj As Double = 0
    Dim dResult As Double = 0

    For i = 0 To UBound(Dates)
        dDayOfCF = (DateDiff(DateInterval.Day, StartDate, Dates(i)))
        dAdj = (dDayOfCF / 365)
        dXNPV = Receipts(i) / (dXRate ^ dAdj)
        dResult += dXNPV
    Next
    XNPV = dResult
End Function

Private Sub SimpleButton2_Click(sender As System.Object, e As System.EventArgs) Handles SimpleButton2.Click
    Dim tblReceipts(2) As Decimal
    Dim tblDates(2) As DateTime
    Dim dtStartDate As DateTime = "1/1/13"
    Dim XNPVResult As Decimal = 0

    tblReceipts(0) = -100000
    tblReceipts(1) = 500000
    tblReceipts(2) = 2000000

    tblDates(0) = "1/1/13"
    tblDates(1) = "1/7/13"
    tblDates(2) = "1/1/15"
    'xCF = 1 + DateDiff(DateInterval.Day, dtIssueDate, tblDates(2))
    XNPVResult = XNPV(tblReceipts, tblDates, 0.1, dtStartDate)
    MsgBox(XNPVResult)
End Sub

Returns value same as Excels' XNPV (double-checked)

    public static double XNPV(double rate, List<xnpvFlow> Cashflows, DateTime? StartDate = null)
    {
        if (Cashflows == null || Cashflows.Count == 0) return 0;
        if(StartDate == null)
        {
            StartDate = (from xnpvFlow flow in Cashflows select flow.FlowDate).Min();
        }
        double _xnpv = 0;
        foreach(xnpvFlow flow in Cashflows)
        {
            _xnpv += (double)flow.FlowAmount / Math.Pow((1 + rate), (double)(flow.FlowDate - (DateTime)StartDate).Days/365);
        }
        return _xnpv;
    }
    public class xnpvFlow
    {
        public xnpvFlow(DateTime _FlowDate, decimal _flowAmount)
        {
            this.FlowAmount = _flowAmount;
            this.FlowDate = _FlowDate;
        }
        public DateTime FlowDate;
        public decimal FlowAmount;
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top