Test Failed
Push — develop ( 90366f...812a46 )
by Adrien
28:16
created

Financial::isLastDayOfMonth()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Calculation;
4
5
use PhpOffice\PhpSpreadsheet\Shared\Date;
6
7
class Financial
8
{
9
    const FINANCIAL_MAX_ITERATIONS = 128;
10
11
    const FINANCIAL_PRECISION = 1.0e-08;
12
13
    /**
14
     * isLastDayOfMonth.
15
     *
16
     * Returns a boolean TRUE/FALSE indicating if this date is the last date of the month
17
     *
18
     * @param DateTime $testDate The date for testing
19
     *
20
     * @return bool
21
     */
22 12
    private static function isLastDayOfMonth(\DateTime $testDate)
23
    {
24 12
        return $testDate->format('d') == $testDate->format('t');
25
    }
26
27 12
    private static function couponFirstPeriodDate($settlement, $maturity, $frequency, $next)
28
    {
29 12
        $months = 12 / $frequency;
30
31 12
        $result = Date::excelToDateTimeObject($maturity);
32 12
        $eom = self::isLastDayOfMonth($result);
33
34 12
        while ($settlement < Date::PHPToExcel($result)) {
35 12
            $result->modify('-' . $months . ' months');
36
        }
37 12
        if ($next) {
38 8
            $result->modify('+' . $months . ' months');
39
        }
40
41 12
        if ($eom) {
42 1
            $result->modify('-1 day');
43
        }
44
45 12
        return Date::PHPToExcel($result);
46
    }
47
48 19
    private static function isValidFrequency($frequency)
49
    {
50 19
        if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) {
51 13
            return true;
52
        }
53 6
        if ((Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) &&
54 6
            (($frequency == 6) || ($frequency == 12))) {
55
            return true;
56
        }
57
58 6
        return false;
59
    }
60
61
    /**
62
     * daysPerYear.
63
     *
64
     * Returns the number of days in a specified year, as defined by the "basis" value
65
     *
66
     * @param int $year The year against which we're testing
67
     * @param int $basis The type of day count:
68
     *                                    0 or omitted US (NASD)    360
69
     *                                    1                        Actual (365 or 366 in a leap year)
70
     *                                    2                        360
71
     *                                    3                        365
72
     *                                    4                        European 360
73
     *
74
     * @return int
75
     */
76 4
    private static function daysPerYear($year, $basis = 0)
77
    {
78
        switch ($basis) {
79 4
            case 0:
80 2
            case 2:
81 2
            case 4:
82 2
                $daysPerYear = 360;
83
84 2
                break;
85 2
            case 3:
86
                $daysPerYear = 365;
87
88
                break;
89 2
            case 1:
90 2
                $daysPerYear = (DateTime::isLeapYear($year)) ? 366 : 365;
91
92 2
                break;
93
            default:
94
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
95
        }
96
97 4
        return $daysPerYear;
98
    }
99
100 20
    private static function interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
101
    {
102 20
        $pmt = self::PMT($rate, $nper, $pv, $fv, $type);
103 20
        $capital = $pv;
104 20
        for ($i = 1; $i <= $per; ++$i) {
105 20
            $interest = ($type && $i == 1) ? 0 : -$capital * $rate;
106 20
            $principal = $pmt - $interest;
107 20
            $capital += $principal;
108
        }
109
110 20
        return [$interest, $principal];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $interest does not seem to be defined for all execution paths leading up to this point.
Loading history...
Comprehensibility Best Practice introduced by
The variable $principal does not seem to be defined for all execution paths leading up to this point.
Loading history...
111
    }
112
113
    /**
114
     * ACCRINT.
115
     *
116
     * Returns the accrued interest for a security that pays periodic interest.
117
     *
118
     * Excel Function:
119
     *        ACCRINT(issue,firstinterest,settlement,rate,par,frequency[,basis])
120
     *
121
     * @category Financial Functions
122
     *
123
     * @param mixed $issue the security's issue date
124
     * @param mixed $firstinterest the security's first interest date
125
     * @param mixed $settlement The security's settlement date.
126
     *                                    The security settlement date is the date after the issue date
127
     *                                    when the security is traded to the buyer.
128
     * @param float $rate the security's annual coupon rate
129
     * @param float $par The security's par value.
130
     *                                    If you omit par, ACCRINT uses $1,000.
131
     * @param int $frequency the number of coupon payments per year.
132
     *                                    Valid frequency values are:
133
     *                                        1    Annual
134
     *                                        2    Semi-Annual
135
     *                                        4    Quarterly
136
     *                                    If working in Gnumeric Mode, the following frequency options are
137
     *                                    also available
138
     *                                        6    Bimonthly
139
     *                                        12    Monthly
140
     * @param int $basis The type of day count to use.
141
     *                                        0 or omitted    US (NASD) 30/360
142
     *                                        1                Actual/actual
143
     *                                        2                Actual/360
144
     *                                        3                Actual/365
145
     *                                        4                European 30/360
146
     *
147
     * @return float
148
     */
149 7
    public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0)
150
    {
151 7
        $issue = Functions::flattenSingleValue($issue);
152 7
        $firstinterest = Functions::flattenSingleValue($firstinterest);
0 ignored issues
show
Unused Code introduced by
The assignment to $firstinterest is dead and can be removed.
Loading history...
153 7
        $settlement = Functions::flattenSingleValue($settlement);
154 7
        $rate = Functions::flattenSingleValue($rate);
155 7
        $par = ($par === null) ? 1000 : Functions::flattenSingleValue($par);
156 7
        $frequency = ($frequency === null) ? 1 : Functions::flattenSingleValue($frequency);
0 ignored issues
show
Unused Code introduced by
The assignment to $frequency is dead and can be removed.
Loading history...
157 7
        $basis = ($basis === null) ? 0 : Functions::flattenSingleValue($basis);
158
159
        //    Validate
160 7 View Code Duplication
        if ((is_numeric($rate)) && (is_numeric($par))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
161 6
            $rate = (float) $rate;
162 6
            $par = (float) $par;
163 6
            if (($rate <= 0) || ($par <= 0)) {
164 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
165
            }
166 5
            $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis);
167 5
            if (!is_numeric($daysBetweenIssueAndSettlement)) {
168
                //    return date error
169 2
                return $daysBetweenIssueAndSettlement;
170
            }
171
172 3
            return $par * $rate * $daysBetweenIssueAndSettlement;
173
        }
174
175 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
176
    }
177
178
    /**
179
     * ACCRINTM.
180
     *
181
     * Returns the accrued interest for a security that pays interest at maturity.
182
     *
183
     * Excel Function:
184
     *        ACCRINTM(issue,settlement,rate[,par[,basis]])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\par was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\basis was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\settlement was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
185
     *
186
     * @category Financial Functions
187
     *
188
     * @param mixed issue The security's issue date
189
     * @param mixed settlement The security's settlement (or maturity) date
190
     * @param float rate The security's annual coupon rate
191
     * @param float par The security's par value.
192
     *                                    If you omit par, ACCRINT uses $1,000.
193
     * @param int basis The type of day count to use.
194
     *                                        0 or omitted    US (NASD) 30/360
195
     *                                        1                Actual/actual
196
     *                                        2                Actual/360
197
     *                                        3                Actual/365
198
     *                                        4                European 30/360
199
     * @param mixed $issue
200
     * @param mixed $settlement
201
     * @param mixed $rate
202
     * @param mixed $par
203
     * @param mixed $basis
204
     *
205
     * @return float
206
     */
207 5
    public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0)
208
    {
209 5
        $issue = Functions::flattenSingleValue($issue);
210 5
        $settlement = Functions::flattenSingleValue($settlement);
211 5
        $rate = Functions::flattenSingleValue($rate);
212 5
        $par = ($par === null) ? 1000 : Functions::flattenSingleValue($par);
213 5
        $basis = ($basis === null) ? 0 : Functions::flattenSingleValue($basis);
214
215
        //    Validate
216 5 View Code Duplication
        if ((is_numeric($rate)) && (is_numeric($par))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
217 4
            $rate = (float) $rate;
218 4
            $par = (float) $par;
219 4
            if (($rate <= 0) || ($par <= 0)) {
220 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
221
            }
222 3
            $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis);
223 3
            if (!is_numeric($daysBetweenIssueAndSettlement)) {
224
                //    return date error
225 1
                return $daysBetweenIssueAndSettlement;
226
            }
227
228 2
            return $par * $rate * $daysBetweenIssueAndSettlement;
229
        }
230
231 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
232
    }
233
234
    /**
235
     * AMORDEGRC.
236
     *
237
     * Returns the depreciation for each accounting period.
238
     * This function is provided for the French accounting system. If an asset is purchased in
239
     * the middle of the accounting period, the prorated depreciation is taken into account.
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\rate was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
240
     * The function is similar to AMORLINC, except that a depreciation coefficient is applied in
241
     * the calculation depending on the life of the assets.
242
     * This function will return the depreciation until the last period of the life of the assets
243
     * or until the cumulated value of depreciation is greater than the cost of the assets minus
244
     * the salvage value.
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\salvage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
245
     *
246
     * Excel Function:
247
     *        AMORDEGRC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
248
     *
249
     * @category Financial Functions
250
     *
251
     * @param float cost The cost of the asset
252
     * @param mixed purchased Date of the purchase of the asset
253
     * @param mixed firstPeriod Date of the end of the first period
254
     * @param mixed salvage The salvage value at the end of the life of the asset
255
     * @param float period The period
256
     * @param float rate Rate of depreciation
257
     * @param int basis The type of day count to use.
258
     *                                        0 or omitted    US (NASD) 30/360
259
     *                                        1                Actual/actual
260
     *                                        2                Actual/360
261
     *                                        3                Actual/365
262
     *                                        4                European 30/360
263
     * @param mixed $cost
264
     * @param mixed $purchased
265
     * @param mixed $firstPeriod
266
     * @param mixed $salvage
267
     * @param mixed $period
268
     * @param mixed $rate
269
     * @param mixed $basis
270
     *
271
     * @return float
272
     */
273 2
    public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
274
    {
275 2
        $cost = Functions::flattenSingleValue($cost);
276 2
        $purchased = Functions::flattenSingleValue($purchased);
277 2
        $firstPeriod = Functions::flattenSingleValue($firstPeriod);
278 2
        $salvage = Functions::flattenSingleValue($salvage);
279 2
        $period = floor(Functions::flattenSingleValue($period));
280 2
        $rate = Functions::flattenSingleValue($rate);
281 2
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
282
283
        //    The depreciation coefficients are:
284
        //    Life of assets (1/rate)        Depreciation coefficient
285
        //    Less than 3 years            1
286
        //    Between 3 and 4 years        1.5
287
        //    Between 5 and 6 years        2
288
        //    More than 6 years            2.5
289 2
        $fUsePer = 1.0 / $rate;
290 2
        if ($fUsePer < 3.0) {
291
            $amortiseCoeff = 1.0;
292 2
        } elseif ($fUsePer < 5.0) {
293
            $amortiseCoeff = 1.5;
294 2
        } elseif ($fUsePer <= 6.0) {
295 1
            $amortiseCoeff = 2.0;
296
        } else {
297 1
            $amortiseCoeff = 2.5;
298
        }
299
300 2
        $rate *= $amortiseCoeff;
301 2
        $fNRate = round(DateTime::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost, 0);
302 2
        $cost -= $fNRate;
303 2
        $fRest = $cost - $salvage;
304
305 2
        for ($n = 0; $n < $period; ++$n) {
306 2
            $fNRate = round($rate * $cost, 0);
307 2
            $fRest -= $fNRate;
308
309 2
            if ($fRest < 0.0) {
310
                switch ($period - $n) {
311
                    case 0:
312
                    case 1:
313
                        return round($cost * 0.5, 0);
314
                    default:
315
                        return 0.0;
316
                }
317
            }
318 2
            $cost -= $fNRate;
319
        }
320
321 2
        return $fNRate;
322
    }
