hquantlib 0.0.2.1 → 0.0.2.3
raw patch · 9 files changed
+209/−17 lines, 9 filesdep +HUnitdep +QuickCheckdep +test-frameworkdep ~basePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: HUnit, QuickCheck, test-framework, test-framework-hunit, test-framework-quickcheck2
Dependency ranges changed: base
API changes (from Hackage documentation)
- QuantLib.Instruments: iErrorEstimate :: Instrument a => a -> Double
- QuantLib.Instruments: iNPV :: Instrument a => a -> Double
+ QuantLib.Math.Copulas: AliMikhailHaqCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: ClaytonCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: FarlieGumbelMorgensternCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: FrankCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: GalambosCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: GaussianCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: GumbelCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: HuslerReissCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: IndependentCopula :: Copulas
+ QuantLib.Math.Copulas: MarshallOlkinCopula :: Double -> Double -> Copulas
+ QuantLib.Math.Copulas: MaxCopula :: Copulas
+ QuantLib.Math.Copulas: MinCopula :: Copulas
+ QuantLib.Math.Copulas: PlackettCopula :: Double -> Copulas
+ QuantLib.Math.Copulas: class Copula a where copula t = precheckRange (copulaFunc t)
+ QuantLib.Math.Copulas: data Copulas
+ QuantLib.Math.Copulas: instance Copula Copulas
+ QuantLib.Priceable: class Priceable a
+ QuantLib.Priceable: errorEstimate :: Priceable a => a -> Double
+ QuantLib.Priceable: npv :: Priceable a => a -> Double
- QuantLib.Instruments: CompositeInstrument :: (Map a Double) -> CompositeInstrument a
+ QuantLib.Instruments: CompositeInstrument :: (Map a Double) -> CompositeInstrument
- QuantLib.Instruments: data Instrument a => CompositeInstrument a
+ QuantLib.Instruments: data CompositeInstrument
Files
- hquantlib.cabal +23/−3
- src/QuantLib.hs +1/−0
- src/QuantLib/Instruments.hs +1/−0
- src/QuantLib/Instruments/Instrument.hs +13/−11
- src/QuantLib/Instruments/Stock.hs +5/−3
- src/QuantLib/Math.hs +2/−0
- src/QuantLib/Math/Copulas.hs +128/−0
- src/QuantLib/Priceable.hs +10/−0
- src/Test.hs +26/−0
hquantlib.cabal view
@@ -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
src/QuantLib.hs view
@@ -5,3 +5,4 @@ import QuantLib.Position as Q import QuantLib.TimeSeries as Q import QuantLib.Prices as Q+import QuantLib.Math as Q
src/QuantLib/Instruments.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE ExistentialQuantification #-} module QuantLib.Instruments ( module QuantLib.Instruments.Instrument , module QuantLib.Instruments.Stock
src/QuantLib/Instruments/Instrument.hs view
@@ -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
src/QuantLib/Instruments/Stock.hs view
@@ -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
src/QuantLib/Math.hs view
@@ -1,5 +1,7 @@ module QuantLib.Math ( module QuantLib.Math.InverseNormal+ , module QuantLib.Math.Copulas ) where import QuantLib.Math.InverseNormal+import QuantLib.Math.Copulas
+ src/QuantLib/Math/Copulas.hs view
@@ -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
+ src/QuantLib/Priceable.hs view
@@ -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+
+ src/Test.hs view
@@ -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+ ] + ]