{-# LANGUAGE ExistentialQuantification #-}
module QuantLib.Instruments.Instrument
    ( Instrument (..)
    , CompositeInstrument (..)
    ) where

import Data.Time.LocalTime
import qualified Data.Map as M
import QuantLib.Priceable

-- | Instrument type class
class Instrument a where
        iDate           :: a -> LocalTime
        iIsExpired      :: a -> Bool

-- | Composite instrument is an aggregate of other instruments.
data CompositeInstrument = forall a . (Instrument a, Priceable a) => CompositeInstrument (M.Map a Double) 

instance Priceable CompositeInstrument where
        npv :: CompositeInstrument -> Double
npv (CompositeInstrument Map a Double
xs)   = (a -> Double -> Double -> Double)
-> Double -> Map a Double -> Double
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
M.foldrWithKey (\a
k Double
x Double
y -> Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ a -> Double
forall a. Priceable a => a -> Double
npv a
k Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x) Double
0.0 Map a Double
xs
        errorEstimate :: CompositeInstrument -> Double
errorEstimate CompositeInstrument
_                = Double
0.0

instance Instrument CompositeInstrument where
        iDate :: CompositeInstrument -> LocalTime
iDate (CompositeInstrument Map a Double
xs)  = (a -> LocalTime
forall a. Instrument a => a -> LocalTime
iDate (a -> LocalTime)
-> (Map a Double -> a) -> Map a Double -> LocalTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> a
forall a. [a] -> a
head ([a] -> a) -> (Map a Double -> [a]) -> Map a Double -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map a Double -> [a]
forall k a. Map k a -> [k]
M.keys) Map a Double
xs
        iIsExpired :: CompositeInstrument -> Bool
iIsExpired (CompositeInstrument Map a Double
xs) = ((a -> Bool) -> [a] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any a -> Bool
forall a. Instrument a => a -> Bool
iIsExpired ([a] -> Bool) -> (Map a Double -> [a]) -> Map a Double -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map a Double -> [a]
forall k a. Map k a -> [k]
M.keys) Map a Double
xs