323
324
    /**
325
     * AMORLINC.
326
     *
327
     * Returns the depreciation for each accounting period.
328
     * This function is provided for the French accounting system. If an asset is purchased in
329
     * the middle of the accounting period, the prorated depreciation is taken into account.
330
     *
331
     * Excel Function:
332
     *        AMORLINC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
333
     *
334
     * @category Financial Functions
335
     *
336
     * @param float cost The cost of the asset
337
     * @param mixed purchased Date of the purchase of the asset
338
     * @param mixed firstPeriod Date of the end of the first period
339
     * @param mixed salvage The salvage value at the end of the life of the asset
340
     * @param float period The period
341
     * @param float rate Rate of depreciation
342
     * @param int basis The type of day count to use.
343
     *                                        0 or omitted    US (NASD) 30/360
344
     *                                        1                Actual/actual
345
     *                                        2                Actual/360
346
     *                                        3                Actual/365
347
     *                                        4                European 30/360
348
     * @param mixed $cost
349
     * @param mixed $purchased
350
     * @param mixed $firstPeriod
351
     * @param mixed $salvage
352
     * @param mixed $period
353
     * @param mixed $rate
354
     * @param mixed $basis
355
     *
356
     * @return float
357
     */
358 2
    public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
359
    {
360 2
        $cost = Functions::flattenSingleValue($cost);
361 2
        $purchased = Functions::flattenSingleValue($purchased);
362 2
        $firstPeriod = Functions::flattenSingleValue($firstPeriod);
363 2
        $salvage = Functions::flattenSingleValue($salvage);
364 2
        $period = Functions::flattenSingleValue($period);
365 2
        $rate = Functions::flattenSingleValue($rate);
366 2
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
367
368 2
        $fOneRate = $cost * $rate;
369 2
        $fCostDelta = $cost - $salvage;
370
        //    Note, quirky variation for leap years on the YEARFRAC for this function
371 2
        $purchasedYear = DateTime::YEAR($purchased);
372 2
        $yearFrac = DateTime::YEARFRAC($purchased, $firstPeriod, $basis);
373
374 2
        if (($basis == 1) && ($yearFrac < 1) && (DateTime::isLeapYear($purchasedYear))) {
375 1
            $yearFrac *= 365 / 366;
376
        }
377
378 2
        $f0Rate = $yearFrac * $rate * $cost;
379 2
        $nNumOfFullPeriods = (int) (($cost - $salvage - $f0Rate) / $fOneRate);
380
381 2
        if ($period == 0) {
382
            return $f0Rate;
383 2
        } elseif ($period <= $nNumOfFullPeriods) {
384 2
            return $fOneRate;
385
        } elseif ($period == ($nNumOfFullPeriods + 1)) {
386
            return $fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate;
387
        }
388
389
        return 0.0;
390
    }
391
392
    /**
393
     * COUPDAYBS.
394
     *
395
     * Returns the number of days from the beginning of the coupon period to the settlement date.
396
     *
397
     * Excel Function:
398
     *        COUPDAYBS(settlement,maturity,frequency[,basis])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\maturity was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
399
     *
400
     * @category Financial Functions
401
     *
402
     * @param mixed settlement The security's settlement date.
403
     *                                The security settlement date is the date after the issue
404
     *                                date when the security is traded to the buyer.
405
     * @param mixed maturity The security's maturity date.
406
     *                                The maturity date is the date when the security expires.
407
     * @param int frequency the number of coupon payments per year.
408
     *                                    Valid frequency values are:
409
     *                                        1    Annual
410
     *                                        2    Semi-Annual
411
     *                                        4    Quarterly
412
     *                                    If working in Gnumeric Mode, the following frequency options are
413
     *                                    also available
414
     *                                        6    Bimonthly
415
     *                                        12    Monthly
416
     * @param int basis The type of day count to use.
417
     *                                        0 or omitted    US (NASD) 30/360
418
     *                                        1                Actual/actual
419
     *                                        2                Actual/360
420
     *                                        3                Actual/365
421
     *                                        4                European 30/360
422
     * @param mixed $settlement
423
     * @param mixed $maturity
424
     * @param mixed $frequency
425
     * @param mixed $basis
426
     *
427
     * @return float
428
     */
429 5 View Code Duplication
    public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
430
    {
431 5
        $settlement = Functions::flattenSingleValue($settlement);
432 5
        $maturity = Functions::flattenSingleValue($maturity);
433 5
        $frequency = (int) Functions::flattenSingleValue($frequency);
434 5
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
435
436 5
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
437 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
438
        }
439 4
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
440 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
441
        }
442
443 3
        if (($settlement > $maturity) ||
444 3
            (!self::isValidFrequency($frequency)) ||
445 3
            (($basis < 0) || ($basis > 4))) {
446 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
447
        }
448
449 2
        $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
450 2
        $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
451
452 2
        return DateTime::YEARFRAC($prev, $settlement, $basis) * $daysPerYear;
453
    }
454
455
    /**
456
     * COUPDAYS.
457
     *
458
     * Returns the number of days in the coupon period that contains the settlement date.
459
     *
460
     * Excel Function:
461
     *        COUPDAYS(settlement,maturity,frequency[,basis])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\frequency was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
462
     *
463
     * @category Financial Functions
464
     *
465
     * @param mixed settlement The security's settlement date.
466
     *                                The security settlement date is the date after the issue
467
     *                                date when the security is traded to the buyer.
468
     * @param mixed maturity The security's maturity date.
469
     *                                The maturity date is the date when the security expires.
470
     * @param mixed frequency the number of coupon payments per year.
471
     *                                    Valid frequency values are:
472
     *                                        1    Annual
473
     *                                        2    Semi-Annual
474
     *                                        4    Quarterly
475
     *                                    If working in Gnumeric Mode, the following frequency options are
476
     *                                    also available
477
     *                                        6    Bimonthly
478
     *                                        12    Monthly
479
     * @param int basis The type of day count to use.
480
     *                                        0 or omitted    US (NASD) 30/360
481
     *                                        1                Actual/actual
482
     *                                        2                Actual/360
483
     *                                        3                Actual/365
484
     *                                        4                European 30/360
485
     * @param int $frequency
486
     * @param mixed $settlement
487
     * @param mixed $maturity
488
     * @param mixed $basis
489
     *
490
     * @return float
491
     */
492 5
    public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0)
493
    {
494 5
        $settlement = Functions::flattenSingleValue($settlement);
495 5
        $maturity = Functions::flattenSingleValue($maturity);
496 5
        $frequency = (int) Functions::flattenSingleValue($frequency);
497 5
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
498
499 5
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
500 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
501
        }
502 4
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
503 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
504
        }
505
506 3
        if (($settlement > $maturity) ||
507 3
            (!self::isValidFrequency($frequency)) ||
508 3
            (($basis < 0) || ($basis > 4))) {
509 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
510
        }
511
512
        switch ($basis) {
513 2
            case 3:
514
                // Actual/365
515
                return 365 / $frequency;
516 2
            case 1:
517
                // Actual/actual
518 1
                if ($frequency == 1) {
519
                    $daysPerYear = self::daysPerYear(DateTime::YEAR($maturity), $basis);
520
521
                    return $daysPerYear / $frequency;
522
                }
523 1
                $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
524 1
                $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
525
526 1
                return $next - $prev;
527
            default:
528
                // US (NASD) 30/360, Actual/360 or European 30/360
529 1
                return 360 / $frequency;
530
        }
531
    }
532
533
    /**
534
     * COUPDAYSNC.
535
     *
536
     * Returns the number of days from the settlement date to the next coupon date.
537
     *
538
     * Excel Function:
539
     *        COUPDAYSNC(settlement,maturity,frequency[,basis])
540
     *
541
     * @category Financial Functions
542
     *
543
     * @param mixed settlement The security's settlement date.
544
     *                                The security settlement date is the date after the issue
545
     *                                date when the security is traded to the buyer.
546
     * @param mixed maturity The security's maturity date.
547
     *                                The maturity date is the date when the security expires.
548
     * @param mixed frequency the number of coupon payments per year.
549
     *                                    Valid frequency values are:
550
     *                                        1    Annual
551
     *                                        2    Semi-Annual
552
     *                                        4    Quarterly
553
     *                                    If working in Gnumeric Mode, the following frequency options are
554
     *                                    also available
555
     *                                        6    Bimonthly
556
     *                                        12    Monthly
557
     * @param int basis The type of day count to use.
558
     *                                        0 or omitted    US (NASD) 30/360
559
     *                                        1                Actual/actual
560
     *                                        2                Actual/360
561
     *                                        3                Actual/365
562
     *                                        4                European 30/360
563
     * @param mixed $settlement
564
     * @param mixed $maturity
565
     * @param mixed $frequency
566
     * @param mixed $basis
567
     *
568
     * @return float
569
     */
570 5 View Code Duplication
    public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
571
    {
572 5
        $settlement = Functions::flattenSingleValue($settlement);
573 5
        $maturity = Functions::flattenSingleValue($maturity);
574 5
        $frequency = (int) Functions::flattenSingleValue($frequency);
575 5
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
576
577 5
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
578 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
579
        }
580 4
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
581 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
582
        }
583
584 3
        if (($settlement > $maturity) ||
585 3
            (!self::isValidFrequency($frequency)) ||
586 3
            (($basis < 0) || ($basis > 4))) {
587 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
588
        }
589
590 2
        $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
591 2
        $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
592
593 2
        return DateTime::YEARFRAC($settlement, $next, $basis) * $daysPerYear;
594
    }
595
596
    /**
597
     * COUPNCD.
598
     *
599
     * Returns the next coupon date after the settlement date.
600
     *
601
     * Excel Function:
602
     *        COUPNCD(settlement,maturity,frequency[,basis])
603
     *
604
     * @category Financial Functions
605
     *
606
     * @param mixed settlement The security's settlement date.
607
     *                                The security settlement date is the date after the issue
608
     *                                date when the security is traded to the buyer.
609
     * @param mixed maturity The security's maturity date.
610
     *                                The maturity date is the date when the security expires.
611
     * @param mixed frequency the number of coupon payments per year.
612
     *                                    Valid frequency values are:
613
     *                                        1    Annual
614
     *                                        2    Semi-Annual
615
     *                                        4    Quarterly
616
     *                                    If working in Gnumeric Mode, the following frequency options are
617
     *                                    also available
618
     *                                        6    Bimonthly
619
     *                                        12    Monthly
620
     * @param int basis The type of day count to use.
621
     *                                        0 or omitted    US (NASD) 30/360
622
     *                                        1                Actual/actual
623
     *                                        2                Actual/360
624
     *                                        3                Actual/365
625
     *                                        4                European 30/360
626
     * @param mixed $settlement
627
     * @param mixed $maturity
628
     * @param mixed $frequency
629
     * @param mixed $basis
630
     *
631
     * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
632
     *                        depending on the value of the ReturnDateType flag
633
     */
634 5 View Code Duplication
    public static function COUPNCD($settlement, $maturity, $frequency, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
635
    {
636 5
        $settlement = Functions::flattenSingleValue($settlement);
637 5
        $maturity = Functions::flattenSingleValue($maturity);
638 5
        $frequency = (int) Functions::flattenSingleValue($frequency);
639 5
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
640
641 5
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
642 1
            return Functions::VALUE();
643
        }
644 4
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
645 1
            return Functions::VALUE();
646
        }
647
648 3
        if (($settlement > $maturity) ||
649 3
            (!self::isValidFrequency($frequency)) ||
650 3
            (($basis < 0) || ($basis > 4))) {
651 1
            return Functions::NAN();
652
        }
653
654 2
        return self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
655
    }
