ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Coupons.php
Go to the documentation of this file.
1<?php
2
4
5use DateTime;
11
13{
14 private const PERIOD_DATE_PREVIOUS = false;
15 private const PERIOD_DATE_NEXT = true;
16
44 public static function COUPDAYBS(
45 $settlement,
46 $maturity,
47 $frequency,
48 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
49 ) {
50 $settlement = Functions::flattenSingleValue($settlement);
51 $maturity = Functions::flattenSingleValue($maturity);
52 $frequency = Functions::flattenSingleValue($frequency);
53 $basis = ($basis === null)
54 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
56
57 try {
58 $settlement = FinancialValidations::validateSettlementDate($settlement);
59 $maturity = FinancialValidations::validateMaturityDate($maturity);
60 self::validateCouponPeriod($settlement, $maturity);
61 $frequency = FinancialValidations::validateFrequency($frequency);
63 } catch (Exception $e) {
64 return $e->getMessage();
65 }
66
67 $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis);
68 if (is_string($daysPerYear)) {
69 return Functions::VALUE();
70 }
71 $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_PREVIOUS);
72
73 if ($basis === FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL) {
74 return abs((float) DateTimeExcel\Days::between($prev, $settlement));
75 }
76
77 return (float) DateTimeExcel\YearFrac::fraction($prev, $settlement, $basis) * $daysPerYear;
78 }
79
107 public static function COUPDAYS(
108 $settlement,
109 $maturity,
110 $frequency,
111 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
112 ) {
113 $settlement = Functions::flattenSingleValue($settlement);
114 $maturity = Functions::flattenSingleValue($maturity);
115 $frequency = Functions::flattenSingleValue($frequency);
116 $basis = ($basis === null)
117 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
119
120 try {
121 $settlement = FinancialValidations::validateSettlementDate($settlement);
122 $maturity = FinancialValidations::validateMaturityDate($maturity);
123 self::validateCouponPeriod($settlement, $maturity);
124 $frequency = FinancialValidations::validateFrequency($frequency);
126 } catch (Exception $e) {
127 return $e->getMessage();
128 }
129
130 switch ($basis) {
131 case FinancialConstants::BASIS_DAYS_PER_YEAR_365:
132 // Actual/365
133 return 365 / $frequency;
134 case FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL:
135 // Actual/actual
136 if ($frequency == FinancialConstants::FREQUENCY_ANNUAL) {
137 $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis);
138
139 return $daysPerYear / $frequency;
140 }
141 $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_PREVIOUS);
142 $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_NEXT);
143
144 return $next - $prev;
145 default:
146 // US (NASD) 30/360, Actual/360 or European 30/360
147 return 360 / $frequency;
148 }
149 }
150
178 public static function COUPDAYSNC(
179 $settlement,
180 $maturity,
181 $frequency,
182 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
183 ) {
184 $settlement = Functions::flattenSingleValue($settlement);
185 $maturity = Functions::flattenSingleValue($maturity);
186 $frequency = Functions::flattenSingleValue($frequency);
187 $basis = ($basis === null)
188 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
190
191 try {
192 $settlement = FinancialValidations::validateSettlementDate($settlement);
193 $maturity = FinancialValidations::validateMaturityDate($maturity);
194 self::validateCouponPeriod($settlement, $maturity);
195 $frequency = FinancialValidations::validateFrequency($frequency);
197 } catch (Exception $e) {
198 return $e->getMessage();
199 }
200
201 $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis);
202 $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_NEXT);
203
204 if ($basis === FinancialConstants::BASIS_DAYS_PER_YEAR_NASD) {
205 $settlementDate = Date::excelToDateTimeObject($settlement);
206 $settlementEoM = Helpers::isLastDayOfMonth($settlementDate);
207 if ($settlementEoM) {
208 ++$settlement;
209 }
210 }
211
212 return (float) DateTimeExcel\YearFrac::fraction($settlement, $next, $basis) * $daysPerYear;
213 }
214
243 public static function COUPNCD(
244 $settlement,
245 $maturity,
246 $frequency,
247 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
248 ) {
249 $settlement = Functions::flattenSingleValue($settlement);
250 $maturity = Functions::flattenSingleValue($maturity);
251 $frequency = Functions::flattenSingleValue($frequency);
252 $basis = ($basis === null)
253 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
255
256 try {
257 $settlement = FinancialValidations::validateSettlementDate($settlement);
258 $maturity = FinancialValidations::validateMaturityDate($maturity);
259 self::validateCouponPeriod($settlement, $maturity);
260 $frequency = FinancialValidations::validateFrequency($frequency);
262 } catch (Exception $e) {
263 return $e->getMessage();
264 }
265
266 return self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_NEXT);
267 }
268
297 public static function COUPNUM(
298 $settlement,
299 $maturity,
300 $frequency,
301 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
302 ) {
303 $settlement = Functions::flattenSingleValue($settlement);
304 $maturity = Functions::flattenSingleValue($maturity);
305 $frequency = Functions::flattenSingleValue($frequency);
306 $basis = ($basis === null)
307 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
309
310 try {
311 $settlement = FinancialValidations::validateSettlementDate($settlement);
312 $maturity = FinancialValidations::validateMaturityDate($maturity);
313 self::validateCouponPeriod($settlement, $maturity);
314 $frequency = FinancialValidations::validateFrequency($frequency);
316 } catch (Exception $e) {
317 return $e->getMessage();
318 }
319
320 $yearsBetweenSettlementAndMaturity = DateTimeExcel\YearFrac::fraction(
321 $settlement,
322 $maturity,
323 FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
324 );
325
326 return (int) ceil((float) $yearsBetweenSettlementAndMaturity * $frequency);
327 }
328
357 public static function COUPPCD(
358 $settlement,
359 $maturity,
360 $frequency,
361 $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
362 ) {
363 $settlement = Functions::flattenSingleValue($settlement);
364 $maturity = Functions::flattenSingleValue($maturity);
365 $frequency = Functions::flattenSingleValue($frequency);
366 $basis = ($basis === null)
367 ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
369
370 try {
371 $settlement = FinancialValidations::validateSettlementDate($settlement);
372 $maturity = FinancialValidations::validateMaturityDate($maturity);
373 self::validateCouponPeriod($settlement, $maturity);
374 $frequency = FinancialValidations::validateFrequency($frequency);
376 } catch (Exception $e) {
377 return $e->getMessage();
378 }
379
380 return self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_PREVIOUS);
381 }
382
383 private static function monthsDiff(DateTime $result, int $months, string $plusOrMinus, int $day, bool $lastDayFlag): void
384 {
385 $result->setDate((int) $result->format('Y'), (int) $result->format('m'), 1);
386 $result->modify("$plusOrMinus $months months");
387 $daysInMonth = (int) $result->format('t');
388 $result->setDate((int) $result->format('Y'), (int) $result->format('m'), $lastDayFlag ? $daysInMonth : min($day, $daysInMonth));
389 }
390
391 private static function couponFirstPeriodDate(float $settlement, float $maturity, int $frequency, bool $next): float
392 {
393 $months = 12 / $frequency;
394
395 $result = Date::excelToDateTimeObject($maturity);
396 $day = (int) $result->format('d');
397 $lastDayFlag = Helpers::isLastDayOfMonth($result);
398
399 while ($settlement < Date::PHPToExcel($result)) {
400 self::monthsDiff($result, $months, '-', $day, $lastDayFlag);
401 }
402 if ($next === true) {
403 self::monthsDiff($result, $months, '+', $day, $lastDayFlag);
404 }
405
406 return (float) Date::PHPToExcel($result);
407 }
408
409 private static function validateCouponPeriod(float $settlement, float $maturity): void
410 {
411 if ($settlement >= $maturity) {
412 throw new Exception(Functions::NAN());
413 }
414 }
415}
$result
An exception for terminatinating execution or to throw for unit testing.
static between($endDate, $startDate)
DAYS.
Definition: Days.php:27
static fraction($startDate, $endDate, $method=0)
YEARFRAC.
Definition: YearFrac.php:37
static couponFirstPeriodDate(float $settlement, float $maturity, int $frequency, bool $next)
Definition: Coupons.php:391
static COUPDAYS( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPDAYS.
Definition: Coupons.php:107
static COUPNUM( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPNUM.
Definition: Coupons.php:297
static COUPNCD( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPNCD.
Definition: Coupons.php:243
static monthsDiff(DateTime $result, int $months, string $plusOrMinus, int $day, bool $lastDayFlag)
Definition: Coupons.php:383
static COUPDAYSNC( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPDAYSNC.
Definition: Coupons.php:178
static COUPDAYBS( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPDAYBS.
Definition: Coupons.php:44
static COUPPCD( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPPCD.
Definition: Coupons.php:357
static validateCouponPeriod(float $settlement, float $maturity)
Definition: Coupons.php:409
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:649