如何实现Excel的ACCRINT

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

有趣的是,Excel,Google Spreadsheets,Apple Numbers,Gnumeric和OpenOffice都不同意实现它的方法,即使所有三个主要版本的Excel(Win,Mac,Web)似乎都认同。 在这个博客文章中可以find更多的上下文。

几十个testing用例和我目前的(有缺陷的)实现可以在这里find。

任何帮助将不胜感激!

更新:要清楚的是,这个问题与date计数约定无关,我们使用David Wheeler的YEARFRAC 伪代码实现了这一约定 ,该validation本身已经通过3200多万次testingvalidation,涵盖了所有五个基本选项。 这个问题来自first_interest参数,这似乎没有人真正理解。 据我们所知,这个参数被许多其他电子表格所忽略,包括OpenOffice(它在源代码中被注释掉了)。 而这个参数真的performance得很奇怪。 如果你使用Excel并且改变它的值,你会发现它会改变ACCRINT函数给出的结果,但是看起来很混乱。 试着将first_interestdate改变一整个世纪,你会看到应计利息的变化,但不是太多。 我真的无法理解这一点。 如果任何人都可以的话,我都是耳朵…

这是在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() 

Quantitative Finance的Phil H发现了这个.NET库 ,它提供了所有财务函数的净室实现,除了两个似乎都通过了testing(其实201,349个testing用例)。 这些包括ACCRINT。 该代码根据知识共享署名进行许可。 它是用F#编写的,但是很清楚。 ACCRINT的代码位于bonds.fs文件中。 我们将尝试将其移植到JavaScript,并查看是否得到与Excel返回的结果相同的结果。 更多关于这个…