diff --git a/hquantlib.cabal b/hquantlib.cabal
--- a/hquantlib.cabal
+++ b/hquantlib.cabal
@@ -1,5 +1,5 @@
 name:           hquantlib
-version:        0.0.2.1
+version:        0.0.2.3
 license:        LGPL
 license-file:   LICENSE
 author:         Pavel Ryzhov
@@ -9,7 +9,7 @@
 description:    HQuantLib is intended to be a functional style port of QuantLib (http://quantlib.org)
 build-type:     Simple
 stability:      alpha
-homepage:       http://code.google.com/p/hquantlib/
+homepage:       http://github.com/paulrzcz/hquantlib.git
 cabal-version:  >= 1.10.0
 
 source-repository head
@@ -19,8 +19,12 @@
 source-repository this
         type:           git
         location:       https://github.com/paulrzcz/hquantlib.git
-        tag:            0.0.2
+        tag:            0.0.2.3
 
+flag optimize
+        description : Enable optimizations for library and benchmarks
+        default     : True
+
 library
         default-language: Haskell2010
         exposed-modules:
@@ -29,6 +33,7 @@
                 QuantLib.Instruments
                 QuantLib.Currencies
                 QuantLib.Stochastic
+                QuantLib.Priceable
                 QuantLib.PricingEngines
                 QuantLib.PricingEngines.BlackFormula
                 QuantLib.Quotes
@@ -37,6 +42,7 @@
                 QuantLib.TimeSeries
                 QuantLib.Money
                 QuantLib.Math
+                QuantLib.Math.Copulas
                 QuantLib.Prices
                 QuantLib.Position
                 QuantLib.Options
@@ -66,4 +72,18 @@
 
         hs-source-dirs: src
         ghc-options:    -Wall
+        if flag(optimize)
+                ghc-options: -funbox-strict-fields -O2 -fspec-constr -fdicts-cheap
+
+Test-Suite main-test
+        default-language:   Haskell2010
+        type            :   exitcode-stdio-1.0
+        main-is         :   Test.hs
+        hs-source-dirs  :   src
+        build-depends   :   base,
+                            test-framework  >= 0.6,
+                            test-framework-hunit >= 0.2.7,
+                            test-framework-quickcheck2 >= 0.2.12.0,
+                            QuickCheck      >= 2.4.0,
+                            HUnit           >= 1.2.4.0
 
diff --git a/src/QuantLib.hs b/src/QuantLib.hs
--- a/src/QuantLib.hs
+++ b/src/QuantLib.hs
@@ -5,3 +5,4 @@
 import QuantLib.Position as Q
 import QuantLib.TimeSeries as Q
 import QuantLib.Prices as Q
+import QuantLib.Math as Q
diff --git a/src/QuantLib/Instruments.hs b/src/QuantLib/Instruments.hs
--- a/src/QuantLib/Instruments.hs
+++ b/src/QuantLib/Instruments.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE ExistentialQuantification #-}
 module QuantLib.Instruments
         ( module QuantLib.Instruments.Instrument
         , module QuantLib.Instruments.Stock
diff --git a/src/QuantLib/Instruments/Instrument.hs b/src/QuantLib/Instruments/Instrument.hs
--- a/src/QuantLib/Instruments/Instrument.hs
+++ b/src/QuantLib/Instruments/Instrument.hs
@@ -1,23 +1,25 @@
+{-# LANGUAGE ExistentialQuantification #-}
 module QuantLib.Instruments.Instrument
-        (module QuantLib.Instruments.Instrument
-        ) where
+    ( Instrument (..)
+    , CompositeInstrument (..)
+    ) where
 
 import Data.Time.LocalTime
 import qualified Data.Map as M
+import QuantLib.Priceable
 
 -- | Instrument type class
 class Instrument a where
-        iNPV            :: a->Double
-        iErrorEstimate  :: a->Double
-        iDate           :: a->LocalTime
-        iIsExpired      :: a->Bool
+        iDate           :: a -> LocalTime
+        iIsExpired      :: a -> Bool
 
 -- | Composite instrument is an aggregate of other instruments.
-data Instrument a => CompositeInstrument a = CompositeInstrument (M.Map a Double) 
-        deriving (Show)
+data CompositeInstrument = forall a . (Instrument a, Priceable a) => CompositeInstrument (M.Map a Double) 
 
-instance Instrument a => Instrument (CompositeInstrument a) where
-        iNPV (CompositeInstrument xs)   = M.foldrWithKey (\k x y -> y + iNPV k * x) 0.0 xs
-        iErrorEstimate _                = 0.0
+instance Priceable CompositeInstrument where
+        npv (CompositeInstrument xs)   = M.foldrWithKey (\k x y -> y + npv k * x) 0.0 xs
+        errorEstimate _                = 0.0
+
+instance Instrument CompositeInstrument where
         iDate (CompositeInstrument xs)  = (iDate . head . M.keys) xs
         iIsExpired (CompositeInstrument xs) = (any iIsExpired . M.keys) xs
diff --git a/src/QuantLib/Instruments/Stock.hs b/src/QuantLib/Instruments/Stock.hs
--- a/src/QuantLib/Instruments/Stock.hs
+++ b/src/QuantLib/Instruments/Stock.hs
@@ -2,8 +2,9 @@
         ( module QuantLib.Instruments.Stock
         ) where
 
-import QuantLib.Instruments.Instrument
 import Data.Time.LocalTime
+import QuantLib.Instruments.Instrument
+import QuantLib.Priceable
 
 -- | Single stock instrument 
 data Stock = Stock {
@@ -12,8 +13,9 @@
         } deriving (Show)
 
 instance Instrument Stock where
-       iNPV             = sQuote
-       iErrorEstimate _ = 0.0
        iDate            = sDate
        iIsExpired     _ = False
 
+instance Priceable Stock where
+    npv (Stock q _)     = q
+    errorEstimate _     = 0.0
diff --git a/src/QuantLib/Math.hs b/src/QuantLib/Math.hs
--- a/src/QuantLib/Math.hs
+++ b/src/QuantLib/Math.hs
@@ -1,5 +1,7 @@
 module QuantLib.Math
         ( module QuantLib.Math.InverseNormal
+        , module QuantLib.Math.Copulas
         ) where
 
 import QuantLib.Math.InverseNormal
+import QuantLib.Math.Copulas
diff --git a/src/QuantLib/Math/Copulas.hs b/src/QuantLib/Math/Copulas.hs
new file mode 100644
--- /dev/null
+++ b/src/QuantLib/Math/Copulas.hs
@@ -0,0 +1,128 @@
+module QuantLib.Math.Copulas
+        ( Copula,
+          Copulas (..) 
+        ) where
+
+{-| Copula type class. 
+ -| Normally instance should implement only copulaFunc.
+ -| Method copula provides a precheck for [0..1] range for x and y but real implementation is in copulaFunc
+ -}
+class Copula a where
+        copula :: a -> Double -> Double -> Maybe Double
+        copula t = precheckRange (copulaFunc t)
+        copulaFunc :: a -> Double -> Double -> Maybe Double
+
+-- Copula must be in [0,1] range
+precheckRange :: (Double->Double->Maybe Double) -> Double -> Double -> Maybe Double
+precheckRange f x y
+        | x >= 0.0 || x <= 1.0
+        || y>= 0.0 || y <= 1.0
+                = f x y
+        | otherwise
+                = Nothing
+
+{-| Copula data types with parameters required by the concrete copula definition
+ -}
+data Copulas = ClaytonCopula Double
+        | MinCopula
+        | MaxCopula
+        | AliMikhailHaqCopula Double
+        | FarlieGumbelMorgensternCopula Double
+        | FrankCopula Double
+        | GalambosCopula Double
+        | GaussianCopula Double
+        | GumbelCopula Double
+        | HuslerReissCopula Double
+        | IndependentCopula
+        | MarshallOlkinCopula Double Double
+        | PlackettCopula Double
+
+instance Copula Copulas where
+        copulaFunc (ClaytonCopula theta)                    = claytonCopula theta
+        copulaFunc MinCopula                                = minCopula
+        copulaFunc MaxCopula                                = maxCopula
+        copulaFunc (AliMikhailHaqCopula theta)              = aliMikhailHaqCopula theta
+        copulaFunc (FarlieGumbelMorgensternCopula theta)    = farlieGumbelMorgenstern theta
+        copulaFunc (FrankCopula theta)                      = frankCopula theta
+        copulaFunc (GalambosCopula theta)                   = galambosCopula theta
+        copulaFunc (GaussianCopula rho)                     = gaussianCopula rho
+        copulaFunc (GumbelCopula theta)                     = gumbelCopula theta
+        copulaFunc (HuslerReissCopula theta)                = huslerReissCopula theta 
+        copulaFunc IndependentCopula                        = independentCopula
+        copulaFunc (MarshallOlkinCopula a b)                = marshallOlkinCopula a b
+        copulaFunc (PlackettCopula theta)                   = plackettCopula theta
+
+{- Private implementations   -}
+
+aliMikhailHaqCopula :: (Fractional a, Ord a) => a -> a -> a -> Maybe a
+aliMikhailHaqCopula theta x y
+        | theta >= -1.0 && theta <= 1.0
+                = Just ((x*y)/(1.0 - theta * (1.0-x)*(1.0-y)))
+        | otherwise
+                = Nothing
+
+farlieGumbelMorgenstern :: (Fractional a, Ord a) => a -> a -> a -> Maybe a
+farlieGumbelMorgenstern theta x y
+        | theta >= -1.0 && theta <= 1.0
+                = Just (x*y + theta*x*y*(1.0-x)*(1.0-y))
+        | otherwise
+                = Nothing
+
+{-|  Original code and algorithm from the Quantlib project
+     implemented in Haskell by Nicholas Pezolano 
+                                  npezolano "at" gmail.com
+-}
+claytonCopula :: Double -> Double -> Double -> Maybe Double
+claytonCopula theta x y
+	|  theta ==0 
+	|| theta < -1.0
+	 = Nothing
+
+	| otherwise 
+	= Just $ max( (x ** (-theta) ) +   (y ** (-theta)-1.0)  **   (-1.0/theta)) 0
+	
+minCopula ::  Ord a => a -> a -> Maybe a
+minCopula x y = Just (min x y)
+
+maxCopula ::  (Fractional a, Ord a) => a -> a -> Maybe a
+maxCopula x y = Just (max 0.0 (x+y-1.0))
+
+frankCopula ::  (Eq a, Floating a) => a -> a -> a -> Maybe a
+frankCopula theta x y
+    | theta     == 0.0 = Nothing
+    | otherwise = Just (-1.0/theta * log (1 + (exp (-theta*x) - 1.0) * (exp (-theta*y) -1.0) / (exp (-theta) - 1.0)   ))
+ 
+galambosCopula ::  (Floating a, Ord a) => a -> a -> a -> Maybe a
+galambosCopula theta x y
+    | theta <= 0.0  = Nothing
+    | otherwise     = Just (x * y * exp ( ( (-log x) ** (-theta) + (-log y) ** (-theta) ) ** (-1.0/theta)  ))
+
+gaussianCopula ::  (Fractional a, Ord a) => a -> t -> t1 -> Maybe a1
+gaussianCopula rho x y
+    | rho >= -1.0 && rho <= 1.0 = undefined
+    | otherwise                 = Nothing
+
+gumbelCopula ::  (Floating a, Ord a) => a -> a -> a -> Maybe a
+gumbelCopula theta x y
+    | theta >= 1.0  = Just (exp ( - ( (-log x) ** theta + (-log y) ** theta) ** (1.0/theta)))
+    | otherwise     = Nothing
+
+huslerReissCopula theta x y
+    | theta > 0.0   = undefined
+    | otherwise     = Nothing
+
+independentCopula ::  Num a => a -> a -> Maybe a
+independentCopula x y = Just (x*y)
+
+marshallOlkinCopula :: (Floating a, Ord a) => a -> a -> a -> a -> Maybe a
+marshallOlkinCopula a b x y
+    | a >= 0.0 && b >= 0.0  = Just (min (y * (x ** (1-a))) (x * (y ** (1-b))))
+    | otherwise             = Nothing
+
+plackettCopula ::  (Floating a, Ord a) => a -> a -> a -> Maybe a
+plackettCopula theta x y
+    | theta >= 0.0 && theta /= 1.0  = Just $ (sumXyTheta1 - sqrt (sumXyTheta1 * sumXyTheta1 - 4.0 * x * y * theta * theta1))/(2*theta1)
+    | otherwise                     = Nothing
+        where   sumXy           = x + y
+                theta1          = theta - 1.0
+                sumXyTheta1     = 1.0 + theta1 * sumXy
diff --git a/src/QuantLib/Priceable.hs b/src/QuantLib/Priceable.hs
new file mode 100644
--- /dev/null
+++ b/src/QuantLib/Priceable.hs
@@ -0,0 +1,10 @@
+{-# LANGUAGE ExistentialQuantification #-}
+module QuantLib.Priceable
+    ( Priceable (..)
+    ) where
+
+-- | All instruments and events have a net present value
+class Priceable a where
+    npv             :: a -> Double
+    errorEstimate   :: a -> Double
+
diff --git a/src/Test.hs b/src/Test.hs
new file mode 100644
--- /dev/null
+++ b/src/Test.hs
@@ -0,0 +1,26 @@
+{-# LANGUAGE BangPatterns #-}
+module Main where
+
+import Test.Framework (Test)
+import Test.Framework (defaultMain, testGroup)
+import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.QuickCheck2 (testProperty)
+import Test.QuickCheck hiding ( (==>) )
+
+main :: IO () 
+main = defaultMain tests
+
+ignore :: Functor f => f a -> f () 
+ignore = fmap (const ())
+
+sumTest :: Int->Int->Int
+sumTest x y = x + y
+
+tests :: [Test]
+tests = 
+    [ testGroup "cases" $ zipWith (testCase . show) [1 :: Int ..] $
+        [] 
+    , testGroup "properties" $ zipWith (testProperty . show) [1 :: Int ..] $ 
+        [ property $ \ a b -> sumTest a b == a + b
+        ] 
+    ]
