Skip to content

Commit

Permalink
- added BondYTMCalculator
Browse files Browse the repository at this point in the history
- created an abstract class for bond instances
  • Loading branch information
uruba committed Aug 11, 2015
1 parent 0256048 commit 946e9cc
Show file tree
Hide file tree
Showing 7 changed files with 447 additions and 73 deletions.
33 changes: 32 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ namespace `FinanCalc\Calculators\DebtAmortizator`

### BondFairValueCalculator
namespace `FinanCalc\Calculators`
* **__construct($bondFaceValue, $bondAnnualCouponRate, $bondVIR, $bondYearsToMaturity, $bondPaymentFrequency)**
* **__construct($bondFaceValue, $bondAnnualCouponRate, $bondVIR, $bondYearsToMaturity, $bondPaymentFrequency = 1)**
* *$bondFaceValue* = **'F'** – face value of the bond (number greater than zero)
* *$bondAnnualCouponRate* = **'c'** – annual coupon rate of the bond (i.e., a decimal number typically lower than 1 and greater than 0)
* *$bondVIR* = **'i' or 'VIR'** – valuation interest rate of the bond (i.e., a decimal number typically lower than 1 and greater than 0)
Expand All @@ -266,6 +266,37 @@ namespace `FinanCalc\Calculators\BondFairValueCalculator`
* **getBondNoOfPayments()** – gets the total number of payments during the lifespan of the bond
* **getBondFairValue()** – gets the fair (market) value of the bond [calculated as present value of future cashflows corresponding to the bond by means of the valuation interest rate]

* * *

### BondYTMCalculator
namespace `FinanCalc\Calculators`
* **__construct($bondFaceValue, $bondMarketValue, $bondAnnualCouponRate, $bondYearsToMaturity, $bondPaymentFrequency = 1)**
* *$bondFaceValue* = **'F'** – face value of the bond (number greater than zero)
* *$bondMarketValue* = **'P'** – market value (i.e., price) of the bond (number greater than zero)
* *$bondAnnualCouponRate* = **'c'** – annual coupon rate of the bond (i.e., a decimal number typically lower than 1 and greater than 0)
* *bondYearsToMaturity* = number of years to the maturity of the bond (number greater than zero, can be a decimal number)
* *bondPaymentFrequency* = frequency of bond payments (expressed in a divisor of 12 months ~ 1 year); e.g.: divisor 2 means semi-annual payments
* **getResult()** – gets the ***BondInstance*** object manufactured by the constructor

#### BondInstance (*BondYTMCalculator's result object*)
namespace `FinanCalc\Calculators\BondYTMCalculator`
##### Setters
* **setBondFaceValue($bondFaceValue)** – sets F
* **setBondMarketValue($bondMarketValue)** – sets the market value of the bond
* **setBondAnnualCouponRate($bondAnnualCouponRate)** – sets c
* **setBondYearsToMaturity($bondYearsToMaturity)** – sets the number of years to the maturity of the bond
* **setBondPaymentFrequency($bondPaymentFrequency)** – sets the frequency of bond payments

##### Getters
* **getBondFaceValue()** – gets F
* **getBondMarketValue()** – gets the market value of the bond
* **getBondAnnualCouponRate()** – gets c
* **getBondYearsToMaturity()** – gets the number of years to the maturity of the bond
* **getBondPaymentFrequncy()** – gets the frequency of bond payments
* **getBondNoOfPayments()** – gets the total number of payments during the lifespan of the bond
* **getApproxBondYTM()** – gets the approximate value of the bond's yield to maturity in the form of a decimal number [it is the internal rate of return of the bond]


* * *

## DISCLAIMER
Expand Down
101 changes: 29 additions & 72 deletions src/calculators/BondFairValueCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
use FinanCalc\Calculators\BondFairValueCalculator\BondInstance;
use FinanCalc\Interfaces\CalculatorInterface;

