raft-0.3.2.2: src/Data/Function/Excel.hs
-----------------------------------------------------------------------------
--
-- Module : Data.Function.Excel
-- Copyright : (c) 2012-16 Brian W Bush
-- License : MIT
--
-- Maintainer : Brian W Bush <consult@brianwbush.info>
-- Stability : Stable
-- Portability : Portable
--
-- | Several Microsoft Excel functions, adapted from <https://gist.github.com/econ-r/dcd503815bbb271484ff>.
--
-----------------------------------------------------------------------------
{-# LANGUAGE Safe #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
module Data.Function.Excel (
-- * Finance functions
pmt
, ipmt
, ppmt
, nper
, pv
, fv
) where
import Data.Maybe (fromMaybe)
-- | Compute payments.
pmt :: Double -- ^ Interest rate per period.
-> Int -- ^ Total number of periods.
-> Double -- ^ Present value.
-> Maybe Double -- ^ Future value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each perioed.
-> Double -- ^ Payment per period.
pmt rate nper pv fv typ =
if rate /= 0
then (rate * (fv' + pv * (1+ rate)^nper)) / ((1 + rate * typ') * (1 - (1 + rate)^nper))
else -1 * (fv' + pv) / fromIntegral nper
where
fv' = fromMaybe 0 fv
typ' = if fromMaybe False typ then 1 else 0
-- | Compute interest payment.
ipmt :: Double -- ^ Interest rate per period.
-> Int -- ^ Period for which interest is to be computed.
-> Int -- ^ Total number of periods.
-> Double -- ^ Present value.
-> Maybe Double -- ^ Future value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each period.
-> Double -- ^ Interest payment.
ipmt rate per nper pv fv (Just True) = ipmt rate per nper pv fv (Just False) / (1 + rate)
ipmt rate per nper pv fv _ = - ((1 + rate)^(per-1) * (pv * rate + pmt rate nper pv fv (Just False)) - pmt rate nper pv fv (Just False))
-- | Compute principle payment.
ppmt :: Double -- ^ Interest rate per period.
-> Int -- ^ Period for which interest is to be computed.
-> Int -- ^ Total number of periods.
-> Double -- ^ Present value.
-> Maybe Double -- ^ Future value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each period.
-> Double -- ^ Interest payment.
ppmt rate per nper pv fv typ = pmt rate nper pv fv typ - ipmt rate per nper pv fv typ
-- | Number of periods for an investment.
nper :: Double -- ^ Interest rate per period.
-> Double -- ^ Payment per period.
-> Double -- ^ Present value.
-> Maybe Double -- ^ Future value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each period.
-> Double -- ^ Number of periods.
nper rate pmt pv fv typ =
if rate /= 0
then logBase (1 + rate) ((pmt * (1 + rate * typ') - fv' * rate) / (pmt * (1 + rate * typ') + pv * rate))
else - (fv' + pv) / pmt
where
fv' = fromMaybe 0 fv
typ' = if fromMaybe False typ then 1 else 0
-- | Compute prevent value.
pv :: Double -- ^ Interest rate per period.
-> Int -- ^ Total number of periods.
-> Double -- ^ Payment per period.
-> Maybe Double -- ^ Future value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each period.
-> Double -- ^ Present value.
pv rate nper pmt fv typ =
if rate /= 0
then - (fv' + pmt * (1 + rate * typ') * (((1 + rate)^nper) - 1) / rate) / (1 + rate)^nper
else - (fv' + pmt * fromIntegral nper)
where
fv' = fromMaybe 0 fv
typ' = if fromMaybe False typ then 1 else 0
-- | Compute future value.
fv :: Double -- ^ Interest rate per period.
-> Int -- ^ Total number of periods.
-> Double -- ^ Payment per period.
-> Maybe Double -- ^ Present value.
-> Maybe Bool -- ^ Whether payments are due at the beginning of each period.
-> Double -- ^ Future value.
fv rate nper pmt pv typ =
if rate /= 0
then (pmt * (1 + rate * typ') * (1 - (1 + rate)^nper) / rate) - pv' * (1 + rate)^nper
else - (pv' + pmt * fromIntegral nper)
where
pv' = fromMaybe 0 pv
typ' = if fromMaybe False typ then 1 else 0