-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
MarkBaker
committed
Mar 19, 2021
1 parent
5ad1675
commit 3818f02
Showing
3 changed files
with
218 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
|
||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial; | ||
|
||
use PhpOffice\PhpSpreadsheet\Calculation\DateTime; | ||
use PhpOffice\PhpSpreadsheet\Calculation\Functions; | ||
|
||
class Helpers | ||
{ | ||
public const DAYS_PER_YEAR_NASD = 0; | ||
public const DAYS_PER_YEAR_ACTUAL = 1; | ||
public const DAYS_PER_YEAR_360 = 2; | ||
public const DAYS_PER_YEAR_365 = 3; | ||
public const DAYS_PER_YEAR_360_EUROPEAN = 4; | ||
|
||
/** | ||
* daysPerYear. | ||
* | ||
* Returns the number of days in a specified year, as defined by the "basis" value | ||
* | ||
* @param int|string $year The year against which we're testing | ||
* @param int|string $basis The type of day count: | ||
* 0 or omitted US (NASD) 360 | ||
* 1 Actual (365 or 366 in a leap year) | ||
* 2 360 | ||
* 3 365 | ||
* 4 European 360 | ||
* | ||
* @return int|string Result, or a string containing an error | ||
*/ | ||
public static function daysPerYear($year, $basis = 0) | ||
{ | ||
switch ($basis) { | ||
case self::DAYS_PER_YEAR_NASD: | ||
case self::DAYS_PER_YEAR_360: | ||
case self::DAYS_PER_YEAR_360_EUROPEAN: | ||
return 360; | ||
case self::DAYS_PER_YEAR_365: | ||
return 365; | ||
case self::DAYS_PER_YEAR_ACTUAL: | ||
return (DateTime::isLeapYear($year)) ? 366 : 365; | ||
} | ||
|
||
return Functions::NAN(); | ||
} | ||
} |
152 changes: 152 additions & 0 deletions
152
src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
<?php | ||
|
||
namespace PhpOffice\PhpSpreadsheet\Calculation\Financial; | ||
|
||
use PhpOffice\PhpSpreadsheet\Calculation\DateTime; | ||
use PhpOffice\PhpSpreadsheet\Calculation\Functions; | ||
|
||
class TreasuryBill | ||
{ | ||
/** | ||
* TBILLEQ. | ||
* | ||
* Returns the bond-equivalent yield for a Treasury bill. | ||
* | ||
* @param mixed $settlement The Treasury bill's settlement date. | ||
* The Treasury bill's settlement date is the date after the issue date | ||
* when the Treasury bill is traded to the buyer. | ||
* @param mixed $maturity The Treasury bill's maturity date. | ||
* The maturity date is the date when the Treasury bill expires. | ||
* @param int $discount The Treasury bill's discount rate | ||
* | ||
* @return float|string Result, or a string containing an error | ||
*/ | ||
public static function bondEquivalentYield($settlement, $maturity, $discount) | ||
{ | ||
$settlement = Functions::flattenSingleValue($settlement); | ||
$maturity = Functions::flattenSingleValue($maturity); | ||
$discount = Functions::flattenSingleValue($discount); | ||
|
||
// Use TBILLPRICE for validation | ||
$testValue = self::price($settlement, $maturity, $discount); | ||
if (is_string($testValue)) { | ||
return $testValue; | ||
} | ||
|
||
if (is_string($maturity = DateTime::getDateValue($maturity))) { | ||
return Functions::VALUE(); | ||
} | ||
|
||
if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) { | ||
++$maturity; | ||
$daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; | ||
} else { | ||
$daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement)); | ||
} | ||
|
||
return (365 * $discount) / (360 - $discount * $daysBetweenSettlementAndMaturity); | ||
} | ||
|
||
/** | ||
* TBILLPRICE. | ||
* | ||
* Returns the price per $100 face value for a Treasury bill. | ||
* | ||
* @param mixed $settlement The Treasury bill's settlement date. | ||
* The Treasury bill's settlement date is the date after the issue date | ||
* when the Treasury bill is traded to the buyer. | ||
* @param mixed $maturity The Treasury bill's maturity date. | ||
* The maturity date is the date when the Treasury bill expires. | ||
* @param int $discount The Treasury bill's discount rate | ||
* | ||
* @return float|string Result, or a string containing an error | ||
*/ | ||
public static function price($settlement, $maturity, $discount) | ||
{ | ||
$settlement = Functions::flattenSingleValue($settlement); | ||
$maturity = Functions::flattenSingleValue($maturity); | ||
$discount = Functions::flattenSingleValue($discount); | ||
|
||
if (is_string($maturity = DateTime::getDateValue($maturity))) { | ||
return Functions::VALUE(); | ||
} | ||
|
||
// Validate | ||
if (is_numeric($discount)) { | ||
if ($discount <= 0) { | ||
return Functions::NAN(); | ||
} | ||
|
||
if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) { | ||
++$maturity; | ||
$daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; | ||
if (!is_numeric($daysBetweenSettlementAndMaturity)) { | ||
// return date error | ||
return $daysBetweenSettlementAndMaturity; | ||
} | ||
} else { | ||
$daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement)); | ||
} | ||
|
||
if ($daysBetweenSettlementAndMaturity > Helpers::daysPerYear(DateTime::YEAR($maturity), 1)) { | ||
return Functions::NAN(); | ||
} | ||
|
||
$price = 100 * (1 - (($discount * $daysBetweenSettlementAndMaturity) / 360)); | ||
if ($price <= 0) { | ||
return Functions::NAN(); | ||
} | ||
|
||
return $price; | ||
} | ||
|
||
return Functions::VALUE(); | ||
} | ||
|
||
/** | ||
* TBILLYIELD. | ||
* | ||
* Returns the yield for a Treasury bill. | ||
* | ||
* @param mixed $settlement The Treasury bill's settlement date. | ||
* The Treasury bill's settlement date is the date after the issue date when | ||
* the Treasury bill is traded to the buyer. | ||
* @param mixed $maturity The Treasury bill's maturity date. | ||
* The maturity date is the date when the Treasury bill expires. | ||
* @param int $price The Treasury bill's price per $100 face value | ||
* | ||
* @return float|mixed|string | ||
*/ | ||
public static function yield($settlement, $maturity, $price) | ||
{ | ||
$settlement = Functions::flattenSingleValue($settlement); | ||
$maturity = Functions::flattenSingleValue($maturity); | ||
$price = Functions::flattenSingleValue($price); | ||
|
||
// Validate | ||
if (is_numeric($price)) { | ||
if ($price <= 0) { | ||
return Functions::NAN(); | ||
} | ||
|
||
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_OPENOFFICE) { | ||
++$maturity; | ||
$daysBetweenSettlementAndMaturity = DateTime::YEARFRAC($settlement, $maturity) * 360; | ||
if (!is_numeric($daysBetweenSettlementAndMaturity)) { | ||
// return date error | ||
return $daysBetweenSettlementAndMaturity; | ||
} | ||
} else { | ||
$daysBetweenSettlementAndMaturity = (DateTime::getDateValue($maturity) - DateTime::getDateValue($settlement)); | ||
} | ||
|
||
if ($daysBetweenSettlementAndMaturity > 360) { | ||
return Functions::NAN(); | ||
} | ||
|
||
return ((100 - $price) / $price) * (360 / $daysBetweenSettlementAndMaturity); | ||
} | ||
|
||
return Functions::VALUE(); | ||
} | ||
} |