656
657
    /**
658
     * COUPNUM.
659
     *
660
     * Returns the number of coupons payable between the settlement date and maturity date,
661
     * rounded up to the nearest whole coupon.
662
     *
663
     * Excel Function:
664
     *        COUPNUM(settlement,maturity,frequency[,basis])
665
     *
666
     * @category Financial Functions
667
     *
668
     * @param mixed settlement The security's settlement date.
669
     *                                The security settlement date is the date after the issue
670
     *                                date when the security is traded to the buyer.
671
     * @param mixed maturity The security's maturity date.
672
     *                                The maturity date is the date when the security expires.
673
     * @param mixed frequency the number of coupon payments per year.
674
     *                                    Valid frequency values are:
675
     *                                        1    Annual
676
     *                                        2    Semi-Annual
677
     *                                        4    Quarterly
678
     *                                    If working in Gnumeric Mode, the following frequency options are
679
     *                                    also available
680
     *                                        6    Bimonthly
681
     *                                        12    Monthly
682
     * @param int basis The type of day count to use.
683
     *                                        0 or omitted    US (NASD) 30/360
684
     *                                        1                Actual/actual
685
     *                                        2                Actual/360
686
     *                                        3                Actual/365
687
     *                                        4                European 30/360
688
     * @param mixed $settlement
689
     * @param mixed $maturity
690
     * @param mixed $frequency
691
     * @param mixed $basis
692
     *
693
     * @return int
694
     */
695 6
    public static function COUPNUM($settlement, $maturity, $frequency, $basis = 0)
696
    {
697 6
        $settlement = Functions::flattenSingleValue($settlement);
698 6
        $maturity = Functions::flattenSingleValue($maturity);
699 6
        $frequency = (int) Functions::flattenSingleValue($frequency);
700 6
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
701
702 6
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
703 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
704
        }
705 5
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
706 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
707
        }
708
709 4
        if (($settlement > $maturity) ||
710 4
            (!self::isValidFrequency($frequency)) ||
711 4
            (($basis < 0) || ($basis > 4))) {
712 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type integer.
Loading history...
713
        }
714
715 3
        $settlement = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
716 3
        $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis) * 365;
717
718
        switch ($frequency) {
719 3
            case 1: // annual payments
720 1
                return ceil($daysBetweenSettlementAndMaturity / 360);
721 2
            case 2: // half-yearly
722 1
                return ceil($daysBetweenSettlementAndMaturity / 180);
723 1
            case 4: // quarterly
724 1
                return ceil($daysBetweenSettlementAndMaturity / 90);
725
            case 6: // bimonthly
726
                return ceil($daysBetweenSettlementAndMaturity / 60);
727
            case 12: // monthly
728
                return ceil($daysBetweenSettlementAndMaturity / 30);
729
        }
730
731
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type integer.
Loading history...
732
    }
733
734
    /**
735
     * COUPPCD.
736
     *
737
     * Returns the previous coupon date before the settlement date.
738
     *
739
     * Excel Function:
740
     *        COUPPCD(settlement,maturity,frequency[,basis])
741
     *
742
     * @category Financial Functions
743
     *
744
     * @param mixed settlement The security's settlement date.
745
     *                                The security settlement date is the date after the issue
746
     *                                date when the security is traded to the buyer.
747
     * @param mixed maturity The security's maturity date.
748
     *                                The maturity date is the date when the security expires.
749
     * @param mixed frequency the number of coupon payments per year.
750
     *                                    Valid frequency values are:
751
     *                                        1    Annual
752
     *                                        2    Semi-Annual
753
     *                                        4    Quarterly
754
     *                                    If working in Gnumeric Mode, the following frequency options are
755
     *                                    also available
756
     *                                        6    Bimonthly
757
     *                                        12    Monthly
758
     * @param int basis The type of day count to use.
759
     *                                        0 or omitted    US (NASD) 30/360
760
     *                                        1                Actual/actual
761
     *                                        2                Actual/360
762
     *                                        3                Actual/365
763
     *                                        4                European 30/360
764
     * @param mixed $settlement
765
     * @param mixed $maturity
766
     * @param mixed $frequency
767
     * @param mixed $basis
768
     *
769
     * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
770
     *                        depending on the value of the ReturnDateType flag
771
     */
772 5 View Code Duplication
    public static function COUPPCD($settlement, $maturity, $frequency, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
773
    {
774 5
        $settlement = Functions::flattenSingleValue($settlement);
775 5
        $maturity = Functions::flattenSingleValue($maturity);
776 5
        $frequency = (int) Functions::flattenSingleValue($frequency);
777 5
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
778
779 5
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
780 1
            return Functions::VALUE();
781
        }
782 4
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
783 1
            return Functions::VALUE();
784
        }
785
786 3
        if (($settlement > $maturity) ||
787 3
            (!self::isValidFrequency($frequency)) ||
788 3
            (($basis < 0) || ($basis > 4))) {
789 1
            return Functions::NAN();
790
        }
791
792 2
        return self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
793
    }
794
795
    /**
796
     * CUMIPMT.
797
     *
798
     * Returns the cumulative interest paid on a loan between the start and end periods.
799
     *
800
     * Excel Function:
801
     *        CUMIPMT(rate,nper,pv,start,end[,type])
802
     *
803
     * @category Financial Functions
804
     *
805
     * @param float $rate The Interest rate
806
     * @param int $nper The total number of payment periods
807
     * @param float $pv Present Value
808
     * @param int $start The first period in the calculation.
809
     *                            Payment periods are numbered beginning with 1.
810
     * @param int $end the last period in the calculation
811
     * @param int $type A number 0 or 1 and indicates when payments are due:
812
     *                                0 or omitted    At the end of the period.
813
     *                                1                At the beginning of the period.
814
     *
815
     * @return float
816
     */
817 9 View Code Duplication
    public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
818
    {
819 9
        $rate = Functions::flattenSingleValue($rate);
820 9
        $nper = (int) Functions::flattenSingleValue($nper);
821 9
        $pv = Functions::flattenSingleValue($pv);
822 9
        $start = (int) Functions::flattenSingleValue($start);
823 9
        $end = (int) Functions::flattenSingleValue($end);
824 9
        $type = (int) Functions::flattenSingleValue($type);
825
826
        // Validate parameters
827 9
        if ($type != 0 && $type != 1) {
828 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
829
        }
830 8
        if ($start < 1 || $start > $end) {
831 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
832
        }
833
834
        // Calculate
835 7
        $interest = 0;
836 7
        for ($per = $start; $per <= $end; ++$per) {
837 7
            $interest += self::IPMT($rate, $per, $nper, $pv, 0, $type);
838
        }
839
840 7
        return $interest;
841
    }
842
843
    /**
844
     * CUMPRINC.
845
     *
846
     * Returns the cumulative principal paid on a loan between the start and end periods.
847
     *
848
     * Excel Function:
849
     *        CUMPRINC(rate,nper,pv,start,end[,type])
850
     *
851
     * @category Financial Functions
852
     *
853
     * @param float $rate The Interest rate
854
     * @param int $nper The total number of payment periods
855
     * @param float $pv Present Value
856
     * @param int $start The first period in the calculation.
857
     *                            Payment periods are numbered beginning with 1.
858
     * @param int $end the last period in the calculation
859
     * @param int $type A number 0 or 1 and indicates when payments are due:
860
     *                                0 or omitted    At the end of the period.
861
     *                                1                At the beginning of the period.
862
     *
863
     * @return float
864
     */
865 9 View Code Duplication
    public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
866
    {
867 9
        $rate = Functions::flattenSingleValue($rate);
868 9
        $nper = (int) Functions::flattenSingleValue($nper);
869 9
        $pv = Functions::flattenSingleValue($pv);
870 9
        $start = (int) Functions::flattenSingleValue($start);
871 9
        $end = (int) Functions::flattenSingleValue($end);
872 9
        $type = (int) Functions::flattenSingleValue($type);
873
874
        // Validate parameters
875 9
        if ($type != 0 && $type != 1) {
876 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
877
        }
878 8
        if ($start < 1 || $start > $end) {
879 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
880
        }
881
882
        // Calculate
883 7
        $principal = 0;
884 7
        for ($per = $start; $per <= $end; ++$per) {
885 7
            $principal += self::PPMT($rate, $per, $nper, $pv, 0, $type);
886
        }
887
888 7
        return $principal;
889
    }
890
891
    /**
892
     * DB.
893
     *
894
     * Returns the depreciation of an asset for a specified period using the
895
     * fixed-declining balance method.
896
     * This form of depreciation is used if you want to get a higher depreciation value
897
     * at the beginning of the depreciation (as opposed to linear depreciation). The
898
     * depreciation value is reduced with every depreciation period by the depreciation
899
     * already deducted from the initial cost.
900
     *
901
     * Excel Function:
902
     *        DB(cost,salvage,life,period[,month])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\month was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
903
     *
904
     * @category Financial Functions
905
     *
906
     * @param float cost Initial cost of the asset
907
     * @param float salvage Value at the end of the depreciation.
908
     *                                (Sometimes called the salvage value of the asset)
909
     * @param int life Number of periods over which the asset is depreciated.
910
     *                                (Sometimes called the useful life of the asset)
911
     * @param int period The period for which you want to calculate the
912
     *                                depreciation. Period must use the same units as life.
913
     * @param int month Number of months in the first year. If month is omitted,
914
     *                                it defaults to 12.
915
     * @param mixed $cost
916
     * @param mixed $salvage
917
     * @param mixed $life
918
     * @param mixed $period
919
     * @param mixed $month
920
     *
921
     * @return float
922
     */
923 16
    public static function DB($cost, $salvage, $life, $period, $month = 12)
924
    {
925 16
        $cost = Functions::flattenSingleValue($cost);
926 16
        $salvage = Functions::flattenSingleValue($salvage);
927 16
        $life = Functions::flattenSingleValue($life);
928 16
        $period = Functions::flattenSingleValue($period);
929 16
        $month = Functions::flattenSingleValue($month);
930
931
        //    Validate
932 16
        if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month))) {
933 15
            $cost = (float) $cost;
934 15
            $salvage = (float) $salvage;
935 15
            $life = (int) $life;
936 15
            $period = (int) $period;
937 15
            $month = (int) $month;
938 15
            if ($cost == 0) {
939 1
                return 0.0;
940 14
            } elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1)) {
941 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
942
            }
943
            //    Set Fixed Depreciation Rate
944 13
            $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
945 13
            $fixedDepreciationRate = round($fixedDepreciationRate, 3);
946
947
            //    Loop through each period calculating the depreciation
948 13
            $previousDepreciation = 0;
949 13
            for ($per = 1; $per <= $period; ++$per) {
950 13
                if ($per == 1) {
951 13
                    $depreciation = $cost * $fixedDepreciationRate * $month / 12;
952 11
                } elseif ($per == ($life + 1)) {
953 2
                    $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12;
954
                } else {
955 11
                    $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate;
956
                }
957 13
                $previousDepreciation += $depreciation;
958
            }
959 13
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
960
                $depreciation = round($depreciation, 2);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $depreciation does not seem to be defined for all execution paths leading up to this point.
Loading history...
961
            }
962
963 13
            return $depreciation;
964
        }
965
966 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
967
    }
968
969
    /**
970
     * DDB.
971
     *
972
     * Returns the depreciation of an asset for a specified period using the
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\period was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
973
     * double-declining balance method or some other method you specify.
974
     *
975
     * Excel Function:
976
     *        DDB(cost,salvage,life,period[,factor])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\factor was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
977
     *
978
     * @category Financial Functions
979
     *
980
     * @param float cost Initial cost of the asset
981
     * @param float salvage Value at the end of the depreciation.
982
     *                                (Sometimes called the salvage value of the asset)
983
     * @param int life Number of periods over which the asset is depreciated.
984
     *                                (Sometimes called the useful life of the asset)
985
     * @param int period The period for which you want to calculate the
986
     *                                depreciation. Period must use the same units as life.
987
     * @param float factor The rate at which the balance declines.
988
     *                                If factor is omitted, it is assumed to be 2 (the
989
     *                                double-declining balance method).
990
     * @param mixed $cost
991
     * @param mixed $salvage
992
     * @param mixed $life
993
     * @param mixed $period
994
     * @param mixed $factor
995
     *
996
     * @return float
997
     */
