----------------------------------------------------------------------------- -- -- Module : Data.Function.Excel -- Copyright : (c) 2012-16 Brian W Bush -- License : MIT -- -- Maintainer : Brian W Bush -- Stability : Stable -- Portability : Portable -- -- | Several Microsoft Excel functions, adapted from . -- ----------------------------------------------------------------------------- {-# 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