PageRenderTime 55ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/phpexcel/PHPExcel/Calculation/Financial.php

https://bitbucket.org/moodle/moodle
PHP | 2359 lines | 1131 code | 224 blank | 1004 comment | 313 complexity | c8f9b1bc9e47d9d7e42d4f3bcea7cb9c MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /** PHPExcel root directory */
  3. if (!defined('PHPEXCEL_ROOT')) {
  4. /**
  5. * @ignore
  6. */
  7. define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../../');
  8. require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
  9. }
  10. /** FINANCIAL_MAX_ITERATIONS */
  11. define('FINANCIAL_MAX_ITERATIONS', 128);
  12. /** FINANCIAL_PRECISION */
  13. define('FINANCIAL_PRECISION', 1.0e-08);
  14. /**
  15. * PHPExcel_Calculation_Financial
  16. *
  17. * Copyright (c) 2006 - 2015 PHPExcel
  18. *
  19. * This library is free software; you can redistribute it and/or
  20. * modify it under the terms of the GNU Lesser General Public
  21. * License as published by the Free Software Foundation; either
  22. * version 2.1 of the License, or (at your option) any later version.
  23. *
  24. * This library is distributed in the hope that it will be useful,
  25. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  26. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  27. * Lesser General Public License for more details.
  28. *
  29. * You should have received a copy of the GNU Lesser General Public
  30. * License along with this library; if not, write to the Free Software
  31. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  32. *
  33. * @category PHPExcel
  34. * @package PHPExcel_Calculation
  35. * @copyright Copyright (c) 2006 - 2015 PHPExcel (http://www.codeplex.com/PHPExcel)
  36. * @license http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt LGPL
  37. * @version ##VERSION##, ##DATE##
  38. */
  39. class PHPExcel_Calculation_Financial
  40. {
  41. /**
  42. * isLastDayOfMonth
  43. *
  44. * Returns a boolean TRUE/FALSE indicating if this date is the last date of the month
  45. *
  46. * @param DateTime $testDate The date for testing
  47. * @return boolean
  48. */
  49. private static function isLastDayOfMonth($testDate)
  50. {
  51. return ($testDate->format('d') == $testDate->format('t'));
  52. }
  53. /**
  54. * isFirstDayOfMonth
  55. *
  56. * Returns a boolean TRUE/FALSE indicating if this date is the first date of the month
  57. *
  58. * @param DateTime $testDate The date for testing
  59. * @return boolean
  60. */
  61. private static function isFirstDayOfMonth($testDate)
  62. {
  63. return ($testDate->format('d') == 1);
  64. }
  65. private static function couponFirstPeriodDate($settlement, $maturity, $frequency, $next)
  66. {
  67. $months = 12 / $frequency;
  68. $result = PHPExcel_Shared_Date::ExcelToPHPObject($maturity);
  69. $eom = self::isLastDayOfMonth($result);
  70. while ($settlement < PHPExcel_Shared_Date::PHPToExcel($result)) {
  71. $result->modify('-'.$months.' months');
  72. }
  73. if ($next) {
  74. $result->modify('+'.$months.' months');
  75. }
  76. if ($eom) {
  77. $result->modify('-1 day');
  78. }
  79. return PHPExcel_Shared_Date::PHPToExcel($result);
  80. }
  81. private static function isValidFrequency($frequency)
  82. {
  83. if (($frequency == 1) || ($frequency == 2) || ($frequency == 4)) {
  84. return true;
  85. }
  86. if ((PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) &&
  87. (($frequency == 6) || ($frequency == 12))) {
  88. return true;
  89. }
  90. return false;
  91. }
  92. /**
  93. * daysPerYear
  94. *
  95. * Returns the number of days in a specified year, as defined by the "basis" value
  96. *
  97. * @param integer $year The year against which we're testing
  98. * @param integer $basis The type of day count:
  99. * 0 or omitted US (NASD) 360
  100. * 1 Actual (365 or 366 in a leap year)
  101. * 2 360
  102. * 3 365
  103. * 4 European 360
  104. * @return integer
  105. */
  106. private static function daysPerYear($year, $basis = 0)
  107. {
  108. switch ($basis) {
  109. case 0:
  110. case 2:
  111. case 4:
  112. $daysPerYear = 360;
  113. break;
  114. case 3:
  115. $daysPerYear = 365;
  116. break;
  117. case 1:
  118. $daysPerYear = (PHPExcel_Calculation_DateTime::isLeapYear($year)) ? 366 : 365;
  119. break;
  120. default:
  121. return PHPExcel_Calculation_Functions::NaN();
  122. }
  123. return $daysPerYear;
  124. }
  125. private static function interestAndPrincipal($rate = 0, $per = 0, $nper = 0, $pv = 0, $fv = 0, $type = 0)
  126. {
  127. $pmt = self::PMT($rate, $nper, $pv, $fv, $type);
  128. $capital = $pv;
  129. for ($i = 1; $i<= $per; ++$i) {
  130. $interest = ($type && $i == 1) ? 0 : -$capital * $rate;
  131. $principal = $pmt - $interest;
  132. $capital += $principal;
  133. }
  134. return array($interest, $principal);
  135. }
  136. /**
  137. * ACCRINT
  138. *
  139. * Returns the accrued interest for a security that pays periodic interest.
  140. *
  141. * Excel Function:
  142. * ACCRINT(issue,firstinterest,settlement,rate,par,frequency[,basis])
  143. *
  144. * @access public
  145. * @category Financial Functions
  146. * @param mixed $issue The security's issue date.
  147. * @param mixed $firstinterest The security's first interest date.
  148. * @param mixed $settlement The security's settlement date.
  149. * The security settlement date is the date after the issue date
  150. * when the security is traded to the buyer.
  151. * @param float $rate The security's annual coupon rate.
  152. * @param float $par The security's par value.
  153. * If you omit par, ACCRINT uses $1,000.
  154. * @param integer $frequency the number of coupon payments per year.
  155. * Valid frequency values are:
  156. * 1 Annual
  157. * 2 Semi-Annual
  158. * 4 Quarterly
  159. * If working in Gnumeric Mode, the following frequency options are
  160. * also available
  161. * 6 Bimonthly
  162. * 12 Monthly
  163. * @param integer $basis The type of day count to use.
  164. * 0 or omitted US (NASD) 30/360
  165. * 1 Actual/actual
  166. * 2 Actual/360
  167. * 3 Actual/365
  168. * 4 European 30/360
  169. * @return float
  170. */
  171. public static function ACCRINT($issue, $firstinterest, $settlement, $rate, $par = 1000, $frequency = 1, $basis = 0)
  172. {
  173. $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue);
  174. $firstinterest = PHPExcel_Calculation_Functions::flattenSingleValue($firstinterest);
  175. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  176. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  177. $par = (is_null($par)) ? 1000 : PHPExcel_Calculation_Functions::flattenSingleValue($par);
  178. $frequency = (is_null($frequency)) ? 1 : PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  179. $basis = (is_null($basis)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  180. // Validate
  181. if ((is_numeric($rate)) && (is_numeric($par))) {
  182. $rate = (float) $rate;
  183. $par = (float) $par;
  184. if (($rate <= 0) || ($par <= 0)) {
  185. return PHPExcel_Calculation_Functions::NaN();
  186. }
  187. $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis);
  188. if (!is_numeric($daysBetweenIssueAndSettlement)) {
  189. // return date error
  190. return $daysBetweenIssueAndSettlement;
  191. }
  192. return $par * $rate * $daysBetweenIssueAndSettlement;
  193. }
  194. return PHPExcel_Calculation_Functions::VALUE();
  195. }
  196. /**
  197. * ACCRINTM
  198. *
  199. * Returns the accrued interest for a security that pays interest at maturity.
  200. *
  201. * Excel Function:
  202. * ACCRINTM(issue,settlement,rate[,par[,basis]])
  203. *
  204. * @access public
  205. * @category Financial Functions
  206. * @param mixed issue The security's issue date.
  207. * @param mixed settlement The security's settlement (or maturity) date.
  208. * @param float rate The security's annual coupon rate.
  209. * @param float par The security's par value.
  210. * If you omit par, ACCRINT uses $1,000.
  211. * @param integer basis The type of day count to use.
  212. * 0 or omitted US (NASD) 30/360
  213. * 1 Actual/actual
  214. * 2 Actual/360
  215. * 3 Actual/365
  216. * 4 European 30/360
  217. * @return float
  218. */
  219. public static function ACCRINTM($issue, $settlement, $rate, $par = 1000, $basis = 0)
  220. {
  221. $issue = PHPExcel_Calculation_Functions::flattenSingleValue($issue);
  222. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  223. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  224. $par = (is_null($par)) ? 1000 : PHPExcel_Calculation_Functions::flattenSingleValue($par);
  225. $basis = (is_null($basis)) ? 0 : PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  226. // Validate
  227. if ((is_numeric($rate)) && (is_numeric($par))) {
  228. $rate = (float) $rate;
  229. $par = (float) $par;
  230. if (($rate <= 0) || ($par <= 0)) {
  231. return PHPExcel_Calculation_Functions::NaN();
  232. }
  233. $daysBetweenIssueAndSettlement = PHPExcel_Calculation_DateTime::YEARFRAC($issue, $settlement, $basis);
  234. if (!is_numeric($daysBetweenIssueAndSettlement)) {
  235. // return date error
  236. return $daysBetweenIssueAndSettlement;
  237. }
  238. return $par * $rate * $daysBetweenIssueAndSettlement;
  239. }
  240. return PHPExcel_Calculation_Functions::VALUE();
  241. }
  242. /**
  243. * AMORDEGRC
  244. *
  245. * Returns the depreciation for each accounting period.
  246. * This function is provided for the French accounting system. If an asset is purchased in
  247. * the middle of the accounting period, the prorated depreciation is taken into account.
  248. * The function is similar to AMORLINC, except that a depreciation coefficient is applied in
  249. * the calculation depending on the life of the assets.
  250. * This function will return the depreciation until the last period of the life of the assets
  251. * or until the cumulated value of depreciation is greater than the cost of the assets minus
  252. * the salvage value.
  253. *
  254. * Excel Function:
  255. * AMORDEGRC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
  256. *
  257. * @access public
  258. * @category Financial Functions
  259. * @param float cost The cost of the asset.
  260. * @param mixed purchased Date of the purchase of the asset.
  261. * @param mixed firstPeriod Date of the end of the first period.
  262. * @param mixed salvage The salvage value at the end of the life of the asset.
  263. * @param float period The period.
  264. * @param float rate Rate of depreciation.
  265. * @param integer basis The type of day count to use.
  266. * 0 or omitted US (NASD) 30/360
  267. * 1 Actual/actual
  268. * 2 Actual/360
  269. * 3 Actual/365
  270. * 4 European 30/360
  271. * @return float
  272. */
  273. public static function AMORDEGRC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
  274. {
  275. $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost);
  276. $purchased = PHPExcel_Calculation_Functions::flattenSingleValue($purchased);
  277. $firstPeriod = PHPExcel_Calculation_Functions::flattenSingleValue($firstPeriod);
  278. $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage);
  279. $period = floor(PHPExcel_Calculation_Functions::flattenSingleValue($period));
  280. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  281. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  282. // The depreciation coefficients are:
  283. // Life of assets (1/rate) Depreciation coefficient
  284. // Less than 3 years 1
  285. // Between 3 and 4 years 1.5
  286. // Between 5 and 6 years 2
  287. // More than 6 years 2.5
  288. $fUsePer = 1.0 / $rate;
  289. if ($fUsePer < 3.0) {
  290. $amortiseCoeff = 1.0;
  291. } elseif ($fUsePer < 5.0) {
  292. $amortiseCoeff = 1.5;
  293. } elseif ($fUsePer <= 6.0) {
  294. $amortiseCoeff = 2.0;
  295. } else {
  296. $amortiseCoeff = 2.5;
  297. }
  298. $rate *= $amortiseCoeff;
  299. $fNRate = round(PHPExcel_Calculation_DateTime::YEARFRAC($purchased, $firstPeriod, $basis) * $rate * $cost, 0);
  300. $cost -= $fNRate;
  301. $fRest = $cost - $salvage;
  302. for ($n = 0; $n < $period; ++$n) {
  303. $fNRate = round($rate * $cost, 0);
  304. $fRest -= $fNRate;
  305. if ($fRest < 0.0) {
  306. switch ($period - $n) {
  307. case 0:
  308. case 1:
  309. return round($cost * 0.5, 0);
  310. default:
  311. return 0.0;
  312. }
  313. }
  314. $cost -= $fNRate;
  315. }
  316. return $fNRate;
  317. }
  318. /**
  319. * AMORLINC
  320. *
  321. * Returns the depreciation for each accounting period.
  322. * This function is provided for the French accounting system. If an asset is purchased in
  323. * the middle of the accounting period, the prorated depreciation is taken into account.
  324. *
  325. * Excel Function:
  326. * AMORLINC(cost,purchased,firstPeriod,salvage,period,rate[,basis])
  327. *
  328. * @access public
  329. * @category Financial Functions
  330. * @param float cost The cost of the asset.
  331. * @param mixed purchased Date of the purchase of the asset.
  332. * @param mixed firstPeriod Date of the end of the first period.
  333. * @param mixed salvage The salvage value at the end of the life of the asset.
  334. * @param float period The period.
  335. * @param float rate Rate of depreciation.
  336. * @param integer basis The type of day count to use.
  337. * 0 or omitted US (NASD) 30/360
  338. * 1 Actual/actual
  339. * 2 Actual/360
  340. * 3 Actual/365
  341. * 4 European 30/360
  342. * @return float
  343. */
  344. public static function AMORLINC($cost, $purchased, $firstPeriod, $salvage, $period, $rate, $basis = 0)
  345. {
  346. $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost);
  347. $purchased = PHPExcel_Calculation_Functions::flattenSingleValue($purchased);
  348. $firstPeriod = PHPExcel_Calculation_Functions::flattenSingleValue($firstPeriod);
  349. $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage);
  350. $period = PHPExcel_Calculation_Functions::flattenSingleValue($period);
  351. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  352. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  353. $fOneRate = $cost * $rate;
  354. $fCostDelta = $cost - $salvage;
  355. // Note, quirky variation for leap years on the YEARFRAC for this function
  356. $purchasedYear = PHPExcel_Calculation_DateTime::YEAR($purchased);
  357. $yearFrac = PHPExcel_Calculation_DateTime::YEARFRAC($purchased, $firstPeriod, $basis);
  358. if (($basis == 1) && ($yearFrac < 1) && (PHPExcel_Calculation_DateTime::isLeapYear($purchasedYear))) {
  359. $yearFrac *= 365 / 366;
  360. }
  361. $f0Rate = $yearFrac * $rate * $cost;
  362. $nNumOfFullPeriods = intval(($cost - $salvage - $f0Rate) / $fOneRate);
  363. if ($period == 0) {
  364. return $f0Rate;
  365. } elseif ($period <= $nNumOfFullPeriods) {
  366. return $fOneRate;
  367. } elseif ($period == ($nNumOfFullPeriods + 1)) {
  368. return ($fCostDelta - $fOneRate * $nNumOfFullPeriods - $f0Rate);
  369. } else {
  370. return 0.0;
  371. }
  372. }
  373. /**
  374. * COUPDAYBS
  375. *
  376. * Returns the number of days from the beginning of the coupon period to the settlement date.
  377. *
  378. * Excel Function:
  379. * COUPDAYBS(settlement,maturity,frequency[,basis])
  380. *
  381. * @access public
  382. * @category Financial Functions
  383. * @param mixed settlement The security's settlement date.
  384. * The security settlement date is the date after the issue
  385. * date when the security is traded to the buyer.
  386. * @param mixed maturity The security's maturity date.
  387. * The maturity date is the date when the security expires.
  388. * @param mixed frequency the number of coupon payments per year.
  389. * Valid frequency values are:
  390. * 1 Annual
  391. * 2 Semi-Annual
  392. * 4 Quarterly
  393. * If working in Gnumeric Mode, the following frequency options are
  394. * also available
  395. * 6 Bimonthly
  396. * 12 Monthly
  397. * @param integer basis The type of day count to use.
  398. * 0 or omitted US (NASD) 30/360
  399. * 1 Actual/actual
  400. * 2 Actual/360
  401. * 3 Actual/365
  402. * 4 European 30/360
  403. * @return float
  404. */
  405. public static function COUPDAYBS($settlement, $maturity, $frequency, $basis = 0)
  406. {
  407. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  408. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  409. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  410. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  411. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  412. return PHPExcel_Calculation_Functions::VALUE();
  413. }
  414. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  415. return PHPExcel_Calculation_Functions::VALUE();
  416. }
  417. if (($settlement > $maturity) ||
  418. (!self::isValidFrequency($frequency)) ||
  419. (($basis < 0) || ($basis > 4))) {
  420. return PHPExcel_Calculation_Functions::NaN();
  421. }
  422. $daysPerYear = self::daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement), $basis);
  423. $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
  424. return PHPExcel_Calculation_DateTime::YEARFRAC($prev, $settlement, $basis) * $daysPerYear;
  425. }
  426. /**
  427. * COUPDAYS
  428. *
  429. * Returns the number of days in the coupon period that contains the settlement date.
  430. *
  431. * Excel Function:
  432. * COUPDAYS(settlement,maturity,frequency[,basis])
  433. *
  434. * @access public
  435. * @category Financial Functions
  436. * @param mixed settlement The security's settlement date.
  437. * The security settlement date is the date after the issue
  438. * date when the security is traded to the buyer.
  439. * @param mixed maturity The security's maturity date.
  440. * The maturity date is the date when the security expires.
  441. * @param mixed frequency the number of coupon payments per year.
  442. * Valid frequency values are:
  443. * 1 Annual
  444. * 2 Semi-Annual
  445. * 4 Quarterly
  446. * If working in Gnumeric Mode, the following frequency options are
  447. * also available
  448. * 6 Bimonthly
  449. * 12 Monthly
  450. * @param integer basis The type of day count to use.
  451. * 0 or omitted US (NASD) 30/360
  452. * 1 Actual/actual
  453. * 2 Actual/360
  454. * 3 Actual/365
  455. * 4 European 30/360
  456. * @return float
  457. */
  458. public static function COUPDAYS($settlement, $maturity, $frequency, $basis = 0)
  459. {
  460. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  461. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  462. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  463. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  464. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  465. return PHPExcel_Calculation_Functions::VALUE();
  466. }
  467. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  468. return PHPExcel_Calculation_Functions::VALUE();
  469. }
  470. if (($settlement > $maturity) ||
  471. (!self::isValidFrequency($frequency)) ||
  472. (($basis < 0) || ($basis > 4))) {
  473. return PHPExcel_Calculation_Functions::NaN();
  474. }
  475. switch ($basis) {
  476. case 3:
  477. // Actual/365
  478. return 365 / $frequency;
  479. case 1:
  480. // Actual/actual
  481. if ($frequency == 1) {
  482. $daysPerYear = self::daysPerYear(PHPExcel_Calculation_DateTime::YEAR($maturity), $basis);
  483. return ($daysPerYear / $frequency);
  484. }
  485. $prev = self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
  486. $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
  487. return ($next - $prev);
  488. default:
  489. // US (NASD) 30/360, Actual/360 or European 30/360
  490. return 360 / $frequency;
  491. }
  492. return PHPExcel_Calculation_Functions::VALUE();
  493. }
  494. /**
  495. * COUPDAYSNC
  496. *
  497. * Returns the number of days from the settlement date to the next coupon date.
  498. *
  499. * Excel Function:
  500. * COUPDAYSNC(settlement,maturity,frequency[,basis])
  501. *
  502. * @access public
  503. * @category Financial Functions
  504. * @param mixed settlement The security's settlement date.
  505. * The security settlement date is the date after the issue
  506. * date when the security is traded to the buyer.
  507. * @param mixed maturity The security's maturity date.
  508. * The maturity date is the date when the security expires.
  509. * @param mixed frequency the number of coupon payments per year.
  510. * Valid frequency values are:
  511. * 1 Annual
  512. * 2 Semi-Annual
  513. * 4 Quarterly
  514. * If working in Gnumeric Mode, the following frequency options are
  515. * also available
  516. * 6 Bimonthly
  517. * 12 Monthly
  518. * @param integer basis The type of day count to use.
  519. * 0 or omitted US (NASD) 30/360
  520. * 1 Actual/actual
  521. * 2 Actual/360
  522. * 3 Actual/365
  523. * 4 European 30/360
  524. * @return float
  525. */
  526. public static function COUPDAYSNC($settlement, $maturity, $frequency, $basis = 0)
  527. {
  528. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  529. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  530. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  531. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  532. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  533. return PHPExcel_Calculation_Functions::VALUE();
  534. }
  535. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  536. return PHPExcel_Calculation_Functions::VALUE();
  537. }
  538. if (($settlement > $maturity) ||
  539. (!self::isValidFrequency($frequency)) ||
  540. (($basis < 0) || ($basis > 4))) {
  541. return PHPExcel_Calculation_Functions::NaN();
  542. }
  543. $daysPerYear = self::daysPerYear(PHPExcel_Calculation_DateTime::YEAR($settlement), $basis);
  544. $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
  545. return PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $next, $basis) * $daysPerYear;
  546. }
  547. /**
  548. * COUPNCD
  549. *
  550. * Returns the next coupon date after the settlement date.
  551. *
  552. * Excel Function:
  553. * COUPNCD(settlement,maturity,frequency[,basis])
  554. *
  555. * @access public
  556. * @category Financial Functions
  557. * @param mixed settlement The security's settlement date.
  558. * The security settlement date is the date after the issue
  559. * date when the security is traded to the buyer.
  560. * @param mixed maturity The security's maturity date.
  561. * The maturity date is the date when the security expires.
  562. * @param mixed frequency the number of coupon payments per year.
  563. * Valid frequency values are:
  564. * 1 Annual
  565. * 2 Semi-Annual
  566. * 4 Quarterly
  567. * If working in Gnumeric Mode, the following frequency options are
  568. * also available
  569. * 6 Bimonthly
  570. * 12 Monthly
  571. * @param integer basis The type of day count to use.
  572. * 0 or omitted US (NASD) 30/360
  573. * 1 Actual/actual
  574. * 2 Actual/360
  575. * 3 Actual/365
  576. * 4 European 30/360
  577. * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
  578. * depending on the value of the ReturnDateType flag
  579. */
  580. public static function COUPNCD($settlement, $maturity, $frequency, $basis = 0)
  581. {
  582. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  583. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  584. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  585. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  586. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  587. return PHPExcel_Calculation_Functions::VALUE();
  588. }
  589. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  590. return PHPExcel_Calculation_Functions::VALUE();
  591. }
  592. if (($settlement > $maturity) ||
  593. (!self::isValidFrequency($frequency)) ||
  594. (($basis < 0) || ($basis > 4))) {
  595. return PHPExcel_Calculation_Functions::NaN();
  596. }
  597. return self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
  598. }
  599. /**
  600. * COUPNUM
  601. *
  602. * Returns the number of coupons payable between the settlement date and maturity date,
  603. * rounded up to the nearest whole coupon.
  604. *
  605. * Excel Function:
  606. * COUPNUM(settlement,maturity,frequency[,basis])
  607. *
  608. * @access public
  609. * @category Financial Functions
  610. * @param mixed settlement The security's settlement date.
  611. * The security settlement date is the date after the issue
  612. * date when the security is traded to the buyer.
  613. * @param mixed maturity The security's maturity date.
  614. * The maturity date is the date when the security expires.
  615. * @param mixed frequency the number of coupon payments per year.
  616. * Valid frequency values are:
  617. * 1 Annual
  618. * 2 Semi-Annual
  619. * 4 Quarterly
  620. * If working in Gnumeric Mode, the following frequency options are
  621. * also available
  622. * 6 Bimonthly
  623. * 12 Monthly
  624. * @param integer basis The type of day count to use.
  625. * 0 or omitted US (NASD) 30/360
  626. * 1 Actual/actual
  627. * 2 Actual/360
  628. * 3 Actual/365
  629. * 4 European 30/360
  630. * @return integer
  631. */
  632. public static function COUPNUM($settlement, $maturity, $frequency, $basis = 0)
  633. {
  634. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  635. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  636. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  637. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  638. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  639. return PHPExcel_Calculation_Functions::VALUE();
  640. }
  641. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  642. return PHPExcel_Calculation_Functions::VALUE();
  643. }
  644. if (($settlement > $maturity) ||
  645. (!self::isValidFrequency($frequency)) ||
  646. (($basis < 0) || ($basis > 4))) {
  647. return PHPExcel_Calculation_Functions::NaN();
  648. }
  649. $settlement = self::couponFirstPeriodDate($settlement, $maturity, $frequency, true);
  650. $daysBetweenSettlementAndMaturity = PHPExcel_Calculation_DateTime::YEARFRAC($settlement, $maturity, $basis) * 365;
  651. switch ($frequency) {
  652. case 1: // annual payments
  653. return ceil($daysBetweenSettlementAndMaturity / 360);
  654. case 2: // half-yearly
  655. return ceil($daysBetweenSettlementAndMaturity / 180);
  656. case 4: // quarterly
  657. return ceil($daysBetweenSettlementAndMaturity / 90);
  658. case 6: // bimonthly
  659. return ceil($daysBetweenSettlementAndMaturity / 60);
  660. case 12: // monthly
  661. return ceil($daysBetweenSettlementAndMaturity / 30);
  662. }
  663. return PHPExcel_Calculation_Functions::VALUE();
  664. }
  665. /**
  666. * COUPPCD
  667. *
  668. * Returns the previous coupon date before the settlement date.
  669. *
  670. * Excel Function:
  671. * COUPPCD(settlement,maturity,frequency[,basis])
  672. *
  673. * @access public
  674. * @category Financial Functions
  675. * @param mixed settlement The security's settlement date.
  676. * The security settlement date is the date after the issue
  677. * date when the security is traded to the buyer.
  678. * @param mixed maturity The security's maturity date.
  679. * The maturity date is the date when the security expires.
  680. * @param mixed frequency the number of coupon payments per year.
  681. * Valid frequency values are:
  682. * 1 Annual
  683. * 2 Semi-Annual
  684. * 4 Quarterly
  685. * If working in Gnumeric Mode, the following frequency options are
  686. * also available
  687. * 6 Bimonthly
  688. * 12 Monthly
  689. * @param integer basis The type of day count to use.
  690. * 0 or omitted US (NASD) 30/360
  691. * 1 Actual/actual
  692. * 2 Actual/360
  693. * 3 Actual/365
  694. * 4 European 30/360
  695. * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object,
  696. * depending on the value of the ReturnDateType flag
  697. */
  698. public static function COUPPCD($settlement, $maturity, $frequency, $basis = 0)
  699. {
  700. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  701. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  702. $frequency = (int) PHPExcel_Calculation_Functions::flattenSingleValue($frequency);
  703. $basis = (is_null($basis)) ? 0 : (int) PHPExcel_Calculation_Functions::flattenSingleValue($basis);
  704. if (is_string($settlement = PHPExcel_Calculation_DateTime::getDateValue($settlement))) {
  705. return PHPExcel_Calculation_Functions::VALUE();
  706. }
  707. if (is_string($maturity = PHPExcel_Calculation_DateTime::getDateValue($maturity))) {
  708. return PHPExcel_Calculation_Functions::VALUE();
  709. }
  710. if (($settlement > $maturity) ||
  711. (!self::isValidFrequency($frequency)) ||
  712. (($basis < 0) || ($basis > 4))) {
  713. return PHPExcel_Calculation_Functions::NaN();
  714. }
  715. return self::couponFirstPeriodDate($settlement, $maturity, $frequency, false);
  716. }
  717. /**
  718. * CUMIPMT
  719. *
  720. * Returns the cumulative interest paid on a loan between the start and end periods.
  721. *
  722. * Excel Function:
  723. * CUMIPMT(rate,nper,pv,start,end[,type])
  724. *
  725. * @access public
  726. * @category Financial Functions
  727. * @param float $rate The Interest rate
  728. * @param integer $nper The total number of payment periods
  729. * @param float $pv Present Value
  730. * @param integer $start The first period in the calculation.
  731. * Payment periods are numbered beginning with 1.
  732. * @param integer $end The last period in the calculation.
  733. * @param integer $type A number 0 or 1 and indicates when payments are due:
  734. * 0 or omitted At the end of the period.
  735. * 1 At the beginning of the period.
  736. * @return float
  737. */
  738. public static function CUMIPMT($rate, $nper, $pv, $start, $end, $type = 0)
  739. {
  740. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  741. $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper);
  742. $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv);
  743. $start = (int) PHPExcel_Calculation_Functions::flattenSingleValue($start);
  744. $end = (int) PHPExcel_Calculation_Functions::flattenSingleValue($end);
  745. $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type);
  746. // Validate parameters
  747. if ($type != 0 && $type != 1) {
  748. return PHPExcel_Calculation_Functions::NaN();
  749. }
  750. if ($start < 1 || $start > $end) {
  751. return PHPExcel_Calculation_Functions::VALUE();
  752. }
  753. // Calculate
  754. $interest = 0;
  755. for ($per = $start; $per <= $end; ++$per) {
  756. $interest += self::IPMT($rate, $per, $nper, $pv, 0, $type);
  757. }
  758. return $interest;
  759. }
  760. /**
  761. * CUMPRINC
  762. *
  763. * Returns the cumulative principal paid on a loan between the start and end periods.
  764. *
  765. * Excel Function:
  766. * CUMPRINC(rate,nper,pv,start,end[,type])
  767. *
  768. * @access public
  769. * @category Financial Functions
  770. * @param float $rate The Interest rate
  771. * @param integer $nper The total number of payment periods
  772. * @param float $pv Present Value
  773. * @param integer $start The first period in the calculation.
  774. * Payment periods are numbered beginning with 1.
  775. * @param integer $end The last period in the calculation.
  776. * @param integer $type A number 0 or 1 and indicates when payments are due:
  777. * 0 or omitted At the end of the period.
  778. * 1 At the beginning of the period.
  779. * @return float
  780. */
  781. public static function CUMPRINC($rate, $nper, $pv, $start, $end, $type = 0)
  782. {
  783. $rate = PHPExcel_Calculation_Functions::flattenSingleValue($rate);
  784. $nper = (int) PHPExcel_Calculation_Functions::flattenSingleValue($nper);
  785. $pv = PHPExcel_Calculation_Functions::flattenSingleValue($pv);
  786. $start = (int) PHPExcel_Calculation_Functions::flattenSingleValue($start);
  787. $end = (int) PHPExcel_Calculation_Functions::flattenSingleValue($end);
  788. $type = (int) PHPExcel_Calculation_Functions::flattenSingleValue($type);
  789. // Validate parameters
  790. if ($type != 0 && $type != 1) {
  791. return PHPExcel_Calculation_Functions::NaN();
  792. }
  793. if ($start < 1 || $start > $end) {
  794. return PHPExcel_Calculation_Functions::VALUE();
  795. }
  796. // Calculate
  797. $principal = 0;
  798. for ($per = $start; $per <= $end; ++$per) {
  799. $principal += self::PPMT($rate, $per, $nper, $pv, 0, $type);
  800. }
  801. return $principal;
  802. }
  803. /**
  804. * DB
  805. *
  806. * Returns the depreciation of an asset for a specified period using the
  807. * fixed-declining balance method.
  808. * This form of depreciation is used if you want to get a higher depreciation value
  809. * at the beginning of the depreciation (as opposed to linear depreciation). The
  810. * depreciation value is reduced with every depreciation period by the depreciation
  811. * already deducted from the initial cost.
  812. *
  813. * Excel Function:
  814. * DB(cost,salvage,life,period[,month])
  815. *
  816. * @access public
  817. * @category Financial Functions
  818. * @param float cost Initial cost of the asset.
  819. * @param float salvage Value at the end of the depreciation.
  820. * (Sometimes called the salvage value of the asset)
  821. * @param integer life Number of periods over which the asset is depreciated.
  822. * (Sometimes called the useful life of the asset)
  823. * @param integer period The period for which you want to calculate the
  824. * depreciation. Period must use the same units as life.
  825. * @param integer month Number of months in the first year. If month is omitted,
  826. * it defaults to 12.
  827. * @return float
  828. */
  829. public static function DB($cost, $salvage, $life, $period, $month = 12)
  830. {
  831. $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost);
  832. $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage);
  833. $life = PHPExcel_Calculation_Functions::flattenSingleValue($life);
  834. $period = PHPExcel_Calculation_Functions::flattenSingleValue($period);
  835. $month = PHPExcel_Calculation_Functions::flattenSingleValue($month);
  836. // Validate
  837. if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($month))) {
  838. $cost = (float) $cost;
  839. $salvage = (float) $salvage;
  840. $life = (int) $life;
  841. $period = (int) $period;
  842. $month = (int) $month;
  843. if ($cost == 0) {
  844. return 0.0;
  845. } elseif (($cost < 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($month < 1)) {
  846. return PHPExcel_Calculation_Functions::NaN();
  847. }
  848. // Set Fixed Depreciation Rate
  849. $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
  850. $fixedDepreciationRate = round($fixedDepreciationRate, 3);
  851. // Loop through each period calculating the depreciation
  852. $previousDepreciation = 0;
  853. for ($per = 1; $per <= $period; ++$per) {
  854. if ($per == 1) {
  855. $depreciation = $cost * $fixedDepreciationRate * $month / 12;
  856. } elseif ($per == ($life + 1)) {
  857. $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate * (12 - $month) / 12;
  858. } else {
  859. $depreciation = ($cost - $previousDepreciation) * $fixedDepreciationRate;
  860. }
  861. $previousDepreciation += $depreciation;
  862. }
  863. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  864. $depreciation = round($depreciation, 2);
  865. }
  866. return $depreciation;
  867. }
  868. return PHPExcel_Calculation_Functions::VALUE();
  869. }
  870. /**
  871. * DDB
  872. *
  873. * Returns the depreciation of an asset for a specified period using the
  874. * double-declining balance method or some other method you specify.
  875. *
  876. * Excel Function:
  877. * DDB(cost,salvage,life,period[,factor])
  878. *
  879. * @access public
  880. * @category Financial Functions
  881. * @param float cost Initial cost of the asset.
  882. * @param float salvage Value at the end of the depreciation.
  883. * (Sometimes called the salvage value of the asset)
  884. * @param integer life Number of periods over which the asset is depreciated.
  885. * (Sometimes called the useful life of the asset)
  886. * @param integer period The period for which you want to calculate the
  887. * depreciation. Period must use the same units as life.
  888. * @param float factor The rate at which the balance declines.
  889. * If factor is omitted, it is assumed to be 2 (the
  890. * double-declining balance method).
  891. * @return float
  892. */
  893. public static function DDB($cost, $salvage, $life, $period, $factor = 2.0)
  894. {
  895. $cost = PHPExcel_Calculation_Functions::flattenSingleValue($cost);
  896. $salvage = PHPExcel_Calculation_Functions::flattenSingleValue($salvage);
  897. $life = PHPExcel_Calculation_Functions::flattenSingleValue($life);
  898. $period = PHPExcel_Calculation_Functions::flattenSingleValue($period);
  899. $factor = PHPExcel_Calculation_Functions::flattenSingleValue($factor);
  900. // Validate
  901. if ((is_numeric($cost)) && (is_numeric($salvage)) && (is_numeric($life)) && (is_numeric($period)) && (is_numeric($factor))) {
  902. $cost = (float) $cost;
  903. $salvage = (float) $salvage;
  904. $life = (int) $life;
  905. $period = (int) $period;
  906. $factor = (float) $factor;
  907. if (($cost <= 0) || (($salvage / $cost) < 0) || ($life <= 0) || ($period < 1) || ($factor <= 0.0) || ($period > $life)) {
  908. return PHPExcel_Calculation_Functions::NaN();
  909. }
  910. // Set Fixed Depreciation Rate
  911. $fixedDepreciationRate = 1 - pow(($salvage / $cost), (1 / $life));
  912. $fixedDepreciationRate = round($fixedDepreciationRate, 3);
  913. // Loop through each period calculating the depreciation
  914. $previousDepreciation = 0;
  915. for ($per = 1; $per <= $period; ++$per) {
  916. $depreciation = min(($cost - $previousDepreciation) * ($factor / $life), ($cost - $salvage - $previousDepreciation));
  917. $previousDepreciation += $depreciation;
  918. }
  919. if (PHPExcel_Calculation_Functions::getCompatibilityMode() == PHPExcel_Calculation_Functions::COMPATIBILITY_GNUMERIC) {
  920. $depreciation = round($depreciation, 2);
  921. }
  922. return $depreciation;
  923. }
  924. return PHPExcel_Calculation_Functions::VALUE();
  925. }
  926. /**
  927. * DISC
  928. *
  929. * Returns the discount rate for a security.
  930. *
  931. * Excel Function:
  932. * DISC(settlement,maturity,price,redemption[,basis])
  933. *
  934. * @access public
  935. * @category Financial Functions
  936. * @param mixed settlement The security's settlement date.
  937. * The security settlement date is the date after the issue
  938. * date when the security is traded to the buyer.
  939. * @param mixed maturity The security's maturity date.
  940. * The maturity date is the date when the security expires.
  941. * @param integer price The security's price per $100 face value.
  942. * @param integer redemption The security's redemption value per $100 face value.
  943. * @param integer basis The type of day count to use.
  944. * 0 or omitted US (NASD) 30/360
  945. * 1 Actual/actual
  946. * 2 Actual/360
  947. * 3 Actual/365
  948. * 4 European 30/360
  949. * @return float
  950. */
  951. public static function DISC($settlement, $maturity, $price, $redemption, $basis = 0)
  952. {
  953. $settlement = PHPExcel_Calculation_Functions::flattenSingleValue($settlement);
  954. $maturity = PHPExcel_Calculation_Functions::flattenSingleValue($maturity);
  955. $price = PHPExcel_Calculation_Functions::flattenSingleValue($price);
  956. $red

Large files files are truncated, but you can click here to view the full file