998 15
    public static function DDB($cost, $salvage, $life, $period, $factor = 2.0)
999
    {
1000 15
        $cost = Functions::flattenSingleValue($cost);
1001 15
        $salvage = Functions::flattenSingleValue($salvage);
1002 15
        $life = Functions::flattenSingleValue($life);
1003 15
        $period = Functions::flattenSingleValue($period);
1004 15
        $factor = Functions::flattenSingleValue($factor);
1005
1006
        //    Validate
1007 15
        if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor))) {
1008 14
            $cost = (float) $cost;
1009 14
            $salvage = (float) $salvage;
1010 14
            $life = (int) $life;
1011 14
            $period = (int) $period;
1012 14
            $factor = (float) $factor;
1013 14
            if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life)) {
1014 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1015
            }
1016
            //    Set Fixed Depreciation Rate
1017 13
            $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
1018 13
            $fixedDepreciationRate = round($fixedDepreciationRate, 3);
0 ignored issues
show
Unused Code introduced by
The assignment to $fixedDepreciationRate is dead and can be removed.
Loading history...
1019
1020
            //    Loop through each period calculating the depreciation
1021 13
            $previousDepreciation = 0;
1022 13
            for ($per = 1; $per <= $period; ++$per) {
1023 13
                $depreciation = min(($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation));
1024 13
                $previousDepreciation += $depreciation;
1025
            }
1026 13
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC) {
1027
                $depreciation = round($depreciation, 2);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $depreciation does not seem to be defined for all execution paths leading up to this point.
Loading history...
1028
            }
1029
1030 13
            return $depreciation;
1031
        }
1032
1033 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1034
    }
1035
1036
    /**
1037
     * DISC.
1038
     *
1039
     * Returns the discount rate for a security.
1040
     *
1041
     * Excel Function:
1042
     *        DISC(settlement,maturity,price,redemption[,basis])
1043
     *
1044
     * @category Financial Functions
1045
     *
1046
     * @param mixed settlement The security's settlement date.
1047
     *                                The security settlement date is the date after the issue
1048
     *                                date when the security is traded to the buyer.
1049
     * @param mixed maturity The security's maturity date.
1050
     *                                The maturity date is the date when the security expires.
1051
     * @param int price The security's price per $100 face value
1052
     * @param int redemption The security's redemption value per $100 face value
1053
     * @param int basis The type of day count to use.
1054
     *                                        0 or omitted    US (NASD) 30/360
1055
     *                                        1                Actual/actual
1056
     *                                        2                Actual/360
1057
     *                                        3                Actual/365
1058
     *                                        4                European 30/360
1059
     * @param mixed $settlement
1060
     * @param mixed $maturity
1061
     * @param mixed $price
1062
     * @param mixed $redemption
1063
     * @param mixed $basis
1064
     *
1065
     * @return float
1066
     */
1067 5 View Code Duplication
    public static function DISC($settlement, $maturity, $price, $redemption, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1068
    {
1069 5
        $settlement = Functions::flattenSingleValue($settlement);
1070 5
        $maturity = Functions::flattenSingleValue($maturity);
1071 5
        $price = Functions::flattenSingleValue($price);
1072 5
        $redemption = Functions::flattenSingleValue($redemption);
1073 5
        $basis = Functions::flattenSingleValue($basis);
1074
1075
        //    Validate
1076 5
        if ((is_numeric($price)) && (is_numeric($redemption)) && (is_numeric($basis))) {
1077 4
            $price = (float) $price;
1078 4
            $redemption = (float) $redemption;
1079 4
            $basis = (int) $basis;
1080 4
            if (($price <= 0) || ($redemption <= 0)) {
1081 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1082
            }
1083 3
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
1084 3
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1085
                //    return date error
1086 1
                return $daysBetweenSettlementAndMaturity;
1087
            }
1088
1089 2
            return (1 - $price / $redemption) / $daysBetweenSettlementAndMaturity;
1090
        }
1091
1092 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1093
    }
1094
1095
    /**
1096
     * DOLLARDE.
1097
     *
1098
     * Converts a dollar price expressed as an integer part and a fraction
1099
     *        part into a dollar price expressed as a decimal number.
1100
     * Fractional dollar numbers are sometimes used for security prices.
1101
     *
1102
     * Excel Function:
1103
     *        DOLLARDE(fractional_dollar,fraction)
1104
     *
1105
     * @category Financial Functions
1106
     *
1107
     * @param float $fractional_dollar Fractional Dollar
1108
     * @param int $fraction Fraction
1109
     *
1110
     * @return float
1111
     */
