7

作为Formula.js项目的一部分,我正在尝试重新实现 Excel 的ACCRINT函数(在 JavaScript 中,但语言应该无关紧要)。我一直在尝试找到它应该如何工作的正确描述(特别是关于first_interest参数),但找不到任何东西。

有趣的是,Excel、Google 电子表格、Apple Numbers、Gnumeric 和 OpenOffice 在实现它的方式上都存在分歧,尽管 Excel 的所有三个主要版本(Win、Mac、Web)似乎都彼此一致。可以在此博客文章中找到更多上下文。

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

任何帮助将不胜感激!

更新:需要明确的是,该问题与日期计数约定无关,我们使用 David Wheeler 的 YEARFRAC 伪代码实现了约定,它本身已通过超过 3200 万次测试验证,涵盖所有五个基本选项。问题来自参数,似乎没有人真正理解。据我们所知,这个参数被许多替代电子表格简单地忽略了,包括 OpenOffice(它在源代码中被注释掉了)。而且这个参数的行为确实很奇怪。如果您使用 Excel 并更改其值,您将看到它会更改ACCRINT函数给出的结果,但方式看起来很混乱。尝试更改first_interestfirst_interest日期相差一个世纪,您会看到应计利息发生变化,但变化不大。我真的无法理解这一点。如果有人可以,我会全神贯注...

4

2 回答 2

0

这是在 php 中(我认为):来自这个页面

  /**
   *    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, $settlement, $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()
于 2013-01-21T20:15:34.330 回答
0

来自 Quantitative Finance 的Phil H发现了这个.NET 库,它为所有金融功能提供了洁净室实现,除了两个似乎都通过了测试(实际上是 201,349 个测试用例)。其中包括 ACCRINT。该代码在知识共享署名下获得许可。它是用 F# 编写的,但很清楚。ACCRINT 的代码在bonds.fs 文件中。我们将尝试将其移植到 JavaScript,看看我们是否得到与 Excel 返回的结果相同的结果。更多关于这个很快......

于 2013-01-22T13:54:04.690 回答