Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\Financial\Securities;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\YearFrac;
   6  use PhpOffice\PhpSpreadsheet\Calculation\Exception;
   7  use PhpOffice\PhpSpreadsheet\Calculation\Financial\Constants as FinancialConstants;
   8  use PhpOffice\PhpSpreadsheet\Calculation\Functions;
   9  
  10  class AccruedInterest
  11  {
  12      public const ACCRINT_CALCMODE_ISSUE_TO_SETTLEMENT = true;
  13  
  14      public const ACCRINT_CALCMODE_FIRST_INTEREST_TO_SETTLEMENT = false;
  15  
  16      /**
  17       * ACCRINT.
  18       *
  19       * Returns the accrued interest for a security that pays periodic interest.
  20       *
  21       * Excel Function:
  22       *        ACCRINT(issue,firstinterest,settlement,rate,par,frequency[,basis][,calc_method])
  23       *
  24       * @param mixed $issue the security's issue date
  25       * @param mixed $firstInterest the security's first interest date
  26       * @param mixed $settlement The security's settlement date.
  27       *                              The security settlement date is the date after the issue date
  28       *                                  when the security is traded to the buyer.
  29       * @param mixed $rate The security's annual coupon rate
  30       * @param mixed $parValue The security's par value.
  31       *                            If you omit par, ACCRINT uses $1,000.
  32       * @param mixed $frequency The number of coupon payments per year.
  33       *                             Valid frequency values are:
  34       *                               1    Annual
  35       *                               2    Semi-Annual
  36       *                               4    Quarterly
  37       * @param mixed $basis The type of day count to use.
  38       *                         0 or omitted    US (NASD) 30/360
  39       *                         1               Actual/actual
  40       *                         2               Actual/360
  41       *                         3               Actual/365
  42       *                         4               European 30/360
  43       * @param mixed $calcMethod
  44       *
  45       * @return float|string Result, or a string containing an error
  46       */
  47      public static function periodic(
  48          $issue,
  49          $firstInterest,
  50          $settlement,
  51          $rate,
  52          $parValue = 1000,
  53          $frequency = FinancialConstants::FREQUENCY_ANNUAL,
  54          $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD,
  55          $calcMethod = self::ACCRINT_CALCMODE_ISSUE_TO_SETTLEMENT
  56      ) {
  57          $issue = Functions::flattenSingleValue($issue);
  58          $firstInterest = Functions::flattenSingleValue($firstInterest);
  59          $settlement = Functions::flattenSingleValue($settlement);
  60          $rate = Functions::flattenSingleValue($rate);
  61          $parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
  62          $frequency = ($frequency === null)
  63              ? FinancialConstants::FREQUENCY_ANNUAL
  64              : Functions::flattenSingleValue($frequency);
  65          $basis = ($basis === null)
  66              ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
  67              : Functions::flattenSingleValue($basis);
  68  
  69          try {
  70              $issue = SecurityValidations::validateIssueDate($issue);
  71              $settlement = SecurityValidations::validateSettlementDate($settlement);
  72              SecurityValidations::validateSecurityPeriod($issue, $settlement);
  73              $rate = SecurityValidations::validateRate($rate);
  74              $parValue = SecurityValidations::validateParValue($parValue);
  75              $frequency = SecurityValidations::validateFrequency($frequency);
  76              $basis = SecurityValidations::validateBasis($basis);
  77          } catch (Exception $e) {
  78              return $e->getMessage();
  79          }
  80  
  81          $daysBetweenIssueAndSettlement = Functions::scalar(YearFrac::fraction($issue, $settlement, $basis));
  82          if (!is_numeric($daysBetweenIssueAndSettlement)) {
  83              //    return date error
  84              return $daysBetweenIssueAndSettlement;
  85          }
  86          $daysBetweenFirstInterestAndSettlement = Functions::scalar(YearFrac::fraction($firstInterest, $settlement, $basis));
  87          if (!is_numeric($daysBetweenFirstInterestAndSettlement)) {
  88              //    return date error
  89              return $daysBetweenFirstInterestAndSettlement;
  90          }
  91  
  92          return $parValue * $rate * $daysBetweenIssueAndSettlement;
  93      }
  94  
  95      /**
  96       * ACCRINTM.
  97       *
  98       * Returns the accrued interest for a security that pays interest at maturity.
  99       *
 100       * Excel Function:
 101       *        ACCRINTM(issue,settlement,rate[,par[,basis]])
 102       *
 103       * @param mixed $issue The security's issue date
 104       * @param mixed $settlement The security's settlement (or maturity) date
 105       * @param mixed $rate The security's annual coupon rate
 106       * @param mixed $parValue The security's par value.
 107       *                            If you omit parValue, ACCRINT uses $1,000.
 108       * @param mixed $basis The type of day count to use.
 109       *                         0 or omitted    US (NASD) 30/360
 110       *                         1               Actual/actual
 111       *                         2               Actual/360
 112       *                         3               Actual/365
 113       *                         4               European 30/360
 114       *
 115       * @return float|string Result, or a string containing an error
 116       */
 117      public static function atMaturity(
 118          $issue,
 119          $settlement,
 120          $rate,
 121          $parValue = 1000,
 122          $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
 123      ) {
 124          $issue = Functions::flattenSingleValue($issue);
 125          $settlement = Functions::flattenSingleValue($settlement);
 126          $rate = Functions::flattenSingleValue($rate);
 127          $parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
 128          $basis = ($basis === null)
 129              ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
 130              : Functions::flattenSingleValue($basis);
 131  
 132          try {
 133              $issue = SecurityValidations::validateIssueDate($issue);
 134              $settlement = SecurityValidations::validateSettlementDate($settlement);
 135              SecurityValidations::validateSecurityPeriod($issue, $settlement);
 136              $rate = SecurityValidations::validateRate($rate);
 137              $parValue = SecurityValidations::validateParValue($parValue);
 138              $basis = SecurityValidations::validateBasis($basis);
 139          } catch (Exception $e) {
 140              return $e->getMessage();
 141          }
 142  
 143          $daysBetweenIssueAndSettlement = Functions::scalar(YearFrac::fraction($issue, $settlement, $basis));
 144          if (!is_numeric($daysBetweenIssueAndSettlement)) {
 145              //    return date error
 146              return $daysBetweenIssueAndSettlement;
 147          }
 148  
 149          return $parValue * $rate * $daysBetweenIssueAndSettlement;
 150      }
 151  }