Math_Finance
[ class tree: Math_Finance ] [ index: Math_Finance ] [ all elements ]

Source for file Finance.php

Documentation is available at Finance.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  4.  
  5. /**
  6.  * Math_Finance: Class of financial functions
  7.  *
  8.  * Assorted financial functions for interest rates, bonds, amortizations and time value of money calculations (annuities)
  9.  * Same interface as Excel financial functions.
  10.  *
  11.  * PHP versions 4 and 5
  12.  *
  13.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  14.  * that is available through the world-wide-web at the following URI:
  15.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  16.  * the PHP License and are unable to obtain it through the web, please
  17.  * send a note to license@php.net so we can mail you a copy immediately.
  18.  *
  19.  * @category   Math
  20.  * @package    Math_Finance
  21.  * @author     Original Author <alejandro.pedraza@dataenlace.com>
  22.  * @copyright  2005 Alejandro Pedraza
  23.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  24.  * @version    CVS: $Id: Finance.php 274632 2009-01-26 14:29:28Z clockwerx $
  25.  * @link       http://pear.php.net/Math/Finance
  26.  * @since      File available since Release 1.2.0
  27.  */
  28.  
  29. // to be able to throw PEAR errors
  30. require_once 'PEAR.php';
  31.  
  32. // precision of calculations
  33. define('FINANCE_PRECISION'1E-6);
  34.  
  35. // payment types
  36. define('FINANCE_PAY_END'0);
  37. define('FINANCE_PAY_BEGIN'1);
  38.  
  39. // types of daycount basis
  40. define('FINANCE_COUNT_NASD'0);
  41. define('FINANCE_COUNT_ACTUAL_ACTUAL'1);
  42. define('FINANCE_COUNT_ACTUAL_360'2);
  43. define('FINANCE_COUNT_ACTUAL_365'3);
  44. define('FINANCE_COUNT_EUROPEAN'4);
  45.  
  46. /**
  47.  * Math_Finance: Main class
  48.  *
  49.  * @category   Math
  50.  * @package    Math_Finance
  51.  * @author     Original Author <alejandro.pedraza@dataenlace.com>
  52.  * @copyright  2005 Alejandro Pedraza
  53.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  54.  * @version    Release: @package_version@
  55.  * @link       http://pear.php.net/Math/Finance
  56.  * @since      Class available since Release 1.2.0
  57.  */
  58. {
  59.     /*******************************************************************
  60.     ** Interest Rates Conversion Functions                         *****
  61.     *******************************************************************/
  62.  
  63.     /**
  64.     * Returns the effective interest rate given the nominal rate and the number of compounding payments per year
  65.     * Excel equivalent: EFFECT
  66.     *
  67.     * @param float      Nominal interest rate
  68.     * @param int        Number of compounding payments per year
  69.     * @return float 
  70.     * @static
  71.     * @access public
  72.     */
  73.     function effectiveRate($nominal_rate$npery)
  74.     {
  75.         $npery = (int)$npery;
  76.         if ($npery < 0{
  77.             return PEAR::raiseError('Number of compounding payments per year is not positive');
  78.         }
  79.  
  80.         $effect pow((1 + $nominal_rate $npery)$npery- 1;
  81.         return $effect;
  82.     }
  83.  
  84.     /**
  85.     * Returns the nominal interest rate given the effective rate and the number of compounding payments per year
  86.     * Excel equivalent: NOMINAL
  87.     *
  88.     * @param float      Effective interest rate
  89.     * @param int        Number of compounding payments per year
  90.     * @return float 
  91.     * @static
  92.     * @access public
  93.     */
  94.     function nominalRate($effect_rate$npery)
  95.     {
  96.         $npery = (int)$npery;
  97.         if ($npery < 0{
  98.             return PEAR::raiseError('Number of compounding payments per year is not positive');
  99.         }
  100.  
  101.         $nominal $npery (pow($effect_rate + 11/$npery- 1);
  102.         return $nominal;
  103.     }
  104.  
  105.  
  106.     /*******************************************************************
  107.     ** TVM (annuities) Functions                                   *****
  108.     *******************************************************************/
  109.  
  110.     /**
  111.     * Returns the Present Value of a cash flow with constant payments and interest rate (annuities)
  112.     * Excel equivalent: PV
  113.     *
  114.     *   TVM functions solve for a term in the following formula:
  115.     *   pv(1+r)^n + pmt(1+r.type)((1+r)^n - 1)/r) +fv = 0
  116.     *
  117.     *
  118.     * @param float      Interest rate per period
  119.     * @param int        Number of periods
  120.     * @param float      Periodic payment (annuity)
  121.     * @param float      Future Value
  122.     * @param int        Payment type:
  123.                             FINANCE_PAY_END (default):    at the end of each period
  124.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  125.     * @return float 
  126.     * @static
  127.     * @access public
  128.     */
  129.     function presentValue($rate$nper$pmt$fv = 0$type = 0)
  130.     {
  131.         if ($nper < 0{
  132.             return PEAR::raiseError('Number of periods must be positive');
  133.         }
  134.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  135.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  136.         }
  137.  
  138.         if ($rate{
  139.             $pv (-$pmt (1 + $rate $type((pow(1 + $rate$nper- 1$rate$fvpow(1 + $rate$nper);
  140.         else {
  141.             $pv = -$fv $pmt $nper;
  142.         }
  143.         return $pv;
  144.     }
  145.  
  146.     /**
  147.     * Returns the Future Value of a cash flow with constant payments and interest rate (annuities)
  148.     * Excel equivalent: FV
  149.     *
  150.     * @param float      Interest rate per period
  151.     * @param int        Number of periods
  152.     * @param float      Periodic payment (annuity)
  153.     * @param float      Present Value
  154.     * @param int        Payment type:
  155.                             FINANCE_PAY_END (default):    at the end of each period
  156.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  157.     * @return float 
  158.     * @static
  159.     * @access public
  160.     */
  161.     function futureValue($rate$nper$pmt$pv = 0$type = 0)
  162.     {
  163.         if ($nper < 0{
  164.             return PEAR::raiseError('Number of periods must be positive');
  165.         }
  166.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  167.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  168.         }
  169.  
  170.         if ($rate{
  171.             $fv = -$pv pow(1 + $rate$nper$pmt (1 + $rate $type(pow(1 + $rate$nper- 1$rate;
  172.         else {
  173.             $fv = -$pv $pmt $nper;
  174.         }
  175.         return $fv;
  176.     }
  177.  
  178.     /**
  179.     * Returns the constant payment (annuity) for a cash flow with a constant interest rate
  180.     * Excel equivalent: PMT
  181.     *
  182.     * @param float      Interest rate per period
  183.     * @param int        Number of periods
  184.     * @param float      Present Value
  185.     * @param float      Future Value
  186.     * @param int        Payment type:
  187.                             FINANCE_PAY_END (default):    at the end of each period
  188.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  189.     * @return float 
  190.     * @static
  191.     * @access public
  192.     */
  193.     function payment($rate$nper$pv$fv = 0$type = 0)
  194.     {
  195.         if ($nper < 0{
  196.             return PEAR::raiseError('Number of periods must be positive');
  197.         }
  198.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  199.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  200.         }
  201.  
  202.         if ($rate{
  203.             $pmt (-$fv $pv pow(1 + $rate$nper)) (1 + $rate $type((pow(1 + $rate$nper- 1$rate);
  204.         else {
  205.             $pmt (-$pv $fv$nper;
  206.         }
  207.         return $pmt;
  208.     }
  209.  
  210.     /**
  211.     * Returns the number of periods for a cash flow with constant periodic payments (annuities), and interest rate
  212.     * Excel equivalent: NPER
  213.     *
  214.     * @param float      Interest rate per period
  215.     * @param float      Periodic payment (annuity)
  216.     * @param float      Present Value
  217.     * @param float      Future Value
  218.     * @param int        Payment type:
  219.                             FINANCE_PAY_END (default):    at the end of each period
  220.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  221.     * @return float 
  222.     * @static
  223.     * @access public
  224.     */
  225.     function periods($rate$pmt$pv$fv = 0$type = 0)
  226.     {
  227.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  228.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  229.         }
  230.  
  231.         if ($rate{
  232.             if ($pmt == 0 && $pv == 0{
  233.                 return PEAR::raiseError('Payment and Present Value can\'t be both zero when the rate is not zero');
  234.             }
  235.             $nper log(($pmt (1 + $rate $type$rate $fv($pv $pmt (1 + $rate $type$rate))
  236.                      / log(1 + $rate);
  237.         else {
  238.             if ($pmt == 0{
  239.                 return PEAR::raiseError('Rate and Payment can\'t be both zero');
  240.             }
  241.             $nper (-$pv -$fv$pmt;
  242.         }
  243.         return $nper;
  244.     }
  245.  
  246.     /**
  247.     * Returns the periodic interest rate for a cash flow with constant periodic payments (annuities)
  248.     * Excel equivalent: RATE
  249.     *
  250.     * @param int        Number of periods
  251.     * @param float      Periodic payment (annuity)
  252.     * @param float      Present Value
  253.     * @param float      Future Value
  254.     * @param int        Payment type:
  255.                             FINANCE_PAY_END (default):    at the end of each period
  256.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  257.     * @param float      guess for the interest rate
  258.     * @return float 
  259.     * @static
  260.     * @access public
  261.     */
  262.     function rate($nper$pmt$pv$fv = 0$type = 0$guess = 0.1)
  263.     {
  264.         // To solve the equation
  265.         require_once 'Math/Numerical/RootFinding/NewtonRaphson.php';
  266.         // To preserve some variables in the Newton-Raphson callback functions
  267.         require_once 'Math/Finance_FunctionParameters.php';
  268.  
  269.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  270.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  271.         }
  272.  
  273.         // Utilization of a Singleton class to preserve given values of other variables in the callback functions
  274.         $parameters = array(
  275.             'nper'  => $nper,
  276.             'pmt'   => $pmt,
  277.             'pv'    => $pv,
  278.             'fv'    => $fv,
  279.             'type'  => $type,
  280.         );
  281.         $parameters_class =Math_Finance_FunctionParameters::getInstance($parametersTrue);
  282.  
  283.         $newtonRaphson = new Math_Numerical_RootFinding_Newtonraphson(array('err_tolerance' => FINANCE_PRECISION));
  284.         return $newtonRaphson->compute(array('Math_Finance''_tvm')array('Math_Finance''_dtvm')$guess);
  285.     }
  286.  
  287.     /**
  288.     * Callback function only used by Newton-Raphson algorithm. Returns value of function to be solved.
  289.     *
  290.     * Uses a previously instanced Singleton class to retrieve given values of other variables in the function
  291.     *
  292.     * @param float      Interest rate
  293.     * @return float 
  294.     * @static
  295.     * @access private
  296.     */
  297.     function _tvm($rate)
  298.     {
  299.         require_once 'Math/Finance_FunctionParameters.php';
  300.  
  301.         $parameters_class =Math_Finance_FunctionParameters::getInstance();
  302.         $nper   $parameters_class->parameters['nper'];
  303.         $pmt    $parameters_class->parameters['pmt'];
  304.         $pv     $parameters_class->parameters['pv'];
  305.         $fv     $parameters_class->parameters['fv'];
  306.         $type   $parameters_class->parameters['type'];
  307.  
  308.         return $pv pow(1 + $rate$nper$pmt (1 + $rate $type(pow(1 + $rate$nper- 1$rate $fv;
  309.     }
  310.  
  311.     /**
  312.     * Callback function only used by Newton-Raphson algorithm. Returns value of derivative of function to be solved.
  313.     *
  314.     * Uses a previously instanced Singleton class to retrieve given values of other variables in the function
  315.     *
  316.     * @return float 
  317.     * @static
  318.     * @access private
  319.     */
  320.     function _dtvm($rate)
  321.     {
  322.         require_once 'Math/Finance_FunctionParameters.php';
  323.  
  324.         $parameters_class =Math_Finance_FunctionParameters::getInstance();
  325.         $nper   $parameters_class->parameters['nper'];
  326.         $pmt    $parameters_class->parameters['pmt'];
  327.         $pv     $parameters_class->parameters['pv'];
  328.         $type   $parameters_class->parameters['type'];
  329.  
  330.         return $nper $pv pow(1 + $rate$nper - 1)
  331.                  + $pmt *
  332.                      ($type (pow(1 + $rate$nper- 1$rate
  333.                      + (1 + $rate $type($nper $rate pow(1 + $rate$nper - 1pow(1 + $rate$nper+ 1pow($rate,2));
  334.     }
  335.  
  336.     /**
  337.     * Returns the interest payment for a given period for a cash flow with constant periodic payments (annuities)
  338.     * and interest rate.
  339.     * Excel equivalent: IMPT
  340.     *
  341.     * @param float      Interest rate per period
  342.     * @param int        Period for which the interest payment will be calculated
  343.     * @param int        Number of periods
  344.     * @param float      Present Value
  345.     * @param float      Future Value
  346.     * @param int        Payment type:
  347.                             FINANCE_PAY_END (default):    at the end of each period
  348.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  349.     * @return float 
  350.     * @static
  351.     * @access public
  352.     */
  353.     function interestPayment($rate$per$nper$pv$fv = 0$type = 0)
  354.     {
  355.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  356.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  357.         }
  358.  
  359.         $interestAndPrincipal Math_Finance::_interestAndPrincipal($rate$per$nper$pv$fv$type);
  360.         return $interestAndPrincipal[0];
  361.     }
  362.  
  363.     /**
  364.     * Returns the principal payment for a given period for a cash flow with constant periodic payments (annuities)
  365.     * and interest rate
  366.     * Excel equivalent: PPMT
  367.     *
  368.     * @param float      Interest rate per period
  369.     * @param int        Period for which the principal payment will be calculated
  370.     * @param int        Number of periods
  371.     * @param float      Present Value
  372.     * @param float      Future Value
  373.     * @param int        Payment type:
  374.                             FINANCE_PAY_END (default):    at the end of each period
  375.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  376.     * @return float 
  377.     * @static
  378.     * @access public
  379.     */
  380.     function principalPayment($rate$per$nper$pv$fv = 0$type = 0)
  381.     {
  382.         if ($type != FINANCE_PAY_END && $type != FINANCE_PAY_BEGIN{
  383.             return PEAR::raiseError('Payment type must be FINANCE_PAY_END or FINANCE_PAY_BEGIN');
  384.         }
  385.  
  386.         $interestAndPrincipal Math_Finance::_interestAndPrincipal($rate$per$nper$pv$fv$type);
  387.         return $interestAndPrincipal[1];
  388.     }
  389.  
  390.     /**
  391.     * Returns the interest and principal payment for a given period for a cash flow with constant
  392.     * periodic payments (annuities) and interest rate
  393.     *
  394.     * @param float      Interest rate per period
  395.     * @param int        Number of periods
  396.     * @param float      Present Value
  397.     * @param float      Future Value
  398.     * @param int        Payment type:
  399.                             FINANCE_PAY_END (default):    at the end of each period
  400.                             FINANCE_PAY_BEGIN:            at the beginning of each period
  401.     * @return array 
  402.     * @static
  403.     * @access private
  404.     */
  405.     function _interestAndPrincipal($rate$per$nper$pv$fv$type)
  406.     {
  407.         $pmt Math_Finance::payment($rate$nper$pv$fv$type);
  408.         //echo "pmt: $pmt\n\n";
  409.         $capital $pv;
  410.         for ($i = 1; $i<= $per$i++{
  411.             // in first period of advanced payments no interests are paid
  412.             $interest ($type && $i == 1)? 0 : -$capital $rate;
  413.             $principal $pmt $interest;
  414.             $capital += $principal;
  415.             //echo "$i\t$capital\t$interest\t$principal\n";
  416.         }
  417.         return array($interest$principal);
  418.     }
  419.  
  420.     /*******************************************************************
  421.     ** Cash Flow Functions                                        *****
  422.     *******************************************************************/
  423.  
  424.     /**
  425.     * Returns the Net Present Value of a cash flow series given a discount rate
  426.     * Excel equivalent: NPV
  427.     *
  428.     * @param float      Discount interest rate
  429.     * @param array      Cash flow series
  430.     * @return float 
  431.     * @static
  432.     * @access public
  433.     */
  434.  
  435.     function netPresentValue($rate$values)
  436.     {
  437.         if (!is_array($values)) {
  438.             return PEAR::raiseError('The cash flow series most be an array');
  439.         }
  440.     
  441.         return MATH_Finance::_npv($rate$values);
  442.     }
  443.  
  444.     /**
  445.     * Returns the internal rate of return of a cash flow series
  446.     * Excel equivalent: IRR
  447.     *
  448.     * @param array      Cash flow series
  449.     * @param float      guess for the interest rate
  450.     * @return float 
  451.     * @static
  452.     * @access public
  453.     */
  454.     function internalRateOfReturn($values$guess = 0.1)
  455.     {
  456.         // To solve the equation
  457.         require_once 'Math/Numerical/RootFinding/NewtonRaphson.php';
  458.         // To preserve some variables in the Newton-Raphson callback functions
  459.         require_once 'Math/Finance_FunctionParameters.php';
  460.  
  461.         if (!is_array($values)) {
  462.             return PEAR::raiseError('The cash flow series most be an array');
  463.         }
  464.         if (min($valuesmax($values>= 0{
  465.             return PEAR::raiseError('Cash flow must contain at least one positive value and one negative value');
  466.         }
  467.  
  468.         $parameters_class =Math_Finance_FunctionParameters::getInstance(array('values' => $values)True);
  469.         $newtonRaphson = new Math_Numerical_RootFinding_Newtonraphson(array('err_tolerance' => FINANCE_PRECISION));
  470.         return $newtonRaphson->compute(array('Math_Finance''_npv')array('Math_Finance''_dnpv')$guess);
  471.     }
  472.  
  473.     /**
  474.     * Function used by NPV() and as a callback by Newton-Raphson algorithm.
  475.     * Returns value of Net Present Value of a cash flow series.
  476.     *
  477.     * Uses a previously instanced Singleton class to retrieve given values of other variables in the function
  478.     *
  479.     * @param float      Discount interest rate
  480.     * @param array      Cash flow series
  481.     * @return float 
  482.     * @static
  483.     * @access private
  484.     */
  485.     function _npv($rate$values = array())
  486.     {
  487.         require_once 'Math/Finance_FunctionParameters.php';
  488.  
  489.         if (!$values{
  490.             // called from IRR
  491.             $parameters_class =Math_Finance_FunctionParameters::getInstance();
  492.             $values $parameters_class->parameters['values'];
  493.         }
  494.  
  495.         $npv = 0;
  496.         $nper count($values);
  497.         for ($i = 1; $i <= $nper$i++{
  498.             $npv += $values[$i-1]pow(1 + $rate$i);
  499.         }
  500.         return $npv;
  501.     }
  502.  
  503.     /**
  504.     * Callback function used by by Newton-Raphson algorithm to calculate IRR.
  505.     * Returns value of derivative function to be solved.
  506.     *
  507.     * Uses a previously instanced Singleton class to retrieve given values of other variables in the function
  508.     *
  509.     * @param float      Discount interest rate
  510.     * @param array      Cash flow series
  511.     * @return float 
  512.     * @static
  513.     * @access private
  514.     */
  515.     function _dnpv($rate$values = array())
  516.     {
  517.         require_once 'Math/Finance_FunctionParameters.php';
  518.  
  519.         if (!$values{
  520.             // called from IRR
  521.             $parameters_class =Math_Finance_FunctionParameters::getInstance();
  522.             $values $parameters_class->parameters['values'];
  523.         }
  524.  
  525.         $dnpv = 0;
  526.         $nper count($values);
  527.         for ($i = 1; $i <= $nper$i++{
  528.             $dnpv += $values[$i-1(-$ipow(1 + $rate$i - 1pow(1 + $rate2 * $i);
  529.         }
  530.         return $dnpv;
  531.     }
  532.  
  533.     /**
  534.     * Returns the internal rate of return of a cash flow series, considering both financial and reinvestment rates
  535.     * Excel equivalent: MIRR
  536.     *
  537.     * @param array      Cash flow series
  538.     * @param float      Interest rate on the money used in the cash flow
  539.     * @param float      Interest rate received when reinvested
  540.     * @return float 
  541.     * @static
  542.     * @access public
  543.     */
  544.     function modifiedInternalRateOfReturn($values$finance_rate$reinvest_rate)
  545.     {
  546.         if (!is_array($values)) {
  547.             return PEAR::raiseError('The cash flow series most be an array');
  548.         }
  549.         if (min($valuesmax($values>= 0{
  550.             return PEAR::raiseError('Cash flow must contain at least one positive value and one negative value');
  551.         }
  552.  
  553.         $positive_flows $negative_flows = array();
  554.         foreach ($values as $value{
  555.             if ($value >= 0{
  556.                 $positive_flows[$value;
  557.                 $negative_flows[= 0;
  558.             else {
  559.                 $positive_flows[= 0;
  560.                 $negative_flows[$value;
  561.             }
  562.         }
  563.  
  564.         $nper count($values);
  565.  
  566.         return pow(-Math_Finance::netPresentValue($reinvest_rate$positive_flowspow(1 + $reinvest_rate$nper)
  567.                 / Math_Finance::netPresentValue($finance_rate$negative_flows(1 + $finance_rate)1/($nper - 1)) - 1;
  568.     }
  569.  
  570.     /*******************************************************************
  571.     ** Bonds Functions                                             *****
  572.     *******************************************************************/
  573.  
  574.     /**
  575.     * Returns the difference of days between two dates based on a daycount basis
  576.     *
  577.     * @param int        First date (UNIX timestamp)
  578.     * @param int        Second date (UNIX timestamp)
  579.     * @param int        Type of day count basis:
  580.                             FINANCE_COUNT_NASD(default):    US(NASD) 30/360
  581.                             FINANCE_COUNT_ACTUAL_ACTUAL:    Actual/actual
  582.                             FINANCE_COUNT_ACTUAL_360:       Actual/360
  583.                             FINANCE_COUNT_ACTUAL_365:       Actual/365
  584.                             FINANCE_COUNT_EUROPEAN:         European 30/360
  585.     * @return int 
  586.     * @static
  587.     * @access public
  588.     */
  589.     function daysDifference($date1$date2$basis)
  590.     {
  591.         $y1 date('Y'$date1);
  592.         $m1 date('n'$date1);
  593.         $d1 date('j'$date1);
  594.         $y2 date('Y'$date2);
  595.         $m2 date('n'$date2);
  596.         $d2 date('j'$date2);
  597.  
  598.         switch ($basis{
  599.             case FINANCE_COUNT_NASD:
  600.                 if ($d2 == 31 && ($d1 == 30 || $d1 == 31)) {
  601.                     $d2 = 30;
  602.                 }
  603.                 if ($d1 == 31{
  604.                     $d1 = 30;
  605.                 }
  606.                 return ($y2 $y1* 360 + ($m2 $m1* 30 + $d2 $d1;
  607.             case FINANCE_COUNT_ACTUAL_ACTUAL:
  608.             case FINANCE_COUNT_ACTUAL_360:
  609.             case FINANCE_COUNT_ACTUAL_365:
  610.                 return ($date2 $date1/ 86400;
  611.             case FINANCE_COUNT_EUROPEAN// European 30/360
  612.                 return ($y2 $y1* 360 + ($m2 $m1* 30 + $d2 $d1;
  613.         }
  614.     }
  615.  
  616.     /**
  617.     * Returns the number of days in the year based on a daycount basis
  618.     *
  619.     * @param int        Year
  620.     * @param int        Type of day count basis:
  621.                             FINANCE_COUNT_NASD(default):    US(NASD) 30/360
  622.                             FINANCE_COUNT_ACTUAL_ACTUAL:    Actual/actual
  623.                             FINANCE_COUNT_ACTUAL_360:       Actual/360
  624.                             FINANCE_COUNT_ACTUAL_365:       Actual/365
  625.                             FINANCE_COUNT_EUROPEAN:         European 30/360
  626.     * @return int 
  627.     * @static
  628.     * @access public
  629.     */
  630.     function daysPerYear($year$basis)
  631.     {
  632.         switch ($basis{
  633.             case FINANCE_COUNT_NASD:
  634.                 return 360;
  635.             case FINANCE_COUNT_ACTUAL_ACTUAL:
  636.                 return checkdate(229$year)? 366 : 365;
  637.             case FINANCE_COUNT_ACTUAL_360:
  638.                 return 360;
  639.             case FINANCE_COUNT_ACTUAL_365:
  640.                 return 365;
  641.             case FINANCE_COUNT_EUROPEAN:
  642.                 return 360;
  643.         }
  644.     }
  645.  
  646.     /**
  647.     * Returns the yield for a treasury bill
  648.     * Excel equivalent: TBILLYIELD
  649.     *
  650.     * @param int        Settlement date (UNIX timestamp)
  651.     * @param int        Maturity date (UNIX timestamp)
  652.     * @param float      TBill price per $100 face value
  653.     * @return float 
  654.     * @static
  655.     * @access public
  656.     */
  657.     function TBillYield($settlement$maturity$pr)
  658.     {
  659.         if ($settlement >= $maturity{
  660.             return PEAR::raiseError('Maturity must happen before settlement!');
  661.         }
  662.  
  663.         $dsm ($maturity $settlement/ 86400;   // transform to days
  664.  
  665.         if ($dsm > 360{
  666.             return PEAR::raiseError("maturity can't be more than one year after settlement");
  667.         }
  668.  
  669.         return (100 - $pr* 360 / $pr $dsm;
  670.     }
  671.  
  672.     /**
  673.     * Returns the price per $100 face value for a Treasury bill
  674.     * Excel equivalent: TBILLPRICE
  675.     *
  676.     * @param int        Settlement date (UNIX timestamp)
  677.     * @param int        Maturity date (UNIX timestamp)
  678.     * @param float      T-Bill discount rate
  679.     * @return float 
  680.     * @static
  681.     * @access public
  682.     */
  683.     function TBillPrice($settlement$maturity$discount)
  684.     {
  685.         if ($settlement >= $maturity{
  686.             return PEAR::raiseError('Maturity must happen before settlement!');
  687.         }
  688.  
  689.         $dsm ($maturity $settlement/ 86400;   // transform to days
  690.  
  691.         if ($dsm > 360{
  692.             return PEAR::raiseError("maturity can't be more than one year after settlement");
  693.         }
  694.  
  695.         return 100 * (1 - $discount $dsm / 360);
  696.     }
  697.  
  698.     /**
  699.     * Returns the bond-equivalent yield for a Treasury bill
  700.     * Excel equivalent: TBILLEQ
  701.     *
  702.     * @param int        Settlement date (UNIX timestamp)
  703.     * @param int        Maturity date (UNIX timestamp)
  704.     * @param float      T-Bill discount rate
  705.     * @return float 
  706.     * @static
  707.     * @access public
  708.     */
  709.     function TBillEquivalentYield($settlement$maturity$discount)
  710.     {
  711.         if ($settlement >= $maturity{
  712.             return PEAR::raiseError('Maturity must happen before settlement!');
  713.         }
  714.  
  715.         $dsm Math_Finance::daysDifference($settlement$maturityFINANCE_COUNT_ACTUAL_365);
  716.  
  717.         if ($dsm <= 182{
  718.             // for one half year or less, the bond-equivalent-yield is equivalent to an actual/365 interest rate
  719.             return 365 * $discount (360 - $discount $dsm);
  720.         elseif ($dsm == 366 
  721.                   && ((date('m'$settlement<= 2 && checkdate(229date('Y'$settlement))) 
  722.                   || (date('m'$settlement> 2 && checkdate(229date('Y'$maturity))))) {
  723.             return 2 * (sqrt(1 - $discount * 366 / ($discount * 366 - 360)) - 1);
  724.         elseif ($dsm > 365{
  725.             return PEAR::raiseError("maturity can't be more than one year after settlement");
  726.         else {
  727.             // thanks to Zhang Qingpo (zhangqingpo@yahoo.com.cn) for solving this riddle :)
  728.             return (-$dsm sqrt(pow($dsm2(2 * $dsm - 365$discount $dsm * 365 / ($discount $dsm - 360))) ($dsm - 365 / 2);
  729.         }
  730.     }
  731.  
  732.     /**
  733.     * Returns the discount rate for a bond
  734.     * Excel equivalent: DISC
  735.     *
  736.     * @param int        Settlement date (UNIX timestamp)
  737.     * @param int        Maturity date (UNIX timestamp)
  738.     * @param float      The bond's price per $100 face value
  739.     * @param float      The bond's redemption value per $100 face value
  740.     * @param int        Type of day count basis:
  741.                             FINANCE_COUNT_NASD(default):    US(NASD) 30/360
  742.                             FINANCE_COUNT_ACTUAL_ACTUAL:    Actual/actual
  743.                             FINANCE_COUNT_ACTUAL_360:       Actual/360
  744.                             FINANCE_COUNT_ACTUAL_365:       Actual/365
  745.                             FINANCE_COUNT_EUROPEAN:         European 30/360
  746.     * @return float 
  747.     * @static
  748.     * @access public
  749.     */
  750.     function discountRate($settlement$maturity$pr$redemption$basis = 0)
  751.     {
  752.         $days_per_year Math_Finance::daysPerYear(date('Y'$settlement)$basis);
  753.         $dsm Math_Finance::daysDifference($settlement$maturity$basis);
  754.  
  755.         return ($redemption $pr$days_per_year $redemption $dsm;
  756.     }
  757.  
  758.     /**
  759.     * Returns the price per $100 face value of a discounted bond
  760.     * Excel equivalent: PRICEDISC
  761.     *
  762.     * @param int        Settlement date (UNIX timestamp)
  763.     * @param int        Maturity date (UNIX timestamp)
  764.     * @param float      The bond's discount rate
  765.     * @param float      The bond's redemption value per $100 face value
  766.     * @param int        Type of day count basis:
  767.                             FINANCE_COUNT_NASD(default):    US(NASD) 30/360
  768.                             FINANCE_COUNT_ACTUAL_ACTUAL:    Actual/actual
  769.                             FINANCE_COUNT_ACTUAL_360:       Actual/360
  770.                             FINANCE_COUNT_ACTUAL_365:       Actual/365
  771.                             FINANCE_COUNT_EUROPEAN:         European 30/360
  772.     * @return float 
  773.     * @static
  774.     * @access public
  775.     */
  776.     function priceDiscount($settlement$maturity$discount$redemption$basis = 0)
  777.     {
  778.         $days_per_year Math_Finance::daysPerYear(date('Y'$settlement)$basis);
  779.         $dsm Math_Finance::daysDifference($settlement$maturity$basis);
  780.  
  781.         return $redemption $discount $redemption $dsm $days_per_year;
  782.     }
  783.  
  784.  
  785.     /*******************************************************************
  786.     ** Depreciation Functions                                      *****
  787.     *******************************************************************/
  788.  
  789.     /**
  790.     * Returns the depreciation of an asset using the fixed-declining balance method
  791.     * Excel equivalent: DB
  792.     *
  793.     * @param float      The initial cost of the asset
  794.     * @param float      Salvage value of the asset
  795.     * @param int        Number of depreciation periods (same unit as $life)
  796.     * @param int        Number of months in the first year, defaults to 12
  797.     * @return float 
  798.     * @static
  799.     * @access public
  800.     */
  801.     function depreciationFixedDeclining($cost$salvage$life$period$month = 12)
  802.     {
  803.         $cost       = (float) $cost;
  804.         $salvage    = (float) $salvage;
  805.         $life       = (int) $life;
  806.         $period     = (int) $period;
  807.         $month      = (int) $month;
  808.         if ($cost < 0 || $life < 0{
  809.             return PEAR::raiseError('cost and life must be absolute positive numbers');
  810.         }
  811.         if ($period < 1{
  812.             return PEAR::raiseError('period must be greater or equal than one');
  813.         }
  814.  
  815.         $rate = 1 - pow(($salvage $cost)(1 / $life));
  816.         $rate round($rate3);
  817.  
  818.         $acc_depreciation = 0;
  819.         for ($i = 1; $i <= $period$i++{
  820.             if ($i == 1{
  821.                 $depreciation_period $cost $rate $month / 12;
  822.             elseif ($i == ($life + 1)) {
  823.                 $depreciation_period ($cost $acc_depreciation$rate (12 - $month/ 12;
  824.             else {
  825.                 $depreciation_period ($cost $acc_depreciation$rate;
  826.             }
  827.             $acc_depreciation += $depreciation_period;
  828.         }
  829.  
  830.         return $depreciation_period;
  831.     }
  832.  
  833.     /**
  834.     * Returns the straight-line depreciation of an asset for each period
  835.     * Excel equivalent: SLN
  836.     *
  837.     * @param float      The initial cost of the asset
  838.     * @param float      Salvage value of the asset
  839.     * @param int        Number of depreciation periods
  840.     * @return float 
  841.     * @static
  842.     * @access public
  843.     */
  844.     function depreciationStraightLine($cost$salvage$life)
  845.     {
  846.         $life       = (int) $life;
  847.         if ($cost < 0 || $life < 0{
  848.             return PEAR::raiseError('cost and life must be absolute positive numbers');
  849.         }
  850.  
  851.         return (($cost $salvage$life);
  852.     }
  853.  
  854.     /**
  855.     * Returns the depreciation for an asset in a given period using the sum-of-years' digits method
  856.     * Excel equivalent: SYD
  857.     *
  858.     * @param float      The initial cost of the asset
  859.     * @param float      Salvage value of the asset
  860.     * @param int        Number of depreciation periods
  861.     * @param int        Period (must be in the same unit as $life)
  862.     * @return float 
  863.     * @static
  864.     * @access public
  865.     */
  866.     function depreciationSYD($cost$salvage$life$per)
  867.     {
  868.         return (($cost $salvage($life $per + 1* 2 / ($life($life +1));
  869.     }
  870. }
  871.  
  872. ?>

Documentation generated on Sun, 24 Oct 2010 08:00:02 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.