{-# LANGUAGE CPP #-}

-- | Functions to work with the time value of money
module Finance.TimeValue
    (
    -- * Time value of money functions
      compound
    , compoundingFactor
    , discount
    , futureInterest

    -- * Utility functions 
    -- TODO: Should they be moved somewhere else?
    , weightedAverage
    ) where

#if __GLASGOW_HASKELL__ < 710
import Data.Foldable
#endif
import Data.Monoid

-- | Calculate interest rate from spot price, future price and time period.
futureInterest ::  Floating a => a -> a -> a -> a
futureInterest pv fv t = (fv / pv) ** (1 / t) - 1

compoundingFactor :: Floating a => a -> a -> a
compoundingFactor r t = (1 + r) ** t

compound :: Floating a => a -> a -> a -> a
compound r t pv = pv * compoundingFactor r t

discount :: Floating a => a -> a -> a -> a
discount r t fv = fv / compoundingFactor r t

-- | Weighted arithmetic mean with non-normalized weight
weightedAverage :: (Floating a, Foldable f) => f (a, a) -> a
weightedAverage  xs = (getSum $ foldMap (\(w, x) -> Sum (w * x)) xs) / (getSum $ foldMap (\(w, _) -> Sum w) xs)