1112 9 View Code Duplication
    public static function DOLLARDE($fractional_dollar = null, $fraction = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1113
    {
1114 9
        $fractional_dollar = Functions::flattenSingleValue($fractional_dollar);
1115 9
        $fraction = (int) Functions::flattenSingleValue($fraction);
1116
1117
        // Validate parameters
1118 9
        if ($fractional_dollar === null || $fraction < 0) {
1119 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1120
        }
1121 8
        if ($fraction == 0) {
1122 1
            return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
1123
        }
1124
1125 7
        $dollars = floor($fractional_dollar);
1126 7
        $cents = fmod($fractional_dollar, 1);
1127 7
        $cents /= $fraction;
1128 7
        $cents *= pow(10, ceil(log10($fraction)));
1129
1130 7
        return $dollars + $cents;
1131
    }
1132
1133
    /**
1134
     * DOLLARFR.
1135
     *
1136
     * Converts a dollar price expressed as a decimal number into a dollar price
1137
     *        expressed as a fraction.
1138
     * Fractional dollar numbers are sometimes used for security prices.
1139
     *
1140
     * Excel Function:
1141
     *        DOLLARFR(decimal_dollar,fraction)
1142
     *
1143
     * @category Financial Functions
1144
     *
1145
     * @param float $decimal_dollar Decimal Dollar
1146
     * @param int $fraction Fraction
1147
     *
1148
     * @return float
1149
     */
1150 9 View Code Duplication
    public static function DOLLARFR($decimal_dollar = null, $fraction = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1151
    {
1152 9
        $decimal_dollar = Functions::flattenSingleValue($decimal_dollar);
1153 9
        $fraction = (int) Functions::flattenSingleValue($fraction);
1154
1155
        // Validate parameters
1156 9
        if ($decimal_dollar === null || $fraction < 0) {
1157 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1158
        }
1159 8
        if ($fraction == 0) {
1160 1
            return Functions::DIV0();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...ation\Functions::DIV0() returns the type string which is incompatible with the documented return type double.
Loading history...
1161
        }
1162
1163 7
        $dollars = floor($decimal_dollar);
1164 7
        $cents = fmod($decimal_dollar, 1);
1165 7
        $cents *= $fraction;
1166 7
        $cents *= pow(10, -ceil(log10($fraction)));
1167
1168 7
        return $dollars + $cents;
1169
    }
1170
1171
    /**
1172
     * EFFECT.
1173
     *
1174
     * Returns the effective interest rate given the nominal rate and the number of
1175
     *        compounding payments per year.
1176
     *
1177
     * Excel Function:
1178
     *        EFFECT(nominal_rate,npery)
1179
     *
1180
     * @category Financial Functions
1181
     *
1182
     * @param float $nominal_rate Nominal interest rate
1183
     * @param int $npery Number of compounding payments per year
1184
     *
1185
     * @return float
1186
     */
1187 5 View Code Duplication
    public static function EFFECT($nominal_rate = 0, $npery = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1188
    {
1189 5
        $nominal_rate = Functions::flattenSingleValue($nominal_rate);
1190 5
        $npery = (int) Functions::flattenSingleValue($npery);
1191
1192
        // Validate parameters
1193 5
        if ($nominal_rate <= 0 || $npery < 1) {
1194 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1195
        }
1196
1197 4
        return pow((1 + $nominal_rate / $npery), $npery) - 1;
1198
    }
1199
1200
    /**
1201
     * FV.
1202
     *
1203
     * Returns the Future Value of a cash flow with constant payments and interest rate (annuities).
1204
     *
1205
     * Excel Function:
1206
     *        FV(rate,nper,pmt[,pv[,type]])
1207
     *
1208
     * @category Financial Functions
1209
     *
1210
     * @param float $rate The interest rate per period
1211
     * @param int $nper Total number of payment periods in an annuity
1212
     * @param float $pmt The payment made each period: it cannot change over the
1213
     *                            life of the annuity. Typically, pmt contains principal
1214
     *                            and interest but no other fees or taxes.
1215
     * @param float $pv present Value, or the lump-sum amount that a series of
1216
     *                            future payments is worth right now
1217
     * @param int $type A number 0 or 1 and indicates when payments are due:
1218
     *                                0 or omitted    At the end of the period.
1219
     *                                1                At the beginning of the period.
1220
     *
1221
     * @return float
1222
     */
1223 8 View Code Duplication
    public static function FV($rate = 0, $nper = 0, $pmt = 0, $pv = 0, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1224
    {
1225 8
        $rate = Functions::flattenSingleValue($rate);
1226 8
        $nper = Functions::flattenSingleValue($nper);
1227 8
        $pmt = Functions::flattenSingleValue($pmt);
1228 8
        $pv = Functions::flattenSingleValue($pv);
1229 8
        $type = Functions::flattenSingleValue($type);
1230
1231
        // Validate parameters
1232 8
        if ($type != 0 && $type != 1) {
1233 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1234
        }
1235
1236
        // Calculate
1237 7
        if ($rate !== null && $rate != 0) {
1238 6
            return -$pv * pow(1 + $rate, $nper) - $pmt * (1 + $rate * $type) * (pow(1 + $rate, $nper) - 1) / $rate;
1239
        }
1240
1241 1
        return -$pv - $pmt * $nper;
1242
    }
1243
1244
    /**
1245
     * FVSCHEDULE.
1246
     *
1247
     * Returns the future value of an initial principal after applying a series of compound interest rates.
1248
     * Use FVSCHEDULE to calculate the future value of an investment with a variable or adjustable rate.
1249
     *
1250
     * Excel Function:
1251
     *        FVSCHEDULE(principal,schedule)
1252
     *
1253
     * @param float $principal the present value
1254
     * @param float[] $schedule an array of interest rates to apply
1255
     *
1256
     * @return float
1257
     */
1258 3
    public static function FVSCHEDULE($principal, $schedule)
1259
    {
1260 3
        $principal = Functions::flattenSingleValue($principal);
1261 3
        $schedule = Functions::flattenArray($schedule);
1262
1263 3
        foreach ($schedule as $rate) {
1264 3
            $principal *= 1 + $rate;
1265
        }
1266
1267 3
        return $principal;
1268
    }
1269
1270
    /**
1271
     * INTRATE.
1272
     *
1273
     * Returns the interest rate for a fully invested security.
1274
     *
1275
     * Excel Function:
1276
     *        INTRATE(settlement,maturity,investment,redemption[,basis])
1277
     *
1278
     * @param mixed $settlement The security's settlement date.
1279
     *                                The security settlement date is the date after the issue date when the security is traded to the buyer.
1280
     * @param mixed $maturity The security's maturity date.
1281
     *                                The maturity date is the date when the security expires.
1282
     * @param int $investment the amount invested in the security
1283
     * @param int $redemption the amount to be received at maturity
1284
     * @param int $basis The type of day count to use.
1285
     *                                        0 or omitted    US (NASD) 30/360
1286
     *                                        1                Actual/actual
1287
     *                                        2                Actual/360
1288
     *                                        3                Actual/365
1289
     *                                        4                European 30/360
1290
     *
1291
     * @return float
1292
     */
1293 5 View Code Duplication
    public static function INTRATE($settlement, $maturity, $investment, $redemption, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1294
    {
1295 5
        $settlement = Functions::flattenSingleValue($settlement);
1296 5
        $maturity = Functions::flattenSingleValue($maturity);
1297 5
        $investment = Functions::flattenSingleValue($investment);
1298 5
        $redemption = Functions::flattenSingleValue($redemption);
1299 5
        $basis = Functions::flattenSingleValue($basis);
1300
1301
        //    Validate
1302 5
        if ((is_numeric($investment)) && (is_numeric($redemption)) && (is_numeric($basis))) {
1303 4
            $investment = (float) $investment;
1304 4
            $redemption = (float) $redemption;
1305 4
            $basis = (int) $basis;
1306 4
            if (($investment <= 0) || ($redemption <= 0)) {
1307 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1308
            }
1309 3
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
1310 3
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1311
                //    return date error
1312 1
                return $daysBetweenSettlementAndMaturity;
1313
            }
1314
1315 2
            return (($redemption / $investment) - 1) / ($daysBetweenSettlementAndMaturity);
1316
        }
1317
1318 1
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1319
    }
1320
1321
    /**
1322
     * IPMT.
1323
     *
1324
     * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
1325
     *
1326
     * Excel Function:
1327
     *        IPMT(rate,per,nper,pv[,fv][,type])
1328
     *
1329
     * @param float $rate Interest rate per period
1330
     * @param int $per Period for which we want to find the interest
1331
     * @param int $nper Number of periods
1332
     * @param float $pv Present Value
1333
     * @param float $fv Future Value
1334
     * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
1335
     *
1336
     * @return float
1337
     */
1338 15 View Code Duplication
    public static function IPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1339
    {
1340 15
        $rate = Functions::flattenSingleValue($rate);
1341 15
        $per = (int) Functions::flattenSingleValue($per);
1342 15
        $nper = (int) Functions::flattenSingleValue($nper);
1343 15
        $pv = Functions::flattenSingleValue($pv);
1344 15
        $fv = Functions::flattenSingleValue($fv);
1345 15
        $type = (int) Functions::flattenSingleValue($type);
1346
1347
        // Validate parameters
1348 15
        if ($type != 0 && $type != 1) {
1349 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1350
        }
1351 14
        if ($per <= 0 || $per > $nper) {
1352 1
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1353
        }
1354
1355
        // Calculate
1356 13
        $interestAndPrincipal = self::interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type);
1357
1358 13
        return $interestAndPrincipal[0];
1359
    }
1360
1361
    /**
1362
     * IRR.
1363
     *
1364
     * Returns the internal rate of return for a series of cash flows represented by the numbers in values.
1365
     * These cash flows do not have to be even, as they would be for an annuity. However, the cash flows must occur
1366
     * at regular intervals, such as monthly or annually. The internal rate of return is the interest rate received
1367
     * for an investment consisting of payments (negative values) and income (positive values) that occur at regular
1368
     * periods.
1369
     *
1370
     * Excel Function:
1371
     *        IRR(values[,guess])
1372
     *
1373
     * @param float[] $values An array or a reference to cells that contain numbers for which you want
1374
     *                                    to calculate the internal rate of return.
1375
     *                                Values must contain at least one positive value and one negative value to
1376
     *                                    calculate the internal rate of return.
1377
     * @param float $guess A number that you guess is close to the result of IRR
1378
     *
1379
     * @return float
1380
     */
1381 5
    public static function IRR($values, $guess = 0.1)
1382
    {
1383 5
        if (!is_array($values)) {
1384
            return Functions::VALUE();
1385
        }
1386 5
        $values = Functions::flattenArray($values);
1387 5
        $guess = Functions::flattenSingleValue($guess);
1388
1389
        // create an initial range, with a root somewhere between 0 and guess
1390 5
        $x1 = 0.0;
1391 5
        $x2 = $guess;
1392 5
        $f1 = self::NPV($x1, $values);
1393 5
        $f2 = self::NPV($x2, $values);
1394 5 View Code Duplication
        for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1395 5
            if (($f1 * $f2) < 0.0) {
1396 5
                break;
1397
            }
1398 4
            if (abs($f1) < abs($f2)) {
1399 3
                $f1 = self::NPV($x1 += 1.6 * ($x1 - $x2), $values);
1400
            } else {
1401 1
                $f2 = self::NPV($x2 += 1.6 * ($x2 - $x1), $values);
1402
            }
1403
        }
1404 5
        if (($f1 * $f2) > 0.0) {
1405
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1406
        }
1407
1408 5
        $f = self::NPV($x1, $values);
1409 5 View Code Duplication
        if ($f < 0.0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1410
            $rtb = $x1;
1411
            $dx = $x2 - $x1;
1412
        } else {
1413 5
            $rtb = $x2;
1414 5
            $dx = $x1 - $x2;
1415
        }
1416
1417 5 View Code Duplication
        for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1418 5
            $dx *= 0.5;
1419 5
            $x_mid = $rtb + $dx;
1420 5
            $f_mid = self::NPV($x_mid, $values);
1421 5
            if ($f_mid <= 0.0) {
1422 5
                $rtb = $x_mid;
1423
            }
1424 5
            if ((abs($f_mid) < self::FINANCIAL_PRECISION) || (abs($dx) < self::FINANCIAL_PRECISION)) {
1425 5
                return $x_mid;
1426
            }
1427
        }
1428
1429
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1430
    }
1431
1432
    /**
1433
     * ISPMT.
1434
     *
1435
     * Returns the interest payment for an investment based on an interest rate and a constant payment schedule.
1436
     *
1437
     * Excel Function:
1438
     *     =ISPMT(interest_rate, period, number_payments, PV)
1439
     *
1440
     * interest_rate is the interest rate for the investment
1441
     *
1442
     * period is the period to calculate the interest rate.  It must be betweeen 1 and number_payments.
1443
     *
1444
     * number_payments is the number of payments for the annuity
1445
     *
1446
     * PV is the loan amount or present value of the payments
1447
     */
1448 4
    public static function ISPMT(...$args)
1449
    {
1450
        // Return value
1451 4
        $returnValue = 0;
1452
1453
        // Get the parameters
1454 4
        $aArgs = Functions::flattenArray($args);
1455 4
        $interestRate = array_shift($aArgs);
1456 4
        $period = array_shift($aArgs);
1457 4
        $numberPeriods = array_shift($aArgs);
1458 4
        $principleRemaining = array_shift($aArgs);
1459
1460
        // Calculate
1461 4
        $principlePayment = ($principleRemaining * 1.0) / ($numberPeriods * 1.0);
1462 4
        for ($i = 0; $i <= $period; ++$i) {
1463 4
            $returnValue = $interestRate * $principleRemaining * -1;
1464 4
            $principleRemaining -= $principlePayment;
1465
            // principle needs to be 0 after the last payment, don't let floating point screw it up
1466 4
            if ($i == $numberPeriods) {
1467
                $returnValue = 0;
1468
            }
1469
        }
1470
1471 4
        return $returnValue;
1472
    }
1473
1474
    /**
1475
     * MIRR.
1476
     *
1477
     * Returns the modified internal rate of return for a series of periodic cash flows. MIRR considers both
1478
     *        the cost of the investment and the interest received on reinvestment of cash.
1479
     *
1480
     * Excel Function:
1481
     *        MIRR(values,finance_rate, reinvestment_rate)
1482
     *
1483
     * @param float[] $values An array or a reference to cells that contain a series of payments and
1484
     *                                            income occurring at regular intervals.
1485
     *                                        Payments are negative value, income is positive values.
1486
     * @param float $finance_rate The interest rate you pay on the money used in the cash flows
1487
     * @param float $reinvestment_rate The interest rate you receive on the cash flows as you reinvest them
1488
     *
1489
     * @return float
1490
     */
1491 5
    public static function MIRR($values, $finance_rate, $reinvestment_rate)
1492
    {
1493 5
        if (!is_array($values)) {
1494
            return Functions::VALUE();
1495
        }
1496 5
        $values = Functions::flattenArray($values);
1497 5
        $finance_rate = Functions::flattenSingleValue($finance_rate);
1498 5
        $reinvestment_rate = Functions::flattenSingleValue($reinvestment_rate);
1499 5
        $n = count($values);
1500
1501 5
        $rr = 1.0 + $reinvestment_rate;
1502 5
        $fr = 1.0 + $finance_rate;
1503
1504 5
        $npv_pos = $npv_neg = 0.0;
1505 5
        foreach ($values as $i => $v) {
1506 5
            if ($v >= 0) {
1507 5
                $npv_pos += $v / pow($rr, $i);
1508
            } else {
1509 5
                $npv_neg += $v / pow($fr, $i);
1510
            }
1511
        }
1512
1513 5
        if (($npv_neg == 0) || ($npv_pos == 0) || ($reinvestment_rate <= -1)) {
1514
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1515
        }
1516
1517 5
        $mirr = pow((-$npv_pos * pow($rr, $n))
1518 5
                / ($npv_neg * ($rr)), (1.0 / ($n - 1))) - 1.0;
1519
1520 5
        return is_finite($mirr) ? $mirr : Functions::VALUE();
1521
    }
1522
1523
    /**
1524
     * NOMINAL.
1525
     *
1526
     * Returns the nominal interest rate given the effective rate and the number of compounding payments per year.
1527
     *
1528
     * @param float $effect_rate Effective interest rate
1529
     * @param int $npery Number of compounding payments per year
1530
     *
1531
     * @return float
1532
     */
1533 5 View Code Duplication
    public static function NOMINAL($effect_rate = 0, $npery = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1534
    {
1535 5
        $effect_rate = Functions::flattenSingleValue($effect_rate);
1536 5
        $npery = (int) Functions::flattenSingleValue($npery);
1537
1538
        // Validate parameters
1539 5
        if ($effect_rate <= 0 || $npery < 1) {
1540 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1541
        }
1542
1543
        // Calculate
1544 4
        return $npery * (pow($effect_rate + 1, 1 / $npery) - 1);
1545
    }
1546
1547
    /**
1548
     * NPER.
1549
     *
1550
     * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate.
1551
     *
1552
     * @param float $rate Interest rate per period
1553
     * @param int $pmt Periodic payment (annuity)
1554
     * @param float $pv Present Value
1555
     * @param float $fv Future Value
1556
     * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
1557
     *
1558
     * @return float
1559
     */
1560 9
    public static function NPER($rate = 0, $pmt = 0, $pv = 0, $fv = 0, $type = 0)
1561
    {
1562 9
        $rate = Functions::flattenSingleValue($rate);
1563 9
        $pmt = Functions::flattenSingleValue($pmt);
1564 9
        $pv = Functions::flattenSingleValue($pv);
1565 9
        $fv = Functions::flattenSingleValue($fv);
1566 9
        $type = Functions::flattenSingleValue($type);
1567
1568
        // Validate parameters
1569 9
        if ($type != 0 && $type != 1) {
1570 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1571
        }
1572
1573
        // Calculate
1574 8
        if ($rate !== null && $rate != 0) {
1575 6
            if ($pmt == 0 && $pv == 0) {
1576 1
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1577
            }
1578
1579 5
            return log(($pmt * (1 + $rate * $type) / $rate - $fv) / ($pv + $pmt * (1 + $rate * $type) / $rate)) / log(1 + $rate);
1580
        }
1581 2
        if ($pmt == 0) {
1582 1
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1583
        }
1584
1585 1
        return (-$pv - $fv) / $pmt;
1586
    }
1587
1588
    /**
1589
     * NPV.
1590
     *
1591
     * Returns the Net Present Value of a cash flow series given a discount rate.
1592
     *
1593
     * @return float
1594
     */
1595 9
    public static function NPV(...$args)
1596
    {
1597
        // Return value
1598 9
        $returnValue = 0;
1599
1600
        // Loop through arguments
1601 9
        $aArgs = Functions::flattenArray($args);
1602
1603
        // Calculate
1604 9
        $rate = array_shift($aArgs);
1605 9
        for ($i = 1; $i <= count($aArgs); ++$i) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
1606
            // Is it a numeric value?
1607 9
            if (is_numeric($aArgs[$i - 1])) {
1608 9
                $returnValue += $aArgs[$i - 1] / pow(1 + $rate, $i);
1609
            }
1610
        }
1611
1612
        // Return
1613 9
        return $returnValue;
1614
    }
1615
1616
    /**
1617
     * PMT.
1618
     *
1619
     * Returns the constant payment (annuity) for a cash flow with a constant interest rate.
1620
     *
1621
     * @param float $rate Interest rate per period
1622
     * @param int $nper Number of periods
1623
     * @param float $pv Present Value
1624
     * @param float $fv Future Value
1625
     * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
1626
     *
1627
     * @return float
1628
     */
1629 20
    public static function PMT($rate = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
1630
    {
1631 20
        $rate = Functions::flattenSingleValue($rate);
1632 20
        $nper = Functions::flattenSingleValue($nper);
1633 20
        $pv = Functions::flattenSingleValue($pv);
1634 20
        $fv = Functions::flattenSingleValue($fv);
1635 20
        $type = Functions::flattenSingleValue($type);
1636
1637
        // Validate parameters
1638 20
        if ($type != 0 && $type != 1) {
1639
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1640
        }
1641
1642
        // Calculate
1643 20
        if ($rate !== null && $rate != 0) {
1644 20
            return (-$fv - $pv * pow(1 + $rate, $nper)) / (1 + $rate * $type) / ((pow(1 + $rate, $nper) - 1) / $rate);
1645
        }
1646
1647
        return (-$pv - $fv) / $nper;
1648
    }
1649
1650
    /**
1651
     * PPMT.
1652
     *
1653
     * Returns the interest payment for a given period for an investment based on periodic, constant payments and a constant interest rate.
1654
     *
1655
     * @param float $rate Interest rate per period
1656
     * @param int $per Period for which we want to find the interest
1657
     * @param int $nper Number of periods
1658
     * @param float $pv Present Value
1659
     * @param float $fv Future Value
1660
     * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
1661
     *
1662
     * @return float
1663
     */
1664 7 View Code Duplication
    public static function PPMT($rate, $per, $nper, $pv, $fv = 0, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1665
    {
1666 7
        $rate = Functions::flattenSingleValue($rate);
1667 7
        $per = (int) Functions::flattenSingleValue($per);
1668 7
        $nper = (int) Functions::flattenSingleValue($nper);
1669 7
        $pv = Functions::flattenSingleValue($pv);
1670 7
        $fv = Functions::flattenSingleValue($fv);
1671 7
        $type = (int) Functions::flattenSingleValue($type);
1672
1673
        // Validate parameters
1674 7
        if ($type != 0 && $type != 1) {
1675
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1676
        }
1677 7
        if ($per <= 0 || $per > $nper) {
1678
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1679
        }
1680
1681
        // Calculate
1682 7
        $interestAndPrincipal = self::interestAndPrincipal($rate, $per, $nper, $pv, $fv, $type);
1683
1684 7
        return $interestAndPrincipal[1];
1685
    }
1686
1687
    public static function PRICE($settlement, $maturity, $rate, $yield, $redemption, $frequency, $basis = 0)
1688
    {
1689
        $settlement = Functions::flattenSingleValue($settlement);
1690
        $maturity = Functions::flattenSingleValue($maturity);
1691
        $rate = (float) Functions::flattenSingleValue($rate);
1692
        $yield = (float) Functions::flattenSingleValue($yield);
1693
        $redemption = (float) Functions::flattenSingleValue($redemption);
1694
        $frequency = (int) Functions::flattenSingleValue($frequency);
1695
        $basis = ($basis === null) ? 0 : (int) Functions::flattenSingleValue($basis);
1696
1697
        if (is_string($settlement = DateTime::getDateValue($settlement))) {
1698
            return Functions::VALUE();
1699
        }
1700
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
1701
            return Functions::VALUE();
1702
        }
1703
1704
        if (($settlement > $maturity) ||
1705
            (!self::isValidFrequency($frequency)) ||
1706
            (($basis < 0) || ($basis > 4))) {
1707
            return Functions::NAN();
1708
        }
1709
1710
        $dsc = self::COUPDAYSNC($settlement, $maturity, $frequency, $basis);
1711
        $e = self::COUPDAYS($settlement, $maturity, $frequency, $basis);
1712
        $n = self::COUPNUM($settlement, $maturity, $frequency, $basis);
1713
        $a = self::COUPDAYBS($settlement, $maturity, $frequency, $basis);
1714
1715
        $baseYF = 1.0 + ($yield / $frequency);
1716
        $rfp = 100 * ($rate / $frequency);
1717
        $de = $dsc / $e;
1718
1719
        $result = $redemption / pow($baseYF, (--$n + $de));
1720
        for ($k = 0; $k <= $n; ++$k) {
1721
            $result += $rfp / (pow($baseYF, ($k + $de)));
1722
        }
1723
        $result -= $rfp * ($a / $e);
1724
1725
        return $result;
1726
    }
1727
1728
    /**
1729
     * PRICEDISC.
1730
     *
1731
     * Returns the price per $100 face value of a discounted security.
1732
     *
1733
     * @param mixed settlement The security's settlement date.
1734
     *                                The security settlement date is the date after the issue date when the security is traded to the buyer.
1735
     * @param mixed maturity The security's maturity date.
1736
     *                                The maturity date is the date when the security expires.
1737
     * @param int discount The security's discount rate
1738
     * @param int redemption The security's redemption value per $100 face value
1739
     * @param int basis The type of day count to use.
1740
     *                                        0 or omitted    US (NASD) 30/360
1741
     *                                        1                Actual/actual
1742
     *                                        2                Actual/360
1743
     *                                        3                Actual/365
1744
     *                                        4                European 30/360
1745
     * @param mixed $settlement
1746
     * @param mixed $maturity
1747
     * @param mixed $discount
1748
     * @param mixed $redemption
1749
     * @param mixed $basis
1750
     *
1751
     * @return float
1752
     */
1753 View Code Duplication
    public static function PRICEDISC($settlement, $maturity, $discount, $redemption, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1754
    {
1755
        $settlement = Functions::flattenSingleValue($settlement);
1756
        $maturity = Functions::flattenSingleValue($maturity);
1757
        $discount = (float) Functions::flattenSingleValue($discount);
1758
        $redemption = (float) Functions::flattenSingleValue($redemption);
1759
        $basis = (int) Functions::flattenSingleValue($basis);
1760
1761
        //    Validate
1762
        if ((is_numeric($discount)) && (is_numeric($redemption)) && (is_numeric($basis))) {
1763
            if (($discount <= 0) || ($redemption <= 0)) {
1764
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1765
            }
1766
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
1767
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1768
                //    return date error
1769
                return $daysBetweenSettlementAndMaturity;
1770
            }
1771
1772
            return $redemption * (1 - $discount * $daysBetweenSettlementAndMaturity);
1773
        }
1774
1775
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1776
    }
1777
1778
    /**
1779
     * PRICEMAT.
1780
     *
1781
     * Returns the price per $100 face value of a security that pays interest at maturity.
1782
     *
1783
     * @param mixed settlement The security's settlement date.
1784
     *                                The security's settlement date is the date after the issue date when the security is traded to the buyer.
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\issue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1785
     * @param mixed maturity The security's maturity date.
1786
     *                                The maturity date is the date when the security expires.
1787
     * @param mixed issue The security's issue date
1788
     * @param int rate The security's interest rate at date of issue
1789
     * @param int yield The security's annual yield
1790
     * @param int basis The type of day count to use.
1791
     *                                        0 or omitted    US (NASD) 30/360
1792
     *                                        1                Actual/actual
1793
     *                                        2                Actual/360
1794
     *                                        3                Actual/365
1795
     *                                        4                European 30/360
1796
     * @param mixed $settlement
1797
     * @param mixed $maturity
1798
     * @param mixed $issue
1799
     * @param mixed $rate
1800
     * @param mixed $yield
1801
     * @param mixed $basis
1802
     *
1803
     * @return float
1804
     */
1805
    public static function PRICEMAT($settlement, $maturity, $issue, $rate, $yield, $basis = 0)
1806
    {
1807
        $settlement = Functions::flattenSingleValue($settlement);
1808
        $maturity = Functions::flattenSingleValue($maturity);
1809
        $issue = Functions::flattenSingleValue($issue);
1810
        $rate = Functions::flattenSingleValue($rate);
1811
        $yield = Functions::flattenSingleValue($yield);
1812
        $basis = (int) Functions::flattenSingleValue($basis);
1813
1814
        //    Validate
1815
        if (is_numeric($rate) && is_numeric($yield)) {
1816
            if (($rate <= 0) || ($yield <= 0)) {
1817
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1818
            }
1819
            $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
1820
            if (!is_numeric($daysPerYear)) {
1821
                return $daysPerYear;
1822
            }
1823
            $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis);
1824
            if (!is_numeric($daysBetweenIssueAndSettlement)) {
1825
                //    return date error
1826
                return $daysBetweenIssueAndSettlement;
1827
            }
1828
            $daysBetweenIssueAndSettlement *= $daysPerYear;
1829
            $daysBetweenIssueAndMaturity = DateTime::YEARFRAC($issue, $maturity, $basis);
1830
            if (!is_numeric($daysBetweenIssueAndMaturity)) {
1831
                //    return date error
1832
                return $daysBetweenIssueAndMaturity;
1833
            }
1834
            $daysBetweenIssueAndMaturity *= $daysPerYear;
1835
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
1836
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
1837
                //    return date error
1838
                return $daysBetweenSettlementAndMaturity;
1839
            }
1840
            $daysBetweenSettlementAndMaturity *= $daysPerYear;
1841
1842
            return (100 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate * 100)) /
1843
                   (1 + (($daysBetweenSettlementAndMaturity / $daysPerYear) * $yield)) -
1844
                   (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate * 100);
1845
        }