/**
* Class BondFairValueCalculator
* @package FinanCalc\Calculators
*/
class BondFairValueCalculator implements CalculatorInterface {
private $bondInstance;

Expand All @@ -30,8 +34,7 @@ function __construct($bondFaceValue,
/**
* @return BondInstance
*/
public function getResult()
{
public function getResult() {
return $this->bondInstance;
}
}
Expand All @@ -40,22 +43,32 @@ public function getResult()
namespace FinanCalc\Calculators\BondFairValueCalculator {

use FinanCalc\Calculators\AnnuityCalculator;
use FinanCalc\Interfaces\BondInstanceAbstract;
use FinanCalc\Utils\Helpers;
use FinanCalc\Utils\MathFuncs;

class BondInstance {
/**
* Class BondInstance
* @package FinanCalc\Calculators\BondFairValueCalculator
*/
class BondInstance extends BondInstanceAbstract {

// the face value of the bond = 'F'
private $bondFaceValue;
// coupon rate of the bond = 'c'
private $bondAnnualCouponRate;
// valuation interest rate of the bond = 'i'
private $bondVIR;

// INHERITED MEMBERS
// face value of the bond = 'F'
// $bondFaceValue;

// coupon rate of the bond per annum = 'c'
// $bondAnnualCouponRate;

// number of years to the maturity of the bond
private $bondYearsToMaturity;
// $bondYearsToMaturity;

// frequency of bond payments (expressed in a divisor of 12 months ~ 1 year)
// e.g.: divisor 2 means semi-annual payments
private $bondPaymentFrequency;
// $bondPaymentFrequency;

/**
* @param $bondFaceValue
Expand All @@ -76,24 +89,6 @@ function __construct($bondFaceValue,
$this->setBondPaymentFrequency($bondPaymentFrequency);
}

/**
* @param $bondFaceValue
*/
public function setBondFaceValue($bondFaceValue) {
if(Helpers::checkIfPositiveNumberOrThrowAnException($bondFaceValue)) {
$this->bondFaceValue = $bondFaceValue;
}
}

/**
* @param $bondAnnualCouponRate
*/
public function setBondAnnualCouponRate($bondAnnualCouponRate) {
if(Helpers::checkIfPositiveNumberOrThrowAnException($bondAnnualCouponRate)) {
$this->bondAnnualCouponRate = $bondAnnualCouponRate;
}
}

/**
* @param $bondVIR
*/
Expand All @@ -104,54 +99,15 @@ public function setBondVIR($bondVIR) {
}

/**
* @param $bondYearsToMaturity
* @return mixed
*/
public function setBondYearsToMaturity($bondYearsToMaturity) {
if(Helpers::checkIfPositiveNumberOrThrowAnException($bondYearsToMaturity)) {
$this->bondYearsToMaturity = $bondYearsToMaturity;
}
}

/**
* @param $bondPaymentFrequency
*/
public function setBondPaymentFrequency($bondPaymentFrequency) {
if(Helpers::checkIfPositiveNumberOrThrowAnException($bondPaymentFrequency)) {
$this->bondPaymentFrequency = $bondPaymentFrequency;
}
}

public function getBondFaceValue() {
return $this->bondFaceValue;
}

public function getBondAnnualCouponRate() {
return $this->bondAnnualCouponRate;
}

public function getBondVIR() {
return $this->bondVIR;
}

public function getBondYearsToMaturity() {
return $this->bondYearsToMaturity;
}

public function getBondPaymentFrequency() {
return $this->bondPaymentFrequency;
}

public function getBondNoOfPayments() {
// number of payments during the duration of the bond
// is calculated from the number of years of the duration of the bond
// multiplied by the number of payments per year (i.e., payment frequency)
//, floored (to eliminate the last remaining incomplete due period)
return floor(MathFuncs::mul(
$this->bondYearsToMaturity,
$this->bondPaymentFrequency
));
}

/**
* @return float
*/
public function getBondFairValue() {
// we need to get the coupon rate per payment period = c/payment frequency
$couponRateForPeriod = MathFuncs::div(
Expand Down Expand Up @@ -196,7 +152,8 @@ public function getBondFairValue() {
MathFuncs::add(
MathFuncs::mul(
$couponRateForPeriod,
$PVofUnitBondAnnuity),
$PVofUnitBondAnnuity
),
MathFuncs::div(
1,
MathFuncs::pow(
Expand All @@ -210,7 +167,7 @@ public function getBondFairValue() {
)
);

return Helpers::roundMoneyForDisplay($fairValue);
return $fairValue;
}
}
}
135 changes: 135 additions & 0 deletions src/calculators/BondYTMCalculator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
<?php

namespace FinanCalc\Calculators {

use FinanCalc\Calculators\BondYTMCalculator\BondInstance;
use FinanCalc\Interfaces\CalculatorInterface;

/**
* Class BondYTMCalculator
* @package FinanCalc\Calculators
*/
class BondYTMCalculator implements CalculatorInterface {
private $bondInstance;

/**
* @param $bondFaceValue
* @param $bondMarketValue
* @param $bondAnnualCouponRate
* @param $bondYearsToMaturity
* @param int $bondPaymentFrequency
*/
function __construct($bondFaceValue,
$bondMarketValue,
$bondAnnualCouponRate,
$bondYearsToMaturity,
$bondPaymentFrequency = 1) {
$this->bondInstance = new BondInstance($bondFaceValue,
$bondMarketValue,
$bondAnnualCouponRate,
$bondYearsToMaturity,
$bondPaymentFrequency);
}

/**
* @return BondInstance
*/
function getResult() {
return $this->bondInstance;
}
}
}

namespace FinanCalc\Calculators\BondYTMCalculator {

use FinanCalc\Interfaces\BondInstanceAbstract;
use FinanCalc\Utils\Helpers;
use FinanCalc\Utils\MathFuncs;

/**
* Class BondInstance
* @package FinanCalc\Calculators\BondYTMCalculator
*/
class BondInstance extends BondInstanceAbstract {

// market value of the bond = 'P'
private $bondMarketValue;

// INHERITED MEMBERS
// face value of the bond = 'F'
// $bondFaceValue;

// coupon rate of the bond per annum = 'c'
// $bondAnnualCouponRate;

// number of years to the maturity of the bond
// $bondYearsToMaturity;

// frequency of bond payments (expressed in a divisor of 12 months ~ 1 year)
// e.g.: divisor 2 means semi-annual payments
// $bondPaymentFrequency;

/**
* @param $bondFaceValue
* @param $bondMarketValue
* @param $bondAnnualCouponRate
* @param $bondYearsToMaturity
* @param $bondPaymentFrequency
*/
function __construct($bondFaceValue,
$bondMarketValue,
$bondAnnualCouponRate,
$bondYearsToMaturity,
$bondPaymentFrequency) {
$this->setBondFaceValue($bondFaceValue);
$this->setBondMarketValue($bondMarketValue);
$this->setBondAnnualCouponRate($bondAnnualCouponRate);
$this->setBondYearsToMaturity($bondYearsToMaturity);
$this->setBondPaymentFrequency($bondPaymentFrequency);
}

/**
* @param $bondMarketValue
*/
public function setBondMarketValue($bondMarketValue) {
if(Helpers::checkIfPositiveNumberOrThrowAnException($bondMarketValue)) {
$this->bondMarketValue = $bondMarketValue;
}
}

public function getBondMarketValue() {
return $this->bondMarketValue;
}

/**
* @return string
*/
public function getApproxBondYTM() {
// we need to calculate the coupon payment C = F*c
$couponPayment = $this->bondFaceValue * $this->bondAnnualCouponRate;

// we use a formula to approximate the YTM = (C+(F-P)/n)/((F+P)/2)
$approxYTM =
MathFuncs::div(
MathFuncs::add(
$couponPayment,
MathFuncs::div(
MathFuncs::sub(
$this->bondFaceValue,
$this->bondMarketValue),
$this->getBondNoOfPayments()
)
),
MathFuncs::div(
MathFuncs::add(
$this->bondFaceValue,
$this->bondMarketValue
),
2));

return $approxYTM;
}

// TODO – add a method for precise bond YTM calculation by means of a polynominal equation
}
}
Loading

0 comments on commit 946e9cc

Please sign in to comment.