javascript – 如何实现Excel的ACCRINT

前端之家收集整理的这篇文章主要介绍了javascript – 如何实现Excel的ACCRINT前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
作为 Formula.js项目的一部分,我正在尝试重新实现Excel的 ACCRINT功能(在JavaScript中,但语言无关紧要).我一直试图找到一个适当的描述它应该如何工作(特别是关于first_interest参数),但找不到任何东西.

有趣的是,Excel,Google Spreadsheets,Apple Numbers,Gnumeric和OpenOffice在实现它的方式上都存在分歧,尽管所有三个主要版本的Excel(Win,Mac,Web)似乎都互相认同.在blog post上可以找到更多的上下文.

可以在here找到数十个测试用例和我当前(有缺陷的)实现.

任何帮助将不胜感激!

更新:很明显,这个问题与day count convention没有关系,我们使用David Wheeler的pseudocode YEARFRAC实现了这个问题,它本身已经过3200万次测试验证,涵盖了所有五个基本选项.问题来自first_interest参数,似乎没有人真正理解.据我们所知,许多替代电子表格都忽略了这个参数,包括OpenOffice(它在源代码中被注释掉).而这个参数确实表现得很奇怪.如果您使用Excel并更改其值,您将看到它将更改ACCRINT函数给出的结果,但是看起来很混乱.尝试将first_interest日期改变一整个世纪,你会看到应计利息的变化,但不是很多.我真的无法理解这一点.如果有人能,我全都耳朵……

解决方法

这是在PHP(我认为):从 this page
/**
   *    ACCRINT
   *
   *    Returns the discount rate for a security.
   *
   *    @param    mixed    issue        The security's issue date.
   *    @param    mixed    firstinter    The security's first interest date.
   *    @param    mixed    settlement    The security's settlement date.
   *    @param    float    rate        The security's annual coupon rate.
   *    @param    float    par            The security's par value.
   *    @param    int        basis        The type of day count to use.
   *                                        0 or omitted    US (NASD) 30/360
   *                                        1                Actual/actual
   *                                        2                Actual/360
   *                                        3                Actual/365
   *                                        4                European 30/360
   *    @return    float
   */
public static function ACCRINT($issue,$firstinter,$settlement,$rate,$par=1000,$frequency=1,$basis=0) {
      $issue        = self::flattenSingleValue($issue);
      $firstinter    = self::flattenSingleValue($firstinter);
      $settlement    = self::flattenSingleValue($settlement);
      $rate        = (float) self::flattenSingleValue($rate);
      $par        = (is_null($par))    ? 1000    : (float) self::flattenSingleValue($par);
      $frequency    = (is_null($frequency))    ? 1    : (int) self::flattenSingleValue($frequency);
      $basis        = (is_null($basis))    ? 0        : (int) self::flattenSingleValue($basis);

      //    Validate
      if ((is_numeric($rate)) && (is_numeric($par))) {
          if (($rate <= 0) || ($par <= 0)) {
              return self::$_errorCodes['num'];
          }
          $daysBetweenIssueAndSettlement = self::YEARFRAC($issue,$basis);
          if (!is_numeric($daysBetweenIssueAndSettlement)) {
              return $daysBetweenIssueAndSettlement;
          }
          $daysPerYear = self::_daysPerYear(self::YEAR($issue),$basis);
          if (!is_numeric($daysPerYear)) {
              return $daysPerYear;
          }
          $daysBetweenIssueAndSettlement *= $daysPerYear;

          return $par * $rate * ($daysBetweenIssueAndSettlement / $daysPerYear);
      }
      return self::$_errorCodes['value'];
  }    //    function ACCRINT()

猜你在找的JavaScript相关文章