1846
1847
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
1848
    }
1849
1850
    /**
1851
     * PV.
1852
     *
1853
     * Returns the Present Value of a cash flow with constant payments and interest rate (annuities).
1854
     *
1855
     * @param float $rate Interest rate per period
1856
     * @param int $nper Number of periods
1857
     * @param float $pmt Periodic payment (annuity)
1858
     * @param float $fv Future Value
1859
     * @param int $type Payment type: 0 = at the end of each period, 1 = at the beginning of each period
1860
     *
1861
     * @return float
1862
     */
1863 View Code Duplication
    public static function PV($rate = 0, $nper = 0, $pmt = 0, $fv = 0, $type = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1864
    {
1865
        $rate = Functions::flattenSingleValue($rate);
1866
        $nper = Functions::flattenSingleValue($nper);
1867
        $pmt = Functions::flattenSingleValue($pmt);
1868
        $fv = Functions::flattenSingleValue($fv);
1869
        $type = Functions::flattenSingleValue($type);
1870
1871
        // Validate parameters
1872
        if ($type != 0 && $type != 1) {
1873
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
1874
        }
1875
1876
        // Calculate
1877
        if ($rate !== null && $rate != 0) {
1878
            return (-$pmt * (1 + $rate * $type) * ((pow(1 + $rate, $nper) - 1) / $rate) - $fv) / pow(1 + $rate, $nper);
1879
        }
1880
1881
        return -$fv - $pmt * $nper;
1882
    }
1883
1884
    /**
1885
     * RATE.
1886
     *
1887
     * Returns the interest rate per period of an annuity.
1888
     * RATE is calculated by iteration and can have zero or more solutions.
1889
     * If the successive results of RATE do not converge to within 0.0000001 after 20 iterations,
1890
     * RATE returns the #NUM! error value.
1891
     *
1892
     * Excel Function:
1893
     *        RATE(nper,pmt,pv[,fv[,type[,guess]]])
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\guess was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1894
     *
1895
     * @category Financial Functions
1896
     *
1897
     * @param float nper The total number of payment periods in an annuity
1898
     * @param float pmt The payment made each period and cannot change over the life
1899
     *                                    of the annuity.
1900
     *                                Typically, pmt includes principal and interest but no other
1901
     *                                    fees or taxes.
1902
     * @param float pv The present value - the total amount that a series of future
1903
     *                                    payments is worth now
1904
     * @param float fv The future value, or a cash balance you want to attain after
1905
     *                                    the last payment is made. If fv is omitted, it is assumed
1906
     *                                    to be 0 (the future value of a loan, for example, is 0).
1907
     * @param int type A number 0 or 1 and indicates when payments are due:
1908
     *                                        0 or omitted    At the end of the period.
1909
     *                                        1                At the beginning of the period.
1910
     * @param float guess Your guess for what the rate will be.
1911
     *                                    If you omit guess, it is assumed to be 10 percent.
1912
     * @param mixed $nper
1913
     * @param mixed $pmt
1914
     * @param mixed $pv
1915
     * @param mixed $fv
1916
     * @param mixed $type
1917
     * @param mixed $guess
1918
     *
1919
     * @return float
1920
     **/
1921
    public static function RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1)
