Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.

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

   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          self::doNothing($calcMethod);
  58          $issue = Functions::flattenSingleValue($issue);
  59          $firstInterest = Functions::flattenSingleValue($firstInterest);
  60          $settlement = Functions::flattenSingleValue($settlement);
  61          $rate = Functions::flattenSingleValue($rate);
  62          $parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
  63          $frequency = ($frequency === null)
  64              ? FinancialConstants::FREQUENCY_ANNUAL
  65              : Functions::flattenSingleValue($frequency);
  66          $basis = ($basis === null)
  67              ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
  68              : Functions::flattenSingleValue($basis);
  69  
  70          try {
  71              $issue = SecurityValidations::validateIssueDate($issue);
  72              $settlement = SecurityValidations::validateSettlementDate($settlement);
  73              SecurityValidations::validateSecurityPeriod($issue, $settlement);
  74              $rate = SecurityValidations::validateRate($rate);
  75              $parValue = SecurityValidations::validateParValue($parValue);
  76              $frequency = SecurityValidations::validateFrequency($frequency);
  77              self::doNothing($frequency);
  78              $basis = SecurityValidations::validateBasis($basis);
  79          } catch (Exception $e) {
  80              return $e->getMessage();
  81          }
  82  
  83          $daysBetweenIssueAndSettlement = Functions::scalar(YearFrac::fraction($issue, $settlement, $basis));
  84          if (!is_numeric($daysBetweenIssueAndSettlement)) {
  85              //    return date error
  86              return $daysBetweenIssueAndSettlement;
  87          }
  88          $daysBetweenFirstInterestAndSettlement = Functions::scalar(YearFrac::fraction($firstInterest, $settlement, $basis));
  89          if (!is_numeric($daysBetweenFirstInterestAndSettlement)) {
  90              //    return date error
  91              return $daysBetweenFirstInterestAndSettlement;
  92          }
  93  
  94          return $parValue * $rate * $daysBetweenIssueAndSettlement;
  95      }
  96  
  97      /**
  98       * ACCRINTM.
  99       *
 100       * Returns the accrued interest for a security that pays interest at maturity.
 101       *
 102       * Excel Function:
 103       *        ACCRINTM(issue,settlement,rate[,par[,basis]])
 104       *
 105       * @param mixed $issue The security's issue date
 106       * @param mixed $settlement The security's settlement (or maturity) date
 107       * @param mixed $rate The security's annual coupon rate
 108       * @param mixed $parValue The security's par value.
 109       *                            If you omit parValue, ACCRINT uses $1,000.
 110       * @param mixed $basis The type of day count to use.
 111       *                         0 or omitted    US (NASD) 30/360
 112       *                         1               Actual/actual
 113       *                         2               Actual/360
 114       *                         3               Actual/365
 115       *                         4               European 30/360
 116       *
 117       * @return float|string Result, or a string containing an error
 118       */
 119      public static function atMaturity(
 120          $issue,
 121          $settlement,
 122          $rate,
 123          $parValue = 1000,
 124          $basis = FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
 125      ) {
 126          $issue = Functions::flattenSingleValue($issue);
 127          $settlement = Functions::flattenSingleValue($settlement);
 128          $rate = Functions::flattenSingleValue($rate);
 129          $parValue = ($parValue === null) ? 1000 : Functions::flattenSingleValue($parValue);
 130          $basis = ($basis === null)
 131              ? FinancialConstants::BASIS_DAYS_PER_YEAR_NASD
 132              : Functions::flattenSingleValue($basis);
 133  
 134          try {
 135              $issue = SecurityValidations::validateIssueDate($issue);
 136              $settlement = SecurityValidations::validateSettlementDate($settlement);
 137              SecurityValidations::validateSecurityPeriod($issue, $settlement);
 138              $rate = SecurityValidations::validateRate($rate);
 139              $parValue = SecurityValidations::validateParValue($parValue);
 140              $basis = SecurityValidations::validateBasis($basis);
 141          } catch (Exception $e) {
 142              return $e->getMessage();
 143          }
 144  
 145          $daysBetweenIssueAndSettlement = Functions::scalar(YearFrac::fraction($issue, $settlement, $basis));
 146          if (!is_numeric($daysBetweenIssueAndSettlement)) {
 147              //    return date error
 148              return $daysBetweenIssueAndSettlement;
 149          }
 150  
 151          return $parValue * $rate * $daysBetweenIssueAndSettlement;
 152      }
 153  
 154      /** @param mixed $arg */
 155      private static function doNothing($arg): bool
 156      {
 157          return (bool) $arg;
 158      }
 159  }