ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Coupons.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use DateTime;
11 
12 class Coupons
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);
62  $basis = FinancialValidations::validateBasis($basis);
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);
125  $basis = FinancialValidations::validateBasis($basis);
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);
196  $basis = FinancialValidations::validateBasis($basis);
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);
261  $basis = FinancialValidations::validateBasis($basis);
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);
315  $basis = FinancialValidations::validateBasis($basis);
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);
375  $basis = FinancialValidations::validateBasis($basis);
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 }
static isLastDayOfMonth(DateTimeInterface $date)
isLastDayOfMonth.
Definition: Helpers.php:54
$result
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 COUPNCD( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPNCD.
Definition: Coupons.php:243
static COUPDAYS( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPDAYS.
Definition: Coupons.php:107
static fraction($startDate, $endDate, $method=0)
YEARFRAC.
Definition: YearFrac.php:37
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 couponFirstPeriodDate(float $settlement, float $maturity, int $frequency, bool $next)
Definition: Coupons.php:391
static between($endDate, $startDate)
DAYS.
Definition: Days.php:27
static daysPerYear($year, $basis=0)
daysPerYear.
Definition: Helpers.php:27
static flattenSingleValue($value='')
Convert an array to a single scalar value by extracting the first element.
Definition: Functions.php:649
static COUPNUM( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPNUM.
Definition: Coupons.php:297
static COUPDAYBS( $settlement, $maturity, $frequency, $basis=FinancialConstants::BASIS_DAYS_PER_YEAR_NASD)
COUPDAYBS.
Definition: Coupons.php:44