hquantlib 0.0.1.1 → 0.0.1.2
raw patch · 7 files changed
+246/−1 lines, 7 files
Files
- hquantlib.cabal +7/−1
- src/QuantLib/Currency.hs +20/−0
- src/QuantLib/Options.hs +14/−0
- src/QuantLib/Prices.hs +24/−0
- src/QuantLib/Stochastic/Discretize.hs +27/−0
- src/QuantLib/Stochastic/Process.hs +95/−0
- src/QuantLib/Stochastic/Random.hs +59/−0
hquantlib.cabal view
@@ -1,5 +1,5 @@ name: hquantlib-version: 0.0.1.1+version: 0.0.1.2 license: LGPL license-file: LICENSE author: Pavel Ryzhov@@ -35,13 +35,19 @@ QuantLib.VolatilityModel QuantLib.TimeSeries QuantLib.Money+ QuantLib.Prices QuantLib.Position+ QuantLib.Options other-modules: QuantLib.Currencies.America QuantLib.Currencies.Europe QuantLib.Instruments.Instrument QuantLib.Instruments.Stock+ QuantLib.Stochastic.Discretize+ QuantLib.Stochastic.Process+ QuantLib.Stochastic.Random+ QuantLib.Currency build-depends: haskell2010 == 1.0.0.0,
+ src/QuantLib/Currency.hs view
@@ -0,0 +1,20 @@++module QuantLib.Currency+ ( module QuantLib.Currency+ )+ where++-- | Currency specification+data Currency = Currency {+ -- | currency name, e.g. "U.S. dollar"+ cName :: String,+ -- | ISO 4217 three-letter code, e.g. "USD"+ cCode :: String,+ -- | ISO 4217 numeric code, e.g. 840+ cIsoCode :: Integer,+ -- | number of fractionary parts in a unit+ cFracsPerUnit :: Integer+ } deriving (Eq)++instance Show Currency where+ showsPrec _ x s = (cCode x)++s
+ src/QuantLib/Options.hs view
@@ -0,0 +1,14 @@+module QuantLib.Options+ ( module QuantLib.Options+ ) where++data OptionType = Call | Put+ deriving (Show, Eq)++toInt :: OptionType -> Int+toInt Call = 1+toInt Put = -1++toDouble :: OptionType -> Double+toDouble Call = 1.0+toDouble Put = -1.0
+ src/QuantLib/Prices.hs view
@@ -0,0 +1,24 @@+module QuantLib.Prices+ ( module QuantLib.Prices+ ) where++-- | Price types+data PriceType = Bid | Ask | Last | Close | Mid | MidEq | MidSafe+ deriving (Show, Eq)++-- | Call price+data CallPrice = DirtyPrice {+ cpPrice :: Double+ } | CleanPrice {+ cpPrice :: Double+ } deriving (Show, Eq, Ord)++-- | Interval price+data IntervalPrice = IntervalPrice {+ ipOpen :: Double,+ ipHigh :: Double,+ ipLow :: Double,+ ipClose :: Double+ } deriving (Show, Eq)++
+ src/QuantLib/Stochastic/Discretize.hs view
@@ -0,0 +1,27 @@++module QuantLib.Stochastic.Discretize+ ( module QuantLib.Stochastic.Discretize )+ where++import QuantLib.Stochastic.Process++-- | Euler discretization of stochastic processes+data Euler = Euler { eDt :: Double }+ deriving (Show, Eq)++-- | Euler end-point discretization of stochastic processes+data EndEuler = EndEuler { eeDt :: Double }+ deriving (Show, Eq)++instance Discretize Euler where+ dDrift p e dot = (drift p dot)*(eDt e)+ dDiff p e dot = (diff p dot)*sqrt (eDt e)+ dDt _ e _ = eDt e++instance Discretize EndEuler where+ dDrift p e dot = (drift p nextDot)*(eeDt e)+ where nextDot = Dot ((getT dot) + (eeDt e)) (getX dot)+ dDiff p e dot = (diff p nextDot)*sqrt (eeDt e)+ where nextDot = Dot ((getT dot) + (eeDt e)) (getX dot) + dDt _ e _ = eeDt e+
+ src/QuantLib/Stochastic/Process.hs view
@@ -0,0 +1,95 @@++module QuantLib.Stochastic.Process+ ( module QuantLib.Stochastic.Process )+ where++import Control.Monad (foldM)+import QuantLib.Stochastic.Random (NormalGenerator (..))++-- | Discretization of stochastic process over given interval+class Discretize b where+ dDrift :: StochasticProcess a => a->b->Dot->Double+ dDiff :: StochasticProcess a => a->b->Dot->Double+ dDt :: StochasticProcess a => a->b->Dot->Double++-- | 1D Stochastic process+class StochasticProcess a where+ drift :: a->Dot->Double+ diff :: a->Dot->Double+ evolve :: Discretize b=> b->a->Dot->Double->Dot+ evolve discr p dot dw = Dot newT newX+ where newT = ((+) (getT dot) (dDt p discr dot))+ newX = (getX dot) + (dDrift p discr dot) + (dDiff p discr dot)*dw+ +-- | Dot. t and x pair+data Dot = Dot { getT :: Double, getX :: Double }+ deriving (Show, Eq)++-- | Path as list of Dots+type Path = [Dot]++-- | Generates sample path for given stochastic process under discretization and normal generator for given amount of steps, starting from x0+generatePath :: (StochasticProcess a, NormalGenerator b, Discretize c) => b->c->a->Int->Dot->IO Path+generatePath rnd discr sp steps x0 = do+ let s = replicate steps (1 :: Int)+ (path, _) <- foldM intGenPath ([x0], rnd) s+ return path+ where intGenPath (p, r) _ = do+ (dw, newRnd) <- ngGetNext r+ let newDot = evolve discr sp (last p) dw+ return (p ++ [newDot], newRnd)++-- | Geometric Brownian motion+data GeometricBrownian = GeometricBrownian { + gbDrift :: Double, + gbDiff :: Double + } deriving (Show)++instance StochasticProcess GeometricBrownian where+ drift p (Dot _ x) = (gbDrift p) * x+ diff p (Dot _ x) = (gbDiff p) * x++-- | Ito process+data ItoProcess = ItoProcess { + ipDrift :: Dot->Double, + ipDiff :: Dot->Double + }++instance StochasticProcess ItoProcess where+ drift p d = (ipDrift p) d+ diff p d = (ipDiff p) d++-- | Square-root process+data SquareRootProcess = SquareRootProcess { + srpSpeed :: Double, + srpMean :: Double,+ srpSigma :: Double+ } deriving (Show)++instance StochasticProcess SquareRootProcess where+ drift p (Dot _ x) = (srpSpeed p)*((srpMean p) - x)+ diff p (Dot _ x) = (srpSigma p)*(sqrt x)++-- | Ornstein-Uhlenbeck process+data OrnsteinUhlenbeckProcess = OrnsteinUhlenbeckProcess {+ oupSpeed :: Double,+ oupLevel :: Double,+ oupSigma :: Double+ } deriving (Show)++instance StochasticProcess OrnsteinUhlenbeckProcess where+ drift p (Dot _ x) = (oupSpeed p)*((oupLevel p) - x)+ diff p _ = (oupSigma p)++-- | Generalized Black-Scholes process+data BlackScholesProcess = BlackScholesProcess {+ bspRiskFree :: Double->Double,+ bspDividend :: Double->Double,+ bspBlackVol :: Dot->Double+ }++instance StochasticProcess BlackScholesProcess where+ drift (BlackScholesProcess r q v) dot = (r $ getT dot) - (q $ getT dot) - 0.5*(v dot)**2 + diff p dot = (bspBlackVol p) dot++
+ src/QuantLib/Stochastic/Random.hs view
@@ -0,0 +1,59 @@+module QuantLib.Stochastic.Random+ ( BoxMuller+ , createNormalGen+ , NormalGenerator (..)+ , module GSL.Random.Gen+ ) where++import GSL.Random.Gen+import Control.Monad++-- | Box-Muller method+data BoxMuller = BoxMuller {+ bmFirst :: Bool,+ bmSecondValue :: Double,+ bmRng :: RNG+ }++-- | Creates normally distributed generator+createNormalGen :: RNG->BoxMuller+createNormalGen r = BoxMuller {+ bmFirst = True,+ bmSecondValue = 0.0,+ bmRng = r+ }++-- | Generates a list of normally distributed number using generator+getRndList :: NormalGenerator a => a->Int->IO ([Double], a)+getRndList rnd n = do+ let ns = replicate n (1 :: Int)+ foldM foldFunc ([], rnd) ns+ where foldFunc (xs, r) _ = do+ (x, newRnd) <- ngGetNext r+ return (xs++[x], newRnd)++-- | Normally distributed generator+class NormalGenerator a where+ ngGetNext :: a -> IO (Double, a)++instance NormalGenerator BoxMuller where+ ngGetNext (BoxMuller True _ rng) = do+ (r, s1, s2) <- getRs+ let ratio = sqrt (-2.0*(log r)/r)+ let bm = BoxMuller {+ bmFirst = False,+ bmSecondValue = s2*ratio,+ bmRng = rng+ }+ return (s1*ratio, bm)+ where getRs = do+ x1 <- getUniformPos rng+ x2 <- getUniformPos rng+ let r = x1*x1 + x2*x2+ if (r>=1.0 || r<=0.0) then+ getRs+ else+ return (r, x1, x2)+ + ngGetNext (BoxMuller False s r) = do+ return (s, BoxMuller True s r)