📄 stfin.pas
字号:
(* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is TurboPower SysTools
*
* The Initial Developer of the Original Code is
* TurboPower Software
*
* Portions created by the Initial Developer are Copyright (C) 1996-2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** *)
{*********************************************************}
{* SysTools: StFIN.pas 4.03 *}
{*********************************************************}
{* SysTools: Financial math functions modeled on *}
{* those in Excel *}
{*********************************************************}
{$I StDefine.inc}
unit StFIN;
interface
uses
Windows,
{$IFDEF UseMathUnit}
Math,
{$ELSE}
StMath,
{$ENDIF}
SysUtils,
StBase,
StConst,
StDate;
type
TStPaymentTime = (ptEndOfPeriod, ptStartOfPeriod);
TStFrequency = (fqAnnual, fqSemiAnnual, fqQuarterly, fqMonthly);
TStBasis = (BasisNASD, {US (NASD) 30/360}
BasisActAct, {Actual/actual}
BasisAct360, {Actual/360}
BasisAct365, {Actual/365}
BasisEur30360); {European 30/360}
TStDateArray = array[0..(StMaxBlockSize div SizeOf(TStDate))-1] of TStDate;
const
StDelta : Extended = 0.00001; {delta for difference equations}
StEpsilon : Extended = 0.00001; {epsilon for difference equations}
StMaxIterations : Integer = 100; {max attempts for convergence}
function AccruedInterestMaturity(Issue, Maturity : TStDate;
Rate, Par : Extended;
Basis : TStBasis) : Extended;
{-Returns the accrued interest for a security that pays interest at maturity}
function AccruedInterestPeriodic(Issue, Settlement, Maturity : TStDate;
Rate, Par : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Returns the accrued interest for a security that pays periodic interest}
function BondDuration(Settlement, Maturity : TStDate;
Rate, Yield : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Returns the Macauley duration for an assumed par value of $100}
function BondPrice(Settlement, Maturity : TStDate;
Rate, Yield, Redemption : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Returns the "clean" bond price per $100 face value of a security}
function CumulativeInterest(Rate : Extended;
NPeriods : Integer;
PV : Extended;
StartPeriod, EndPeriod : Integer;
Frequency : TStFrequency;
Timing : TStPaymentTime) : Extended;
{-Returns the cumulative interest paid on a loan in specified periods}
function CumulativePrincipal(Rate : Extended;
NPeriods : Integer;
PV : Extended;
StartPeriod, EndPeriod : Integer;
Frequency : TStFrequency;
Timing : TStPaymentTime) : Extended;
{-Returns the cumulative principal paid on a loan in specified periods}
function DayCount(Day1, Day2 : TStDate; Basis : TStBasis) : LongInt;
{-Returns the number of days from Day1 to Day2 according to day count basis}
function DecliningBalance(Cost, Salvage : Extended;
Life, Period, Month : Integer) : Extended;
{-Fixed rate declining balance depreciation}
function DiscountRate(Settlement, Maturity : TStDate;
Price, Redemption : Extended;
Basis : TStBasis) : Extended;
{-Returns the discount Rate for a security}
function DollarToDecimal(FracDollar : Extended;
Fraction : Integer) : Extended;
{-Converts a fractional dollar value to decimal dollar value}
function DollarToDecimalText(DecDollar : Extended) : string;
{-Converts a decimal dollar value into an English text string}
function DollarToFraction(DecDollar : Extended;
Fraction : Integer) : Extended;
{-Converts a decimal dollar value to fractional dollar value}
function DollarToFractionStr(FracDollar : Extended;
Fraction : Integer) : string;
{-Converts a fractional dollar value to number string}
function EffectiveInterestRate(NominalRate : Extended;
Frequency : TStFrequency) : Extended;
{-Converts nominal annual interest Rate to effective Rate}
function FutureValue(Rate : Extended;
NPeriods : Integer;
Pmt, PV : Extended;
Frequency : TStFrequency;
Timing: TStPaymentTime) : Extended;
{-Returns the future value of an annuity}
function FutureValueSchedule(Principal : Extended;
const Schedule : array of Double) : Extended;
function FutureValueSchedule16(Principal : Extended;
const Schedule; NRates : Integer) : Extended;
{-Returns the future value of investment with variable interest rates}
function InterestRate(NPeriods : Integer;
Pmt, PV, FV : Extended;
Frequency : TStFrequency;
Timing : TStPaymentTime;
Guess : Extended) : Extended;
{-Returns the interest Rate per period of an annuity}
function InternalRateOfReturn(const Values : array of Double;
Guess : Extended) : Extended;
function InternalRateOfReturn16(const Values; NValues : Integer;
Guess : Extended) : Extended;
{-Returns internal rate of return of a series of periodic cash flows}
function IsCardValid(const S : string) : Boolean;
{-Checks for valid credit card number (MasterCard, Visa, AMEX, Discover)}
function ModifiedDuration(Settlement, Maturity : TStDate;
Rate, Yield : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Returns the modified duration for bond with an assumed par value of $100}
function ModifiedIRR(const Values : array of Double;
FinanceRate, ReinvestRate : Extended) : Extended;
function ModifiedIRR16(const Values; NValues : Integer;
FinanceRate, ReinvestRate : Extended) : Extended;
{-Returns the MIRR for a series of periodic cash flows}
function NetPresentValue(Rate : Extended;
const Values : array of Double) : Extended;
function NetPresentValue16(Rate : Extended;
const Values; NValues : Integer) : Extended;
{-Returns the net present value of a series of periodic cash flows}
function NominalInterestRate(EffectRate : Extended;
Frequency : TStFrequency) : Extended;
{-Converts effective annual interest Rate to nominal Rate}
function NonperiodicIRR(const Values : array of Double;
const Dates : array of TStDate;
Guess : Extended) : Extended;
function NonperiodicIRR16(const Values;
const Dates; NValues : Integer;
Guess : Extended) : Extended;
{-Returns the IRR for a series of irregular cash flows}
function NonperiodicNPV(Rate : Extended;
const Values : array of Double;
const Dates : array of TStDate) : Extended;
function NonperiodicNPV16(Rate : Extended;
const Values;
const Dates;
NValues : Integer) : Extended;
{-Returns the net present value for a series of irregular cash flows}
function Payment(Rate : Extended;
NPeriods : Integer;
PV, FV : Extended;
Frequency : TStFrequency;
Timing : TStPaymentTime) : Extended;
{-Returns the interest payment per period in an annuity}
function Periods(Rate : Extended;
Pmt, PV, FV : Extended;
Frequency : TStFrequency;
Timing: TStPaymentTime) : Integer;
{-Returns the number of periods for an annuity}
function PresentValue(Rate : Extended;
NPeriods : Integer;
Pmt, FV : Extended;
Frequency : TStFrequency;
Timing : TStPaymentTime) : Extended;
{-Returns present value of an annity}
function ReceivedAtMaturity(Settlement, Maturity : TStDate;
Investment, Discount : Extended;
Basis : TStBasis) : Extended;
{-Returns the amount received at Maturity for a fully invested security}
function RoundToDecimal(Value : Extended;
Places : Integer;
Bankers : Boolean) : Extended;
{-Rounds a real value to the specified number of decimal places}
function TBillEquivYield(Settlement, Maturity : TStDate;
Discount : Extended) : Extended;
{-Returns the bond-equivalent yield for a treasury bill}
function TBillPrice(Settlement, Maturity : TStDate;
Discount : Extended) : Extended;
{-Returns the price per $100 face value for a treasury bill}
function TBillYield(Settlement, Maturity : TStDate;
Price : Extended) : Extended;
{-Returns the yield for a treasury bill}
function VariableDecliningBalance(Cost, Salvage : Extended;
Life : Integer;
StartPeriod, EndPeriod, Factor : Extended;
NoSwitch : boolean) : Extended;
{-Variable rate declining balance depreciation}
function YieldDiscounted(Settlement, Maturity : TStDate;
Price, Redemption : Extended;
Basis : TStBasis) : Extended;
{-Returns the annual yield for a discounted security}
function YieldPeriodic(Settlement, Maturity : TStDate;
Rate, Price, Redemption : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Returns the yield on a security that pays periodicinterest}
function YieldMaturity(Issue, Settlement, Maturity : TStDate;
Rate, Price : Extended;
Basis : TStBasis) : Extended;
{-Returns the annual yield of a security that pays interest at Maturity}
{========================================================================}
implementation
const
PaymentType : array[TStPaymentTime] of Integer = (0, 1);
{Used for converting Timing to integer 0 or 1}
CouponsPerYear : array[TStFrequency] of Integer = (1, 2, 4, 12);
{Used for converting Frequency to integer 1, 2, 4, or 12}
CouponPeriod : array[TStFrequency] of Integer = (12, 6, 3, 1);
{Used for converting Frequency to duration}
DefaultGuess : Extended = 0.1;
{Starting point for rate approximation routines}
var
RecipLn10 : Extended;
{Used for common log computation}
{================= Local routines used by this unit ==================}
procedure RaiseStFinError(Code : Longint);
begin
Raise EStFinError.CreateResTP(Code, 0);
end;
{-------------------------------------------------------}
function Exp10(Exponent : Extended) : Extended;
{-Returns 10^Exponent}
begin
Result := Power(10.0, Exponent);
end;
{-------------------------------------------------------}
function Log10(Value : Extended) : Extended;
{-Returns common log of Value}
begin
Result := Ln(Value) * RecipLn10;
end;
{-------------------------------------------------------}
function DayCount(Day1, Day2 : TStDate; Basis : TStBasis) : LongInt;
{-The number of days from Day1 to Day2 according to day count basis}
var
BDT : TStBondDateType;
begin
case Basis of
BasisNASD : BDT := bdt30360PSA;
BasisEur30360 : BDT := bdt30E360;
else
BDT := bdtActual;
end;
Result := Longint(BondDateDiff(Day1, Day2, BDT));
end;
{-------------------------------------------------------}
function LastCoupon(Settlement, Maturity : TStDate;
Frequency : TStFrequency) : TStDate;
{-The last coupon date prior to settlement}
var
Last : TStDate;
Months : Integer;
begin
Last := Maturity;
Months := 0;
while (Last >= Settlement) do begin
Months := Months + CouponPeriod[Frequency];
Last := IncDateTrunc(Maturity, -Months, 0);
end;
Result := Last;
end;
{-------------------------------------------------------}
function NextCoupon(Settlement, Maturity : TStDate;
Frequency : TStFrequency) : TStDate;
{-The next coupon date after settlement}
var
Next : TStDate;
begin
Next := LastCoupon(Settlement, Maturity, Frequency);
Result := IncDateTrunc(Next, CouponPeriod[Frequency], 0);
end;
{-------------------------------------------------------}
function CouponsToMaturity(Settlement, Maturity : TStDate;
Frequency : TStFrequency) : Integer;
{-The number of coupons remaining after settlement}
var
CouponDate : TStDate;
Months : Integer;
Coupons : Integer;
begin
CouponDate := Maturity;
Coupons := 0;
Months := 0;
while (CouponDate > Settlement) do begin
Months := Months + CouponPeriod[Frequency];
CouponDate := IncDateTrunc(Maturity, -Months, 0);
Coupons := Coupons + 1;
end;
Result := Coupons;
end;
{-------------------------------------------------------}
function DayCountFraction(Day1, Day2, Settlement, Maturity : TStDate;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-The number of days from Day1 to Day2 divided by days/year
except for Act/Act which uses actual coupon period x frequency}
var
Last, Next : TStDate;
DPY : Integer;
begin
if (Basis = BasisActAct) then begin
Last := LastCoupon(Settlement, Maturity, Frequency);
Next := NextCoupon(Settlement, Maturity, Frequency);
DPY := DayCount(Last, Next, Basis) * CouponsPerYear[Frequency];
end else if (Basis = BasisAct365) then
DPY := 365
else
DPY := 360;
Result := DayCount(Day1, Day2, Basis) / DPY;
end;
{-------------------------------------------------------}
function BondDirtyPrice(Settlement, Maturity : TStDate;
Rate, Yield, Redemption : Extended;
Frequency : TStFrequency;
Basis : TStBasis) : Extended;
{-Bond Price including interest accrued in current coupon period}
var
C, DCF, Yw : Extended;
Vn, Vdcf : Extended;
Next : TStDate;
N, W : Integer;
begin
W := CouponsPerYear[Frequency];
C := Redemption * (Rate / W);
Yw := Yield / W;
N := CouponsToMaturity(Settlement, Maturity, Frequency);
Next := NextCoupon(Settlement, Maturity, Frequency);
DCF := DayCountFraction(Settlement, Next, Settlement, Maturity,
Frequency, Basis);
Vdcf := Power(1.0 / (1.0 + Yw), DCF * W);
Vn := Power(1.0 / (1.0 + Yw), N - 1.0);
Result := Vdcf * (( C * (1.0 - Vn) / Yw) + Redemption * Vn + C);
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -