getBondDiscountedCashFlows()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 19
rs 9.4285
cc 2
eloc 12
nc 2
nop 0
1
<?php
2
3
namespace FinanCalc\Calculators {
4
5
    use FinanCalc\Interfaces\Calculator\BondCalculatorAbstract;
6
    use FinanCalc\Utils\Lambdas;
7
    use FinanCalc\Utils\MathFuncs;
8
9
10
    /**
11
     * Class BondDurationCalculator
12
     * @package FinanCalc\Calculators
13
     */
14
    class BondDurationCalculator extends BondCalculatorAbstract
15
    {
16
17
        // annual yield of the bond
18
        protected $bondAnnualYield;
19
20
        // INHERITED MEMBERS
21
        // face value of the bond = 'F'
22
        // $bondFaceValue;
23
24
        // coupon rate of the bond per annum = 'c'
25
        // $bondAnnualCouponRate;
26
27
        // number of years to the maturity of the bond
28
        // $bondYearsToMaturity;
29
30
        // frequency of bond payments (expressed in a divisor of 12 months ~ 1 year)
31
        // e.g.: divisor 2 means semi-annual payments
32
        // $bondPaymentFrequency;
33
34
        // props returned by the getResultAsArray method by default
35
        protected $propResultArray = [
36
            "bondFaceValue",
37
            "bondAnnualCouponRate",
38
            "bondAnnualYield",
39
            "bondYearsToMaturity",
40
            "bondPaymentFrequency",
41
            "bondYieldPerPaymentPeriod",
42
            "bondNominalCashFlows",
43
            "bondDiscountedCashFlows",
44
            "bondPresentValue",
45
            "bondDuration"
46
        ];
47
48
        /**
49
         * @param $bondFaceValue
50
         * @param $bondAnnualCouponRate
51
         * @param $bondAnnualYield
52
         * @param $bondYearsToMaturity
53
         * @param $bondPaymentFrequency
54
         */
55
        public function __construct(
56
            $bondFaceValue,
57
            $bondAnnualCouponRate,
58
            $bondAnnualYield,
59
            $bondYearsToMaturity,
60
            $bondPaymentFrequency = 1
61
        ) {
62
            $this->setBondFaceValue($bondFaceValue);
63
            $this->setBondAnnualCouponRate($bondAnnualCouponRate);
64
            $this->setBondAnnualYield($bondAnnualYield);
65
            $this->setBondYearsToMaturity($bondYearsToMaturity);
66
            $this->setBondPaymentFrequency($bondPaymentFrequency);
67
        }
68
69
        /**
70
         * @param $bondAnnualYield
71
         */
72
        public function setBondAnnualYield($bondAnnualYield)
73
        {
74
            $this->setProperty("bondAnnualYield", $bondAnnualYield, Lambdas::checkIfPositive());
75
        }
76
77
        /**
78
         * @return mixed
79
         */
80
        public function getBondAnnualYield()
81
        {
82
            return $this->bondAnnualYield;
83
        }
84
85
        /**
86
         * @return string
87
         */
88
        public function getBondYieldPerPaymentPeriod()
89
        {
90
            return MathFuncs::div($this->bondAnnualYield, $this->bondPaymentFrequency);
91
        }
92
93
        /**
94
         * @return array
95
         */
96
        public function getBondNominalCashFlows()
97
        {
98
            // nominal cash flows = coupons each period + face value in the last period
99
            $numberOfPayments = $this->getBondNoOfPayments();
100
            $couponPayment = $this->getCouponPayment();
101
102
            $nominalCashFlows = array();
103
            for ($i = 1; $i <= $numberOfPayments; $i++) {
104
                if ($i == $numberOfPayments) {
105
                    $nominalCashFlows[$i] = MathFuncs::add($couponPayment, $this->bondFaceValue);
106
                } else {
107
                    $nominalCashFlows[$i] = $couponPayment;
108
                }
109
            }
110
111
            return $nominalCashFlows;
112
        }
113
114
        /**
115
         * @return array
116
         */
117
        public function getBondDiscountedCashFlows()
118
        {
119
            // discounted cash flows = nominal cash flows discounted by the means of yield
120
            $discountFactor = MathFuncs::div(1, MathFuncs::add(1, $this->getBondYieldPerPaymentPeriod()));
121
122
            $nominalCashFlows = $this->getBondNominalCashFlows();
123
            $discountedCashFlows = array();
124
            $i = 1;
125
            foreach ($nominalCashFlows as $nominalCashFlowEntry) {
126
                $discountedCashFlows[] = MathFuncs::mul(
127
                    $nominalCashFlowEntry,
128
                    MathFuncs::pow(
129
                        $discountFactor,
130
                        $i++)
131
                );
132
            }
133
134
            return $discountedCashFlows;
135
        }
136
137
        /**
138
         * @return float
139
         */
140
        public function getBondPresentValue()
141
        {
142
            // bond present value = sum of all discounted cash flows during the life of the bond
143
            $presentValue = 0;
144
            foreach ($this->getBondDiscountedCashFlows() as $discountedCashFlowEntry) {
145
                $presentValue = MathFuncs::add($presentValue, $discountedCashFlowEntry);
146
            }
147
148
            return $presentValue;
149
        }
150
151
        /**
152
         * @return string
153
         */
154
        public function getBondDuration()
155
        {
156
            // duration of the bond = sum of auxiliary values of all periods / bond present value
157
            // auxiliary value for a period = discounted cash flow in the period * number of the period
158
            $auxiliaryValue = 0;
159
            $i = 1;
160
            foreach ($this->getBondDiscountedCashFlows() as $discountedCashFlowEntry) {
161
                $auxiliaryValue = MathFuncs::add(
162
                    $auxiliaryValue,
163
                    MathFuncs::mul(
164
                        $discountedCashFlowEntry,
165
                        $i++)
166
                );
167
            }
168
169
            $duration = MathFuncs::div($auxiliaryValue, $this->getBondPresentValue());
170
171
            return $duration;
172
        }
173
    }
174
}
175