Skip to content

Commit

Permalink
Group #2, Treasury Bill functions
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkBaker committed Mar 19, 2021
1 parent 5ad1675 commit 3818f02
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 92 deletions.
112 changes: 20 additions & 92 deletions src/PhpSpreadsheet/Calculation/Financial.php
Original file line number Diff line number Diff line change
Expand Up @@ -2006,6 +2006,10 @@ public static function SYD($cost, $salvage, $life, $period)
*
* Returns the bond-equivalent yield for a Treasury bill.
*
* @Deprecated 1.18.0
*
* @see Use the bondEquivalentYield() method in the Financial\TreasuryBill class instead
*
* @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.
Expand All @@ -2016,37 +2020,21 @@ public static function SYD($cost, $salvage, $life, $period)
*/
public static function TBILLEQ($settlement, $maturity, $discount)
{
$settlement = Functions::flattenSingleValue($settlement);
$maturity = Functions::flattenSingleValue($maturity);
$discount = Functions::flattenSingleValue($discount);

// Use TBILLPRICE for validation
$testValue = self::TBILLPRICE($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);
return Financial\TreasuryBill::bondEquivalentYield($settlement, $maturity, $discount);
}

/**
* TBILLPRICE.
*
* Returns the yield for a Treasury bill.
* Returns the price per $100 face value for a Treasury bill.
*
* @Deprecated 1.18.0
*
* @see Use the price() method in the Financial\TreasuryBill class instead
*
* @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.
* 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
Expand All @@ -2055,53 +2043,21 @@ public static function TBILLEQ($settlement, $maturity, $discount)
*/
public static function TBILLPRICE($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 > self::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();
return Financial\TreasuryBill::price($settlement, $maturity, $discount);
}

/**
* TBILLYIELD.
*
* Returns the yield for a Treasury bill.
*
* @Deprecated 1.18.0
*
* @see Use the yield() method in the Financial\TreasuryBill class instead
*
* @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.
* 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
Expand All @@ -2110,35 +2066,7 @@ public static function TBILLPRICE($settlement, $maturity, $discount)
*/
public static function TBILLYIELD($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();
return Financial\TreasuryBill::yield($settlement, $maturity, $price);
}

private static function bothNegAndPos($neg, $pos)
Expand Down
46 changes: 46 additions & 0 deletions src/PhpSpreadsheet/Calculation/Financial/Helpers.php
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 src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php
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();
}
}

0 comments on commit 3818f02

Please sign in to comment.