1922
    {
1923
        $nper = (int) Functions::flattenSingleValue($nper);
1924
        $pmt = Functions::flattenSingleValue($pmt);
1925
        $pv = Functions::flattenSingleValue($pv);
1926
        $fv = ($fv === null) ? 0.0 : Functions::flattenSingleValue($fv);
1927
        $type = ($type === null) ? 0 : (int) Functions::flattenSingleValue($type);
1928
        $guess = ($guess === null) ? 0.1 : Functions::flattenSingleValue($guess);
1929
1930
        $rate = $guess;
1931 View Code Duplication
        if (abs($rate) < self::FINANCIAL_PRECISION) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1932
            $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
0 ignored issues
show
Unused Code introduced by
The assignment to $y is dead and can be removed.
Loading history...
1933
        } else {
1934
            $f = exp($nper * log(1 + $rate));
1935
            $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
1936
        }
1937
        $y0 = $pv + $pmt * $nper + $fv;
1938
        $y1 = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $f does not seem to be defined for all execution paths leading up to this point.
Loading history...
1939
1940
        // find root by secant method
1941
        $i = $x0 = 0.0;
1942
        $x1 = $rate;
1943
        while ((abs($y0 - $y1) > self::FINANCIAL_PRECISION) && ($i < self::FINANCIAL_MAX_ITERATIONS)) {
1944
            $rate = ($y1 * $x0 - $y0 * $x1) / ($y1 - $y0);
1945
            $x0 = $x1;
1946
            $x1 = $rate;
1947
            if (($nper * abs($pmt)) > ($pv - $fv)) {
1948
                $x1 = abs($x1);
1949
            }
1950 View Code Duplication
            if (abs($rate) < self::FINANCIAL_PRECISION) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1951
                $y = $pv * (1 + $nper * $rate) + $pmt * (1 + $rate * $type) * $nper + $fv;
1952
            } else {
1953
                $f = exp($nper * log(1 + $rate));
1954
                $y = $pv * $f + $pmt * (1 / $rate + $type) * ($f - 1) + $fv;
1955
            }
1956
1957
            $y0 = $y1;
1958
            $y1 = $y;
1959
            ++$i;
1960
        }
1961
1962
        return $rate;
1963
    }
1964
1965
    /**
1966
     * RECEIVED.
1967
     *
1968
     * Returns the price per $100 face value of a discounted security.
1969
     *
1970
     * @param mixed settlement The security's settlement date.
1971
     *                                The security settlement date is the date after the issue date when the security is traded to the buyer.
1972
     * @param mixed maturity The security's maturity date.
1973
     *                                The maturity date is the date when the security expires.
1974
     * @param int investment The amount invested in the security
1975
     * @param int discount The security's discount rate
1976
     * @param int basis The type of day count to use.
1977
     *                                        0 or omitted    US (NASD) 30/360
1978
     *                                        1                Actual/actual
1979
     *                                        2                Actual/360
1980
     *                                        3                Actual/365
1981
     *                                        4                European 30/360
1982
     * @param mixed $settlement
1983
     * @param mixed $maturity
1984
     * @param mixed $investment
1985
     * @param mixed $discount
1986
     * @param mixed $basis
1987
     *
1988
     * @return float
1989
     */
1990 View Code Duplication
    public static function RECEIVED($settlement, $maturity, $investment, $discount, $basis = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1991
    {
1992
        $settlement = Functions::flattenSingleValue($settlement);
1993
        $maturity = Functions::flattenSingleValue($maturity);
1994
        $investment = (float) Functions::flattenSingleValue($investment);
1995
        $discount = (float) Functions::flattenSingleValue($discount);
1996
        $basis = (int) Functions::flattenSingleValue($basis);
1997
1998
        //    Validate
1999
        if ((is_numeric($investment)) && (is_numeric($discount)) && (is_numeric($basis))) {
2000
            if (($investment <= 0) || ($discount <= 0)) {
2001
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2002
            }
2003
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
2004
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
2005
                //    return date error
2006
                return $daysBetweenSettlementAndMaturity;
2007
            }
2008
2009
            return $investment / (1 - ($discount * $daysBetweenSettlementAndMaturity));
2010
        }
2011
2012
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2013
    }
2014
2015
    /**
2016
     * SLN.
2017
     *
2018
     * Returns the straight-line depreciation of an asset for one period
2019
     *
2020
     * @param cost Initial cost of the asset
2021
     * @param salvage Value at the end of the depreciation
2022
     * @param life Number of periods over which the asset is depreciated
2023
     * @param mixed $cost
2024
     * @param mixed $salvage
2025
     * @param mixed $life
2026
     *
2027
     * @return float
2028
     */
2029 View Code Duplication
    public static function SLN($cost, $salvage, $life)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2030
    {
2031
        $cost = Functions::flattenSingleValue($cost);
2032
        $salvage = Functions::flattenSingleValue($salvage);
2033
        $life = Functions::flattenSingleValue($life);
2034
2035
        // Calculate
2036
        if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life))) {
2037
            if ($life < 0) {
2038
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2039
            }
2040
2041
            return ($cost - $salvage) / $life;
2042
        }
2043
2044
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2045
    }
2046
2047
    /**
2048
     * SYD.
2049
     *
2050
     * Returns the sum-of-years' digits depreciation of an asset for a specified period.
2051
     *
2052
     * @param cost Initial cost of the asset
2053
     * @param salvage Value at the end of the depreciation
2054
     * @param life Number of periods over which the asset is depreciated
2055
     * @param period Period
2056
     * @param mixed $cost
2057
     * @param mixed $salvage
2058
     * @param mixed $life
2059
     * @param mixed $period
2060
     *
2061
     * @return float
2062
     */
2063
    public static function SYD($cost, $salvage, $life, $period)
2064
    {
2065
        $cost = Functions::flattenSingleValue($cost);
2066
        $salvage = Functions::flattenSingleValue($salvage);
2067
        $life = Functions::flattenSingleValue($life);
2068
        $period = Functions::flattenSingleValue($period);
2069
2070
        // Calculate
2071
        if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period))) {
2072
            if (($life < 1) || ($period > $life)) {
2073
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2074
            }
2075
2076
            return (($cost - $salvage) * ($life - $period + 1) * 2) / ($life * ($life + 1));
2077
        }
2078
2079
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2080
    }
2081
2082
    /**
2083
     * TBILLEQ.
2084
     *
2085
     * Returns the bond-equivalent yield for a Treasury bill.
2086
     *
2087
     * @param mixed settlement The Treasury bill's settlement date.
2088
     *                                The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer.
2089
     * @param mixed maturity The Treasury bill's maturity date.
2090
     *                                The maturity date is the date when the Treasury bill expires.
2091
     * @param int discount The Treasury bill's discount rate
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\discount was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2092
     * @param mixed $settlement
2093
     * @param mixed $maturity
2094
     * @param mixed $discount
2095
     *
2096
     * @return float
2097
     */
2098
    public static function TBILLEQ($settlement, $maturity, $discount)
2099
    {
2100
        $settlement = Functions::flattenSingleValue($settlement);
2101
        $maturity = Functions::flattenSingleValue($maturity);
2102
        $discount = Functions::flattenSingleValue($discount);
2103
2104
        //    Use TBILLPRICE for validation
2105
        $testValue = self::TBILLPRICE($settlement, $maturity, $discount);
2106
        if (is_string($testValue)) {
2107
            return $testValue;
2108
        }
2109
2110
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
2111
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2112
        }
2113
2114
        if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
2115
            ++$maturity;
2116
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360;
2117
        } else {
2118
            $daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement));
1 ignored issue
show
Bug introduced by
It seems like $maturity can also be of type DateTime; however, parameter $dateValue of PhpOffice\PhpSpreadsheet...ateTime::getDateValue() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2118
            $daysBetweenSettlementAndMaturity = (DateTime::getDateValue(/** @scrutinizer ignore-type */ $maturity) - DateTime::getDateValue($settlement));
Loading history...
2119
        }
2120
2121
        return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity);
2122
    }
2123
2124
    /**
2125
     * TBILLPRICE.
2126
     *
2127
     * Returns the yield for a Treasury bill.
2128
     *
2129
     * @param mixed settlement The Treasury bill's settlement date.
2130
     *                                The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer.
2131
     * @param mixed maturity The Treasury bill's maturity date.
2132
     *                                The maturity date is the date when the Treasury bill expires.
2133
     * @param int discount The Treasury bill's discount rate
2134
     * @param mixed $settlement
2135
     * @param mixed $maturity
2136
     * @param mixed $discount
2137
     *
2138
     * @return float
2139
     */
2140
    public static function TBILLPRICE($settlement, $maturity, $discount)
2141
    {
2142
        $settlement = Functions::flattenSingleValue($settlement);
2143
        $maturity = Functions::flattenSingleValue($maturity);
2144
        $discount = Functions::flattenSingleValue($discount);
2145
2146
        if (is_string($maturity = DateTime::getDateValue($maturity))) {
2147
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2148
        }
2149
2150
        //    Validate
2151
        if (is_numeric($discount)) {
2152
            if ($discount <= 0) {
2153
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2154
            }
2155
2156 View Code Duplication
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2157
                ++$maturity;
2158
                $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360;
2159
                if (!is_numeric($daysBetweenSettlementAndMaturity)) {
2160
                    //    return date error
2161
                    return $daysBetweenSettlementAndMaturity;
2162
                }
2163
            } else {
2164
                $daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement));
1 ignored issue
show
Bug introduced by
It seems like $maturity can also be of type DateTime; however, parameter $dateValue of PhpOffice\PhpSpreadsheet...ateTime::getDateValue() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

2164
                $daysBetweenSettlementAndMaturity = (DateTime::getDateValue(/** @scrutinizer ignore-type */ $maturity) - DateTime::getDateValue($settlement));
Loading history...
2165
            }
2166
2167
            if ($daysBetweenSettlementAndMaturity > 360) {
2168
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2169
            }
2170
2171
            $price = 100 * (1 - (($discount * $daysBetweenSettlementAndMaturity) / 360));
2172
            if ($price <= 0) {
2173
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2174
            }
2175
2176
            return $price;
2177
        }
2178
2179
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2180
    }
2181
2182
    /**
2183
     * TBILLYIELD.
2184
     *
2185
     * Returns the yield for a Treasury bill.
2186
     *
2187
     * @param mixed settlement The Treasury bill's settlement date.
2188
     *                                The Treasury bill's settlement date is the date after the issue date when the Treasury bill is traded to the buyer.
2189
     * @param mixed maturity The Treasury bill's maturity date.
2190
     *                                The maturity date is the date when the Treasury bill expires.
2191
     * @param int price The Treasury bill's price per $100 face value
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\price was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2192
     * @param mixed $settlement
2193
     * @param mixed $maturity
2194
     * @param mixed $price
2195
     *
2196
     * @return float
2197
     */
