[mono-vb] Implementation of Financial vb module
Rob.Tillie@Student.tUL.EDU
Rob.Tillie@Student.tUL.EDU
Sat, 12 Jun 2004 13:17:52 +0200
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: text/plain
Hello all,
Because of the complexity of FileSystem, I implemented Financial first
together with unit tests, to get a feel for Mono and its formatting.
It is largely copied from the MainSoft code, but I corrected a few
implementation differences with MS.NET.
Everything works like on MS.NET now.
Because this is my first contribution, I would love to get some feedback on
what I have done wrong, especially concerning formatting.
I used the tab character now for tabs, couldn't figure out if I was supposed
to use tab character or spaces.
The formatting of FileSystem is pretty screwed up, could someone fix this or
could I post a formatting patch?
Greetz,
-- Rob.
------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: application/octet-stream;
name="FinancialTest.cs"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="FinancialTest.cs"
// FinancialTest.cs - NUnit Test Cases for vb module Financial
// (class Microsoft.VisualBasic.Financial)
//
// Rob Tillie (Rob@flep-tech.nl)
//
// (C) 2004 Rob Tillie
//=20
using NUnit.Framework;
using System;
using Microsoft.VisualBasic;
namespace MonoTests.Microsoft.VisualBasic
{
[TestFixture]
public class FinancialTest : Assertion {
=09
[SetUp]
public void GetReady() {}
[TearDown]
public void Clean() {}
=09
=09
// -- DDB Tests
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestDDBArg1()
{
Financial.DDB (-1, 1, 1, 1, 1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestDDBArg2()
{
Financial.DDB (1, -1, 1, 1, 1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestDDBArg3()
{
Financial.DDB (1, 1, 0, 1, 1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestDDBArg4()
{
Financial.DDB (1, 1, 1, 1, 0);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestDDBArg5()
{
// Period has to be > Life
Financial.DDB (1, 1, 1, 2, 1);
}
=09
[Test]
public void TestDDB()
{
double ddb =3D Financial.DDB (1000, 50, 10, 5, 3);
AssertEquals ("#DDB01", 1425, ddb, 0);
=09
// TODO: How should we test an optional parameter in C#?
ddb =3D Financial.DDB (1000, 50, 10, 5, 2);
AssertEquals ("#DDB02", 950, ddb, 0);
}
=09
[Test]
public void TestFV()
{
double d =3D Financial.FV (10, 5, 3, 7, DueDate.BegOfPeriod);
AssertEquals ("#FV01", -1658822, d);
=09
d =3D Financial.FV (10, 5, 3, 7, DueDate.EndOfPeriod);
AssertEquals ("#FV02", -1175672, d);
=09
d =3D Financial.FV (0, 5, 3, 7, DueDate.BegOfPeriod);
AssertEquals ("#FV03", -22, d);
=09
d =3D Financial.FV(0, 1, 1, 1, DueDate.BegOfPeriod);
AssertEquals ("#FV04", -2, d);
=09
d =3D Financial.FV (0, 0, 0, 0, DueDate.BegOfPeriod);
AssertEquals ("#FV05", 0, d);
=09
d =3D Financial.FV (-3, -5, -6, -4, DueDate.BegOfPeriod);
AssertEquals ("#FV06", -4.25, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestIPmtArgs1()
{
Financial.IPmt (3, 6, 4, 2, 2, DueDate.BegOfPeriod);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestIPmtArgs2()
{
Financial.IPmt (3, 0, 4, 2, 2, DueDate.BegOfPeriod);
}
=09
[Test]
public void TestIPmt()
{
double d =3D Financial.IPmt (10, 2, 3, 7, 9, DueDate.BegOfPeriod);
AssertEquals ("#IPmt01", -6.25427204374573, d);
=09
d =3D Financial.IPmt (10, 4, 4, 7, 4, DueDate.EndOfPeriod);
AssertEquals ("#IPmt02", -60.0068306011053, d);
=09
d =3D Financial.IPmt (0, 5, 7, 7, 2, DueDate.BegOfPeriod);
AssertEquals ("#IPmt03", 0, d);
=09
d =3D Financial.IPmt (-5, 5, 7, -7, -2, DueDate.BegOfPeriod);
AssertEquals ("#IPmt04", 8.92508391821792, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestPmtArgs()
{
Financial.Pmt (1, 0, 1, 1, DueDate.BegOfPeriod);
}
=09
[Test]
public void TestPmt()
{
double d =3D Financial.Pmt (2, 5, 2, 3, DueDate.BegOfPeriod);
AssertEquals ("#Pmt01", -1.34710743801653, d);
=09
d =3D Financial.Pmt (2, 5, 2, 3, DueDate.EndOfPeriod);
AssertEquals ("#Pmt02", -4.04132231404959, d);
=09
d =3D Financial.Pmt (-3, -5, -3, -4, DueDate.BegOfPeriod);
AssertEquals ("#Pmt03", -5.68181818181818, d);
=09
d =3D Financial.Pmt (-3, -5, -3, -4, DueDate.EndOfPeriod);
AssertEquals ("#Pmt04", 11.3636363636364, d);
=09
d =3D Financial.Pmt (0, 1, 0, 0, DueDate.BegOfPeriod);
AssertEquals ("#Pmt05", 0, d);
=09
d =3D Financial.Pmt (0, 1, 0, 0, DueDate.EndOfPeriod);
AssertEquals ("#Pmt06", 0, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestSLNArgs()
{
Financial.SLN (0, 0, 0);
} =09
=09
[Test]
public void TestSLN()
{
double d =3D Financial.SLN (0, 0, 1);
AssertEquals ("#SLN01", 0, d);
=20
d =3D Financial.SLN (45, 32, 345);
AssertEquals ("#SLN02", 0.0376811594202899, d, 0.0001);
=20
d =3D Financial.SLN (-54, -4, -76);
AssertEquals ("#SLN03", 0.657894736842105, d, 0.001);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestSYDArgs1()
{
Financial.SYD (1, 1, 1, -1);
}=09
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestSYDArgs2()
{
Financial.SYD (1, -1, 1, 1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestSYDArgs3()
{
Financial.SYD (1, 1, 1, 2);
}
=09
[Test]
public void TestSYD()
{
double d =3D Financial.SYD (23, 34, 26, 21);
AssertEquals ("#SYD01", -0.188034188034188, d);
d =3D Financial.SYD (0, 1, 1, 1);
AssertEquals ("#SYD02", -1, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestIRRArgs1()
{
double [] arr =3D new double [0];
Financial.IRR (ref arr, 0.1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestIRRArgs2()
{
double [] arr =3D new double [] {134};
Financial.IRR (ref arr, 0.1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestIRRArgs3()
{
// -0.99 as Guess throws an exception on MS.NET, -0.98 doesn't
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.IRR (ref arr, -0.99);
}
=09
[Test]
public void TestIRR()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.IRR (ref arr, 0.1);
AssertEquals ("#IRR01", 0.177435884422527, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestNPVArgs1()
{
double [] arr =3D null;
double d =3D Financial.NPV (0.0625, ref arr);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestNPVArgs2()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.NPV (-1, ref arr);
}
=09
[Test]
public void TestNPV()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.NPV (0.0625, ref arr);=09
AssertEquals ("#NPV01", 19312.5702095352, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestNPerArgs1()
{
double d =3D Financial.NPer (-1, 2, 2, 2, DueDate.BegOfPeriod);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestNPerArgs2()
{
double d =3D Financial.NPer (0, 0, 2, 2, DueDate.BegOfPeriod);
}
=09
[Test]
public void TestNPer()
{
double d =3D Financial.NPer (3, 4, 6, 2, DueDate.BegOfPeriod);
AssertEquals ("#NPer01", -0.882767373181489, d, 0.001);
=09
d =3D Financial.NPer (1, -4, -6, -2, DueDate.EndOfPeriod);
AssertEquals ("#NPer02", -2.32192809488736, d, 0.001);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestMIRRArgs1()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.MIRR(ref arr, -1, 1);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestMIRRArgs2()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.MIRR(ref arr, 1, -1);
}
=09
[Test]
public void TestMIRR()
{
double [] arr =3D new double [] {-70000, 22000, 25000, 28000, =
31000};
double d =3D Financial.MIRR (ref arr, 1, 1);
AssertEquals ("#MIRR01", 0.509044845533018, d);
=09
arr =3D new double [] {-70000, 22000, 25000, 28000, 31000};
d =3D Financial.MIRR (ref arr, 5, 5);
AssertEquals ("#MIRR02", 2.02366041666348, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestPPmtArgs1()
{
double d =3D Financial.PPmt (2, -1, 1, 1, 1, DueDate.EndOfPeriod);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestPPmtArgs2()
{
double d =3D Financial.PPmt (1, 2, 1, 1, 1, DueDate.BegOfPeriod);
}
=09
[Test]
public void TestPPmt()
{
double d =3D Financial.PPmt (10, 2, 3, 7, 9, DueDate.BegOfPeriod);
AssertEquals("#PPmt01", -0.120300751879702, d);
=09
d =3D Financial.PPmt (10, 4, 4, 7, 4, DueDate.EndOfPeriod);
AssertEquals("#PPmt02", -10.0006830600969, d);
=09
d =3D Financial.PPmt (0, 5, 7, 7, 2, DueDate.BegOfPeriod);
AssertEquals("#PPmt03", -1.28571428571429, d);
=09
d =3D Financial.PPmt (-5, 5, 7, -7, -2, DueDate.BegOfPeriod);
AssertEquals("#PPmt04", -0.175770521818777, d);
}
=09
[Test]
public void TestPV()
{
double d =3D Financial.PV (1, 1, 1, 1, DueDate.BegOfPeriod);
AssertEquals ("#PV01", -1.5, d);
=09
d =3D Financial.PV (1, 1, 1, 1, DueDate.EndOfPeriod);
AssertEquals ("#PV02", -1, d);
}
=09
[Test]
[ExpectedException(typeof(ArgumentException))]
public void TestRateArgs1()
{
double d =3D Financial.Rate (-1, 1, 1, 1, DueDate.BegOfPeriod, 1);
}
=09
[Test]
public void TestRate()
{
double d =3D Financial.Rate (1, 1, 1, 1, DueDate.BegOfPeriod, 0.1);
AssertEquals("#Rate01", -1.5, d, 0.01);
=09
d =3D Financial.Rate (1, -1, -1, -1, DueDate.BegOfPeriod, 0.1);
AssertEquals("#Rate02", -1.50000000000001, d, 0.01);
=09
d =3D Financial.Rate (1, 2, 12, 10, DueDate.BegOfPeriod, 0.5);
AssertEquals("#Rate03", -1.71428571428571, d);
}
}
}
------_=_NextPart_000_01C4506E.E73FF6D0
Content-Type: application/octet-stream;
name="Financial.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="Financial.patch"
Index: Financial.cs
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: =
/mono/mcs/class/Microsoft.VisualBasic/Microsoft.VisualBasic/Financial.cs=
,v
retrieving revision 1.4
diff -u -r1.4 Financial.cs
--- Financial.cs 31 May 2004 05:35:21 -0000 1.4
+++ Financial.cs 11 Jun 2004 20:43:57 -0000
@@ -3,14 +3,38 @@
//
// Author:
// Chris J Breisch (cjbreisch@altavista.net)=20
+// Rob Tillie (Rob@flep-tech.nl)
//
// (C) 2002 Chris J Breisch
-//
+// (C) 2004 Rob Tillie
+// (C) 2002-2003 MainSoft
+ /*
+ * Copyright (c) 2002-2003 Mainsoft Corporation.
+ *
+ * Permission is hereby granted, free of charge, to any person =
obtaining a
+ * copy of this software and associated documentation files (the =
"Software"),
+ * to deal in the Software without restriction, including without =
limitation
+ * the rights to use, copy, modify, merge, publish, distribute, =
sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom =
the
+ * Software is furnished to do so, subject to the following =
conditions:
+ *=20
+ * The above copyright notice and this permission notice shall be =
included in
+ * all copies or substantial portions of the Software.
+ *=20
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, =
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF =
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT =
SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR =
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, =
ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR =
OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
=20
using System;
using Microsoft.VisualBasic.CompilerServices;
=20
-namespace Microsoft.VisualBasic=20
+namespace Microsoft.VisualBasic=20
+
{
[StandardModule]=20
sealed public class Financial {
@@ -19,32 +43,331 @@
private Financial() {} // prevent public default constructor
// Properties
// Methods
- [MonoTODO]
- public static System.Double DDB (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(2)] System.Double Factor) { throw =
new NotImplementedException (); }
- [MonoTODO]
- public static System.Double FV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double IPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double IRR (ref System.Double[] ValueArray, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess) { throw =
new NotImplementedException (); }
- [MonoTODO]
- public static System.Double MIRR (ref System.Double[] ValueArray, =
System.Double FinanceRate, System.Double ReinvestRate) { throw new =
NotImplementedException (); }
- [MonoTODO]
- public static System.Double NPer (System.Double Rate, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double NPV (System.Double Rate, ref =
System.Double[] ValueArray) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double Pmt (System.Double Rate, System.Double =
NPer, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double PPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double PV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double Rate (System.Double NPer, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess) { throw =
new NotImplementedException (); }
- [MonoTODO]
- public static System.Double SLN (System.Double Cost, System.Double =
Salvage, System.Double Life) { throw new NotImplementedException (); }
- [MonoTODO]
- public static System.Double SYD (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period) { throw new =
NotImplementedException (); }
+ public static System.Double DDB (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(2)] System.Double Factor)=20
+ {=20
+ // LAMESPEC: MSDN says Life and Factor only throws exception if < =
0, but Implementation throws exception if <=3D 0
+ if (Cost < 0
+ || Salvage < 0
+ || Life <=3D 0
+ || Period < 0
+ || Factor <=3D 0
+ || Period > Life)
+ throw new ArgumentException ("Invalid argument value");
+ =09
+ return (((Cost - Salvage) * Factor) / Life) * Period;
+ }
+ =09
+ public static System.Double FV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+ {=20
+ Pmt =3D -Pmt;
+ PV =3D -PV;
+ double currentRate =3D Math.Pow (Rate + 1, NPer);
+ double sum =3D 0;
+ =09
+ if (Rate !=3D 0)
+ sum =3D Pmt * ((currentRate - 1) / Rate);
+ else
+ sum =3D Pmt * NPer;
+=09
+ if (Due =3D=3D DueDate.BegOfPeriod)
+ sum *=3D (1 + Rate);
+ =09
+ return PV * currentRate + sum;
+ }
+ =09
+ public static System.Double IPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)
+ {=20
+ double totalFutureVal;
+ double totalPaymentValue;
+ double numberOfPeriods;
+ =20
+ if ((Per <=3D 0) || (Per >=3D (NPer + 1)))
+ throw new ArgumentException ("Argument 'Per' is not =
valid");
+ if ((Due =3D=3D DueDate.BegOfPeriod) && (Per =3D=3D 1))
+ return 0;
+ =20
+ totalPaymentValue =3D Pmt (Rate, NPer, PV, FV, Due);
+ if (Due =3D=3D DueDate.BegOfPeriod)
+ PV =3D (PV + totalPaymentValue);
+ =09
+ numberOfPeriods =3D Per - ((int)Due) - 1;
+ totalFutureVal =3D
+ Financial.FV (Rate, numberOfPeriods, totalPaymentValue, PV, =
DueDate.EndOfPeriod);
+ =20
+ return (totalFutureVal * Rate);
+ }
+ =09
+ public static System.Double IRR (ref System.Double[] ValueArray, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess)=20
+ {=20
+ double origPV, updatedPV, updateGuess, tmp;
+ double rateDiff =3D 0.0;
+ double pvDiff =3D 0.0;
+ int length;
+ =09
+ // MS.NET 2.0 docs say that Guess may not be <=3D -1
+ if (Guess <=3D -1) =20
+ throw new ArgumentException ("Argument 'Guess' is =
invalid"); =20
+ try {
+ length =3D ValueArray.GetLength(0);
+ }
+ catch {
+ throw new ArgumentException ("Argument 'ValueArray' is =
invalid");
+ }
+ if (length < 2) =20
+ throw new ArgumentException ("Argument 'ValueArray' is =
invalid"); =20
+ =09
+ origPV =3D NPV (Guess, ref ValueArray);
+ updateGuess =3D (origPV > 0) ? Guess + 0.00001 : Guess - =
0.00001; =20
+ =20
+ if (updateGuess < -1)
+ throw new ArgumentException ("Argument 'ValueArray:Rate' =
is invalid");
+ =09
+ rateDiff =3D updateGuess - Guess; =20
+ updatedPV =3D NPV (updateGuess, ref ValueArray);
+ pvDiff =3D updatedPV - origPV;
+ for (int i =3D 0; i < 20; i++) {
+ Guess =3D (updateGuess > Guess) ? (Guess - 0.00001) : (Guess + =
0.00001);
+ origPV =3D NPV (Guess, ref ValueArray);
+ rateDiff =3D updateGuess - Guess;
+ pvDiff =3D updatedPV - origPV; =20
+ if (pvDiff =3D=3D 0)
+ throw new ArgumentException ("Argument is invalid.");
+ Guess =3D updateGuess - (rateDiff * updatedPV / pvDiff);
+ if (Guess < -1)
+ Guess =3D -1;
+ origPV =3D NPV (Guess, ref ValueArray);
+ if ((Math.Abs (origPV) < 0.0000001) && (Math.Abs (rateDiff) < =
0.00001))
+ return Guess;
+ =09
+ tmp =3D Guess;
+ Guess =3D updateGuess;
+ updateGuess =3D tmp;
+ tmp =3D origPV;
+ origPV =3D updatedPV;
+ updatedPV =3D tmp;
+ }
+ double origPVAbs =3D Math.Abs (origPV);
+ double updatedPVAbs =3D Math.Abs (updatedPV);
+ if ((origPVAbs < 0.0000001) && (updatedPVAbs < 0.0000001))
+ return (origPVAbs < updatedPVAbs) ? Guess : updateGuess;
+ else if (origPVAbs < 0.0000001)
+ return Guess;
+ else if (updatedPVAbs < 0.0000001)
+ return updateGuess;
+ else =20
+ throw new ArgumentException("Argument is invalid.");
+ }
+ =09
+ public static System.Double MIRR (ref System.Double[] ValueArray, =
System.Double FinanceRate, System.Double ReinvestRate)
+ {=20
+ double [] array =3D ValueArray;
+ double loansVal =3D 0;
+ double assetsVal =3D 0;
+ double currentLoanRate =3D 1;
+ double currentAssetsRate =3D 1;
+ double totalInterestRate =3D 0;
+ int arrayLength =3D 0;
+ if (array.Rank !=3D 1)
+ throw new ArgumentException ("Rank of 'ValueArray' must be 1.");
+ else if (FinanceRate =3D=3D -1)
+ throw new ArgumentException ("Argument 'FinanceRate' is =
invalid.");
+ else if (ReinvestRate =3D=3D -1)
+ throw new ArgumentException ("Argument 'ReinvestRate' is =
invalid.");
+ =09
+ arrayLength =3D array.Length;
+ if (arrayLength < 2)
+ throw new ArgumentException ("Argument 'ValueArray' is invalid.");
+ =09
+ for (int i =3D 0; i < arrayLength; i++) {
+ currentLoanRate *=3D (1 + FinanceRate);
+ currentAssetsRate *=3D (1 + ReinvestRate);
+ if (array [i] < 0)
+ loansVal +=3D (array [i] / currentLoanRate);
+ else if (array [i] > 0)
+ assetsVal +=3D (array [i] / currentAssetsRate);
+ }
+ =09
+ if (loansVal =3D=3D 0)
+ throw new DivideByZeroException ("Division by zero has =
occurred.");
+ =09
+ totalInterestRate =3D
+ ((-assetsVal * Math.Pow (ReinvestRate + 1, arrayLength))
+ / (loansVal * (FinanceRate + 1)));
+ if (totalInterestRate < 0)
+ throw new ArgumentException ("Argument is invalid.");
+ =09
+ return (Math.Pow (totalInterestRate, 1 / (double) (arrayLength - =
1))) - 1;
+ }
+ =09
+ public static System.Double NPer (System.Double Rate, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+ {=20
+ double totalIncomeFromFlow, sumOfPvAndPayment, =
currentValueOfPvAndPayment;
+ if (Rate =3D=3D 0 && Pmt =3D=3D 0)
+ throw new ArgumentException ("Argument 'Pmt' is invalid.");
+ else if (Rate =3D=3D 0)
+ return (- (PV + FV) / Pmt);
+ // MainSoft had Rate < -1, but MS.NET 2.0 Doc says Rate should not =
be <=3D -1
+ else if (Rate <=3D -1)
+ throw new ArgumentException("Argument 'Rate' is invalid.");
+ totalIncomeFromFlow =3D (Pmt / Rate);
+ if (Due =3D=3D DueDate.BegOfPeriod)
+ totalIncomeFromFlow *=3D (1 + Rate);
+ =09
+ sumOfPvAndPayment =3D (-FV + totalIncomeFromFlow);
+ currentValueOfPvAndPayment =3D (PV + totalIncomeFromFlow);
+ if ((sumOfPvAndPayment < 0) && (currentValueOfPvAndPayment < 0)) {
+ sumOfPvAndPayment =3D -sumOfPvAndPayment;
+ currentValueOfPvAndPayment =3D -currentValueOfPvAndPayment;
+ }
+ else if ((sumOfPvAndPayment <=3D 0) || (currentValueOfPvAndPayment =
< 0))
+ throw new ArgumentException ("Cannot calculate NPer");
+ =09
+ double totalInterestRate =3D sumOfPvAndPayment / =
currentValueOfPvAndPayment;
+ return Math.Log (totalInterestRate) / Math.Log (Rate + 1);
+ }
+ =09
+ public static System.Double NPV (System.Double Rate, ref =
System.Double[] ValueArray)=20
+ {=20
+ if (ValueArray =3D=3D null)
+ throw new ArgumentException ("Argument 'ValueArray' is invalid.");
+ =09
+ double [] arr =3D ValueArray;
+ if (arr.Rank !=3D 1)
+ throw new ArgumentException ("Argument 'ValueArray' is invalid, =
rank must be 1.");
+ if (Rate =3D=3D -1)
+ throw new ArgumentException ("Argument 'Rate' is invalid");
+ int length =3D arr.Length;
+ if (length < 0)
+ throw new ArgumentException ("Argument 'ValueArray' is invalid");
+ =09
+ double currentValue =3D 0;
+ double currentRate =3D 1;
+ double sum =3D 0;
+ for (int index =3D 0; index < length; index++) {
+ currentValue =3D arr [index];
+ currentRate *=3D (1 + Rate);
+ sum +=3D (currentValue / currentRate);
+ }
+ return sum;
+ }
+ =09
+ public static System.Double Pmt (System.Double Rate, System.Double =
NPer, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+ {=20
+ PV =3D -PV;
+ FV =3D -FV;
+ if (NPer =3D=3D 0)
+ throw new ArgumentException ("Argument 'NPer' is =
invalid.");
+ =09
+ double totalFutureVal =3D 0;
+ double geometricSum =3D 0;=20
+ if (Rate =3D=3D 0) {
+ totalFutureVal =3D FV + PV;
+ geometricSum =3D NPer;
+ }
+ else if (Due =3D=3D DueDate.EndOfPeriod) {
+ double totalRate =3D Math.Pow (Rate + 1, NPer);
+ totalFutureVal =3D FV + PV * totalRate;
+ geometricSum =3D (totalRate - 1) / Rate;
+ }
+ else if (Due =3D=3D DueDate.BegOfPeriod) {
+ double totalRate =3D Math.Pow (Rate + 1, NPer);
+ totalFutureVal =3D FV + PV * totalRate;
+ geometricSum =3D ((1 + Rate) * (totalRate - 1)) / Rate; =20
+ }
+ return (totalFutureVal) / geometricSum;=20
+ }
+ =09
+ public static System.Double PPmt (System.Double Rate, System.Double =
Per, System.Double NPer, System.Double PV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+ {=20
+ if ((Per <=3D 0) || (Per >=3D (NPer + 1)))
+ throw new ArgumentException("Argument 'Per' is invalid.");
+ double interestPayment =3D IPmt (Rate, Per, NPer, PV, FV, Due);
+ double totalPayment =3D Pmt (Rate, NPer, PV, FV, Due);
+ return (totalPayment - interestPayment);
+ }
+ =09
+ public static System.Double PV (System.Double Rate, System.Double =
NPer, System.Double Pmt, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due)=20
+ {=20
+ Pmt =3D -Pmt;
+ FV =3D -FV;
+ double currentRate =3D 1;
+ double sum =3D 0;
+ for (int index =3D 1; index <=3D NPer; index++) {
+ currentRate *=3D (1 + Rate);
+ sum +=3D (Pmt / currentRate);
+ }
+ =09
+ if (Due =3D=3D DueDate.BegOfPeriod)
+ sum *=3D (1 + Rate);
+ return sum + FV / currentRate; =20
+ }
+ =09
+ public static System.Double Rate (System.Double NPer, System.Double =
Pmt, System.Double PV, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] System.Double FV, =
[System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0)] Microsoft.VisualBasic.DueDate =
Due, [System.Runtime.InteropServices.Optional] =
[System.ComponentModel.DefaultValue(0.1)] System.Double Guess)
+ {=20
+ double updatedGuess, tmp, origFv, updatedFv;
+ double rateDiff =3D 0.0;
+ double fvDiff =3D 0.0;
+ =09
+ if (NPer < 0)
+ throw new ArgumentException ("Invalid argument 'NPer', must be =
greater then zero.");
+ origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+ updatedGuess =3D (origFv > 0) ? (Guess / 2) : (Guess * 2);
+ rateDiff =3D updatedGuess - Guess;
+ updatedFv =3D -Financial.FV (updatedGuess, NPer, Pmt, PV, Due) + =
FV;
+ fvDiff =3D updatedFv - origFv;
+ for (int i =3D 0; i < 20; i++) {
+ Guess +=3D (updatedGuess > Guess) ? -0.00001 : 0.00001;
+ origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+ rateDiff =3D updatedGuess - Guess;
+ fvDiff =3D updatedFv - origFv;
+ if (fvDiff =3D=3D 0)
+ throw new ArgumentException ("Division by zero.");
+ Guess =3D updatedGuess - (rateDiff * updatedFv / fvDiff);
+ origFv =3D -Financial.FV (Guess, NPer, Pmt, PV, Due) + FV;
+ if (Math.Abs (origFv) < 0.0000001)
+ return Guess;
+ tmp =3D Guess;
+ Guess =3D updatedGuess;
+ updatedGuess =3D tmp;
+ tmp =3D origFv;
+ origFv =3D updatedFv;
+ updatedFv =3D tmp;
+ }
+ double origFVAbs =3D Math.Abs (origFv);
+ double updatedFVAbs =3D Math.Abs (updatedFv);
+ if ((origFVAbs < 0.0000001) && (updatedFVAbs < 0.0000001))
+ return (origFVAbs < updatedFVAbs) ? Guess : updatedGuess;
+ else if (origFVAbs < 0.0000001)
+ return Guess;
+ else if (updatedFVAbs < 0.0000001)
+ return updatedGuess;
+ else
+ throw new ArgumentException ("Cannot calculate Rate.");=20
+ }
+ =09
+ public static System.Double SLN (System.Double Cost, System.Double =
Salvage, System.Double Life)
+ {=20
+ if (Life =3D=3D 0)
+ throw new ArgumentException ("Argument 'Life' is =
invalid");
+ =09
+ return (Cost - Salvage) / Life;
+ }
+ =09
+ public static System.Double SYD (System.Double Cost, System.Double =
Salvage, System.Double Life, System.Double Period)=20
+ {=20
+ if (Period < 0)
+ throw new ArgumentException ("Argument 'Period' is =
invalid");
+ else if (Salvage < 0)
+ throw new ArgumentException ("Argument 'Salvage' is =
invalid");
+ else if (Period > Life)
+ throw new ArgumentException ("Invalid argument, Period =
> Life");
+ =20
+ double depreciation =3D (Cost - Salvage);
+ double sumOfDigits =3D (Life + 1) * Life / 2;
+ double currentPeriodPart =3D Life + 1 - Period ;=20
+ =09
+ return depreciation * currentPeriodPart / sumOfDigits;
+ }
// Events
};
}
------_=_NextPart_000_01C4506E.E73FF6D0--