2198
    public static function TBILLYIELD($settlement, $maturity, $price)
2199
    {
2200
        $settlement = Functions::flattenSingleValue($settlement);
2201
        $maturity = Functions::flattenSingleValue($maturity);
2202
        $price = Functions::flattenSingleValue($price);
2203
2204
        //    Validate
2205
        if (is_numeric($price)) {
2206
            if ($price <= 0) {
2207
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2208
            }
2209
2210 View Code Duplication
            if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2211
                ++$maturity;
2212
                $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360;
2213
                if (!is_numeric($daysBetweenSettlementAndMaturity)) {
2214
                    //    return date error
2215
                    return $daysBetweenSettlementAndMaturity;
2216
                }
2217
            } else {
2218
                $daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement));
2219
            }
2220
2221
            if ($daysBetweenSettlementAndMaturity > 360) {
2222
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2223
            }
2224
2225
            return ((100 - $price) / $price) * (360 / $daysBetweenSettlementAndMaturity);
2226
        }
2227
2228
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2229
    }
2230
2231
    public static function XIRR($values, $dates, $guess = 0.1)
2232
    {
2233
        if ((!is_array($values)) && (!is_array($dates))) {
2234
            return Functions::VALUE();
2235
        }
2236
        $values = Functions::flattenArray($values);
2237
        $dates = Functions::flattenArray($dates);
2238
        $guess = Functions::flattenSingleValue($guess);
2239
        if (count($values) != count($dates)) {
2240
            return Functions::NAN();
2241
        }
2242
2243
        // create an initial range, with a root somewhere between 0 and guess
2244
        $x1 = 0.0;
2245
        $x2 = $guess;
2246
        $f1 = self::XNPV($x1, $values, $dates);
2247
        $f2 = self::XNPV($x2, $values, $dates);
2248 View Code Duplication
        for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2249
            if (($f1 * $f2) < 0.0) {
2250
                break;
2251
            } elseif (abs($f1) < abs($f2)) {
2252
                $f1 = self::XNPV($x1 += 1.6 * ($x1 - $x2), $values, $dates);
2253
            } else {
2254
                $f2 = self::XNPV($x2 += 1.6 * ($x2 - $x1), $values, $dates);
2255
            }
2256
        }
2257
        if (($f1 * $f2) > 0.0) {
2258
            return Functions::VALUE();
2259
        }
2260
2261
        $f = self::XNPV($x1, $values, $dates);
2262 View Code Duplication
        if ($f < 0.0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2263
            $rtb = $x1;
2264
            $dx = $x2 - $x1;
2265
        } else {
2266
            $rtb = $x2;
2267
            $dx = $x1 - $x2;
2268
        }
2269
2270 View Code Duplication
        for ($i = 0; $i < self::FINANCIAL_MAX_ITERATIONS; ++$i) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2271
            $dx *= 0.5;
2272
            $x_mid = $rtb + $dx;
2273
            $f_mid = self::XNPV($x_mid, $values, $dates);
2274
            if ($f_mid <= 0.0) {
2275
                $rtb = $x_mid;
2276
            }
2277
            if ((abs($f_mid) < self::FINANCIAL_PRECISION) || (abs($dx) < self::FINANCIAL_PRECISION)) {
2278
                return $x_mid;
2279
            }
2280
        }
2281
2282
        return Functions::VALUE();
2283
    }
2284
2285
    /**
2286
     * XNPV.
2287
     *
2288
     * Returns the net present value for a schedule of cash flows that is not necessarily periodic.
0 ignored issues
show
Bug introduced by
The type PhpOffice\PhpSpreadsheet\Calculation\of was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
2289
     * To calculate the net present value for a series of cash flows that is periodic, use the NPV function.
2290
     *
2291
     * Excel Function:
2292
     *        =XNPV(rate,values,dates)
2293
     *
2294
     * @param float $rate the discount rate to apply to the cash flows
2295
     * @param array of float    $values     A series of cash flows that corresponds to a schedule of payments in dates.
2296
     *                                         The first payment is optional and corresponds to a cost or payment that occurs at the beginning of the investment.
2297
     *                                         If the first value is a cost or payment, it must be a negative value. All succeeding payments are discounted based on a 365-day year.
2298
     *                                         The series of values must contain at least one positive value and one negative value.
2299
     * @param array of mixed    $dates      A schedule of payment dates that corresponds to the cash flow payments.
2300
     *                                         The first payment date indicates the beginning of the schedule of payments.
2301
     *                                         All other dates must be later than this date, but they may occur in any order.
2302
     *
2303
     * @return float
2304
     */
2305
    public static function XNPV($rate, $values, $dates)
2306
    {
2307
        $rate = Functions::flattenSingleValue($rate);
2308
        if (!is_numeric($rate)) {
2309
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2310
        }
2311
        if ((!is_array($values)) || (!is_array($dates))) {
2312
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2313
        }
2314
        $values = Functions::flattenArray($values);
2315
        $dates = Functions::flattenArray($dates);
2316
        $valCount = count($values);
2317
        if ($valCount != count($dates)) {
2318
            return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2319
        }
2320
        if ((min($values) > 0) || (max($values) < 0)) {
2321
            return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2322
        }
2323
2324
        $xnpv = 0.0;
2325
        for ($i = 0; $i < $valCount; ++$i) {
2326
            if (!is_numeric($values[$i])) {
2327
                return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2328
            }
2329
            $xnpv += $values[$i] / pow(1 + $rate, DateTime::DATEDIF($dates[0], $dates[$i], 'd') / 365);
2330
        }
2331
2332
        return (is_finite($xnpv)) ? $xnpv : Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return is_finite($xnpv) ...tion\Functions::VALUE() also could return the type string which is incompatible with the documented return type double.
Loading history...
2333
    }
2334
2335
    /**
2336
     * YIELDDISC.
2337
     *
2338
     * Returns the annual yield of a security that pays interest at maturity.
2339
     *
2340
     * @param mixed settlement The security's settlement date.
2341
     *                                    The security's settlement date is the date after the issue date when the security is traded to the buyer.
2342
     * @param mixed maturity The security's maturity date.
2343
     *                                    The maturity date is the date when the security expires.
2344
     * @param int price The security's price per $100 face value
2345
     * @param int redemption The security's redemption value per $100 face value
2346
     * @param int basis The type of day count to use.
2347
     *                                        0 or omitted    US (NASD) 30/360
2348
     *                                        1                Actual/actual
2349
     *                                        2                Actual/360
2350
     *                                        3                Actual/365
2351
     *                                        4                European 30/360
2352
     * @param mixed $settlement
2353
     * @param mixed $maturity
2354
     * @param mixed $price
2355
     * @param mixed $redemption
2356
     * @param mixed $basis
2357
     *
2358
     * @return float
2359
     */
2360
    public static function YIELDDISC($settlement, $maturity, $price, $redemption, $basis = 0)
2361
    {
2362
        $settlement = Functions::flattenSingleValue($settlement);
2363
        $maturity = Functions::flattenSingleValue($maturity);
2364
        $price = Functions::flattenSingleValue($price);
2365
        $redemption = Functions::flattenSingleValue($redemption);
2366
        $basis = (int) Functions::flattenSingleValue($basis);
2367
2368
        //    Validate
2369
        if (is_numeric($price) && is_numeric($redemption)) {
2370
            if (($price <= 0) || ($redemption <= 0)) {
2371
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2372
            }
2373
            $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
2374
            if (!is_numeric($daysPerYear)) {
2375
                return $daysPerYear;
2376
            }
2377
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
2378
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
2379
                //    return date error
2380
                return $daysBetweenSettlementAndMaturity;
2381
            }
2382
            $daysBetweenSettlementAndMaturity *= $daysPerYear;
2383
2384
            return (($redemption - $price) / $price) * ($daysPerYear / $daysBetweenSettlementAndMaturity);
2385
        }
2386
2387
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2388
    }
2389
2390
    /**
2391
     * YIELDMAT.
2392
     *
2393
     * Returns the annual yield of a security that pays interest at maturity.
2394
     *
2395
     * @param mixed settlement The security's settlement date.
2396
     *                                   The security's settlement date is the date after the issue date when the security is traded to the buyer.
2397
     * @param mixed maturity The security's maturity date.
2398
     *                                   The maturity date is the date when the security expires.
2399
     * @param mixed issue The security's issue date
2400
     * @param int rate The security's interest rate at date of issue
2401
     * @param int price The security's price per $100 face value
2402
     * @param int basis The type of day count to use.
2403
     *                                        0 or omitted    US (NASD) 30/360
2404
     *                                        1                Actual/actual
2405
     *                                        2                Actual/360
2406
     *                                        3                Actual/365
2407
     *                                        4                European 30/360
2408
     * @param mixed $settlement
2409
     * @param mixed $maturity
2410
     * @param mixed $issue
2411
     * @param mixed $rate
2412
     * @param mixed $price
2413
     * @param mixed $basis
2414
     *
2415
     * @return float
2416
     */
2417
    public static function YIELDMAT($settlement, $maturity, $issue, $rate, $price, $basis = 0)
2418
    {
2419
        $settlement = Functions::flattenSingleValue($settlement);
2420
        $maturity = Functions::flattenSingleValue($maturity);
2421
        $issue = Functions::flattenSingleValue($issue);
2422
        $rate = Functions::flattenSingleValue($rate);
2423
        $price = Functions::flattenSingleValue($price);
2424
        $basis = (int) Functions::flattenSingleValue($basis);
2425
2426
        //    Validate
2427
        if (is_numeric($rate) && is_numeric($price)) {
2428
            if (($rate <= 0) || ($price <= 0)) {
2429
                return Functions::NAN();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...lation\Functions::NAN() returns the type string which is incompatible with the documented return type double.
Loading history...
2430
            }
2431
            $daysPerYear = self::daysPerYear(DateTime::YEAR($settlement), $basis);
2432
            if (!is_numeric($daysPerYear)) {
2433
                return $daysPerYear;
2434
            }
2435
            $daysBetweenIssueAndSettlement = DateTime::YEARFRAC($issue, $settlement, $basis);
2436
            if (!is_numeric($daysBetweenIssueAndSettlement)) {
2437
                //    return date error
2438
                return $daysBetweenIssueAndSettlement;
2439
            }
2440
            $daysBetweenIssueAndSettlement *= $daysPerYear;
2441
            $daysBetweenIssueAndMaturity = DateTime::YEARFRAC($issue, $maturity, $basis);
2442
            if (!is_numeric($daysBetweenIssueAndMaturity)) {
2443
                //    return date error
2444
                return $daysBetweenIssueAndMaturity;
2445
            }
2446
            $daysBetweenIssueAndMaturity *= $daysPerYear;
2447
            $daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity, $basis);
2448
            if (!is_numeric($daysBetweenSettlementAndMaturity)) {
2449
                //    return date error
2450
                return $daysBetweenSettlementAndMaturity;
2451
            }
2452
            $daysBetweenSettlementAndMaturity *= $daysPerYear;
2453
2454
            return ((1 + (($daysBetweenIssueAndMaturity / $daysPerYear) * $rate) - (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) /
2455
                   (($price / 100) + (($daysBetweenIssueAndSettlement / $daysPerYear) * $rate))) *
2456
                   ($daysPerYear / $daysBetweenSettlementAndMaturity);
2457
        }
2458
2459
        return Functions::VALUE();
0 ignored issues
show
Bug Best Practice introduced by
The expression return PhpOffice\PhpSpre...tion\Functions::VALUE() returns the type string which is incompatible with the documented return type double.
Loading history...
2460
    }
2461
}
2462