hquantlib 0.0.1 → 0.0.1.1
raw patch · 13 files changed
+372/−5 lines, 13 files
Files
- hquantlib.cabal +14/−1
- src/QuantLib.hs +0/−4
- src/QuantLib/Currencies/America.hs +24/−0
- src/QuantLib/Currencies/Europe.hs +51/−0
- src/QuantLib/Instruments/Instrument.hs +23/−0
- src/QuantLib/Instruments/Stock.hs +19/−0
- src/QuantLib/Money.hs +28/−0
- src/QuantLib/Position.hs +7/−0
- src/QuantLib/PricingEngines.hs +6/−0
- src/QuantLib/PricingEngines/BlackFormula.hs +56/−0
- src/QuantLib/Quotes.hs +75/−0
- src/QuantLib/TimeSeries.hs +9/−0
- src/QuantLib/VolatilityModel.hs +60/−0
hquantlib.cabal view
@@ -1,5 +1,5 @@ name: hquantlib-version: 0.0.1+version: 0.0.1.1 license: LGPL license-file: LICENSE author: Pavel Ryzhov@@ -29,6 +29,19 @@ QuantLib.Instruments QuantLib.Currencies QuantLib.Stochastic+ QuantLib.PricingEngines+ QuantLib.PricingEngines.BlackFormula+ QuantLib.Quotes+ QuantLib.VolatilityModel+ QuantLib.TimeSeries+ QuantLib.Money+ QuantLib.Position+ + other-modules:+ QuantLib.Currencies.America+ QuantLib.Currencies.Europe+ QuantLib.Instruments.Instrument+ QuantLib.Instruments.Stock build-depends: haskell2010 == 1.0.0.0,
src/QuantLib.hs view
@@ -1,18 +1,14 @@ module QuantLib ( module QuantLib.Stochastic , module QuantLib.Money- , module QuantLib.Currencies , module QuantLib.Position , module QuantLib.TimeSeries , module QuantLib.Prices- , module QuantLib.VolatilityModel ) where import QuantLib.Stochastic import QuantLib.Money-import QuantLib.Currencies import QuantLib.Position import QuantLib.TimeSeries import QuantLib.Prices-import QuantLib.VolatilityModel
+ src/QuantLib/Currencies/America.hs view
@@ -0,0 +1,24 @@+module QuantLib.Currencies.America+ ( module QuantLib.Currencies.America+ ) where ++import QuantLib.Currency++-- | Canadian dollar+cad :: Currency+cad = Currency {+ cName = "Canadian dollar",+ cCode = "CAD",+ cIsoCode = 124,+ cFracsPerUnit = 100+ }++-- | U.S. dollar+usd :: Currency+usd = Currency {+ cName = "U.S. dollar",+ cCode = "USD",+ cIsoCode = 840,+ cFracsPerUnit = 100+ }+
+ src/QuantLib/Currencies/Europe.hs view
@@ -0,0 +1,51 @@+module QuantLib.Currencies.Europe+ ( module QuantLib.Currencies.Europe+ ) where++import QuantLib.Currency++-- | Swiss france+chf :: Currency+chf = Currency {+ cName = "Swiss franc",+ cCode = "CHF",+ cIsoCode = 756,+ cFracsPerUnit = 100+ }++-- | Czech koruna+czk :: Currency+czk = Currency {+ cName = "Czech koruna",+ cCode = "CZK",+ cIsoCode = 203,+ cFracsPerUnit = 100+ }++-- | Danish krone+dkk :: Currency+dkk = Currency {+ cName = "Danish krone",+ cCode = "DKK",+ cIsoCode = 208,+ cFracsPerUnit = 100+ }++-- | European Euro+eur :: Currency+eur = Currency {+ cName = "European Euro",+ cCode = "EUR",+ cIsoCode = 978,+ cFracsPerUnit = 100+ }++-- | British pound sterling+gbp :: Currency+gbp = Currency {+ cName = "British pound sterling",+ cCode = "GBP",+ cIsoCode = 826,+ cFracsPerUnit = 100+ }+
+ src/QuantLib/Instruments/Instrument.hs view
@@ -0,0 +1,23 @@+module QuantLib.Instruments.Instrument+ (module QuantLib.Instruments.Instrument+ ) where++import Data.Time.LocalTime+import qualified Data.Map as M++-- | Instrument type class+class Instrument a where+ iNPV :: a->Double+ iErrorEstimate :: a->Double+ 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)++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+ iDate (CompositeInstrument xs) = (iDate . head . M.keys) xs+ iIsExpired (CompositeInstrument xs) = (any iIsExpired . M.keys) xs
+ src/QuantLib/Instruments/Stock.hs view
@@ -0,0 +1,19 @@+module QuantLib.Instruments.Stock+ ( module QuantLib.Instruments.Stock+ ) where++import QuantLib.Instruments.Instrument+import Data.Time.LocalTime++-- | Single stock instrument +data Stock = Stock {+ sQuote :: Double,+ sDate :: LocalTime+ } deriving (Show)++instance Instrument Stock where+ iNPV = sQuote+ iErrorEstimate _ = 0.0+ iDate = sDate+ iIsExpired _ = False+
+ src/QuantLib/Money.hs view
@@ -0,0 +1,28 @@+module QuantLib.Money+ ( module QuantLib.Money+ ) where++import QuantLib.Currency+import QuantLib.Currencies.Europe (eur)++-- | Amount of cash. Please, note that currency conversion is not implemented yet.+data Money = Money {+ mValue :: Double,+ mCurrency :: Currency+ } deriving (Eq)++instance Show Money where+ showsPrec _ (Money v c) s = show v++" "++show c++s++instance Num Money where+ (+) (Money v0 c0) (Money v1 c1)+ | c0 == c1 = Money (v0+v1) c0+ | otherwise = error "Currency conversion is not implemented"+ (*) _ _ = error "Multiplying moneys has no sense"+ (-) (Money v0 c0) (Money v1 c1)+ | c0 == c1 = Money (v0-v1) c0+ | otherwise = error "Currency conversion is not implemented"+ negate (Money v c) = Money (-v) c+ abs (Money v c) = Money (abs v) c+ signum (Money v c) = Money (signum v) c+ fromInteger i = Money (fromInteger i) eur
+ src/QuantLib/Position.hs view
@@ -0,0 +1,7 @@+module QuantLib.Position+ (module QuantLib.Position+ ) where++-- | Position types+data Position = Long | Short+ deriving (Show, Eq)
+ src/QuantLib/PricingEngines.hs view
@@ -0,0 +1,6 @@+module QuantLib.PricingEngines+ ( module QuantLib.PricingEngines+ ) where++class PricingEngine a where+ peCalculate :: a->a
+ src/QuantLib/PricingEngines/BlackFormula.hs view
@@ -0,0 +1,56 @@+module QuantLib.PricingEngines.BlackFormula+ ( blackFormulaImpliedStdDev+ ) where++import Data.Maybe+import QuantLib.Options+import Numeric.GSL.Root+import Numeric.GSL.Special.Erf++blackFormulaImpliedStdDev :: OptionType->Double->Double->Double->Double->Double->Maybe Double->Double->Int->Maybe Double+blackFormulaImpliedStdDev opType strike forward blackPrice discount displacement guess accuracy maxIter+ | blackPrice < 0.0 = Nothing+ | discount <= 0.0 = Nothing+ | strike < 0.0 = Nothing+ | forward <= 0.0 = Nothing+ | displacement < 0.0 = Nothing+ | otherwise = Just stdDev+ where+ realGuess = fromMaybe apprGuess guess+ apprGuess = blackFormulaImpliedStdDevApproximation opType strike forward blackPrice discount displacement+ blackFunction = blackImpliedStdDevHelper opType strike forward blackPrice displacement+ ([stdDev], _) = root DNewton accuracy maxIter blackFunction [realGuess]++blackImpliedStdDevHelper :: OptionType-> Double-> Double-> Double-> Double-> [Double]-> [Double]+blackImpliedStdDevHelper opType strike forward blackPrice displacement [x] =+ [(max 0.0 result) - blackPrice]+ where result = signedForward * (cdf signedD1) - signedStrike * (cdf signedD2)+ signedD1 = d + temp+ signedD2 = d - temp+ d = signedMoneyness/x+ temp = intOpType * 0.5 * x+ intOpType= toDouble opType+ signedMoneyness = intOpType*log ((forward+displacement)/(strike+displacement))+ signedForward = intOpType*(forward+displacement)+ signedStrike = intOpType*(strike +displacement)++blackImpliedStdDevHelper _ _ _ _ _ _ = undefined++cdf :: Double -> Double+cdf x = 0.5 * (1 + erf (x/(sqrt 2)))++blackFormulaImpliedStdDevApproximation :: OptionType-> Double-> Double-> Double-> Double-> Double-> Double+blackFormulaImpliedStdDevApproximation opType strike forward blackPrice discount displacement+ | realStrike == realForward = blackPrice/discount*sqrt2pi/realForward+ | otherwise = if stdDev < 0.0 then 0.0 else stdDev+ where realForward = forward + displacement+ realStrike = strike + displacement+ intOpType = toDouble opType+ moneynessDelta = intOpType * (forward-strike)+ moneynessDeltaPi= moneynessDelta**2/pi+ temp1 = blackPrice/discount - moneynessDelta/2.0+ temp2 = temp1**2 - moneynessDeltaPi+ temp3 = if temp2<0.0 then 0.0 else sqrt temp2+ temp = sqrt2pi*(temp1 + temp3)+ sqrt2pi = sqrt (2.0*pi)+ stdDev = temp/(realForward + realStrike)
+ src/QuantLib/Quotes.hs view
@@ -0,0 +1,75 @@+module QuantLib.Quotes+ ( module QuantLib.Quotes+ ) where++import Data.Maybe+import QuantLib.Options+import QuantLib.PricingEngines.BlackFormula++-- | Base type class for market observables+class Quote a where+ qValue :: a->Maybe Double+ pureValue :: a->Double+ pureValue x = fromMaybe 0.0 (qValue x)++-- | Market element returning a stored value+data SimpleQuote = SimpleQuote (Maybe Double)+ deriving (Show, Eq)++instance Quote SimpleQuote where+ qValue (SimpleQuote x) = x++-- | Market element whose value depends on two other market elements+data CompositeQuote a = CompositeQuote {+ -- | First element+ cqQuote1 :: a,+ -- | Second element+ cqQuote2 :: a,+ -- | Composition function+ cqComposite :: a->a->Maybe Double+ }++instance Quote (CompositeQuote a) where+ qValue x = (cqComposite x) (cqQuote1 x) (cqQuote2 x)++-- | Market element whose value depends on another quote+data DerivedQuote a = DerivedQuote {+ dqQuote :: a,+ dqDerivateFunc :: a->Maybe Double+ }++instance Quote (DerivedQuote a) where+ qValue x = (dqDerivateFunc x) (dqQuote x)++-- | Quote for the implied standard deviation of an underlying+data ImpliedStdDevQuote a = ImpliedStdDevQuote {+ isdqOptionType :: OptionType,+ isdqForward :: a,+ isdqPrice :: a,+ isdqStrike :: Double,+ isdqGuess :: Maybe Double+ } deriving (Show)++instance Quote a => Quote (ImpliedStdDevQuote a) where+ qValue (ImpliedStdDevQuote opType fwd price strike guess) + = blackFormulaImpliedStdDev opType (pureValue fwd) (pureValue price) strike 1.0 0.0 guess 1.0e-6 100++-- | Quote for the Eurodollar-future implied standard deviation+data EurodollarFutureQuote a = EurodollarFutureQuote {+ efqForward :: a,+ efqCallPrice :: a,+ efqPutPrice :: a,+ efqStrike :: Double,+ efqGuess :: Maybe Double+ } deriving (Show)++instance Quote a => Quote (EurodollarFutureQuote a) where+ qValue (EurodollarFutureQuote forward callPrice putPrice strike guess)+ | strike > forwardValue = blackFormulaImpliedStdDev Call strike forwardValue putValue 1.0 0.0 guess 1.0e-6 100+ | otherwise = blackFormulaImpliedStdDev Put strike forwardValue callValue 1.0 0.0 guess 1.0e-6 100+ where+ forwardValue = 100.0 - (fromMaybe 0.0 (qValue forward))+ putValue = fromMaybe 0.0 (qValue putPrice)+ callValue = fromMaybe 0.0 (qValue callPrice)++
+ src/QuantLib/TimeSeries.hs view
@@ -0,0 +1,9 @@+module QuantLib.TimeSeries+ ( module QuantLib.TimeSeries+ ) where++import Data.Time.LocalTime+import qualified Data.Map as M++-- | Time series+type TimeSeries m = M.Map LocalTime m
+ src/QuantLib/VolatilityModel.hs view
@@ -0,0 +1,60 @@+module QuantLib.VolatilityModel+ ( module QuantLib.VolatilityModel+ ) where++import QuantLib.Prices+import QuantLib.TimeSeries+import qualified Data.Map as M++-- | Volatility type+type Volatility = Double++-- | Volatility time series+type VolatilitySeries = TimeSeries Volatility++-- | The estimator of time series of doubles+class DoubleVolatilityEstimator a where+ dveCalculate :: a->TimeSeries Double->VolatilitySeries++-- | The calculator of volatility for interval price+class IntervalPointCalculator a where+ ipcCalculatePoint :: a->IntervalPrice->Volatility++-- | Interval price volatility estimator+class IntervalVolatilityEstimator a where+ iveCalculate :: IntervalPointCalculator b => a->b->TimeSeries IntervalPrice->VolatilitySeries++-- | Simple local estimator+data SimpleLocalEstimator = SimpleLocalEstimator {+ sleYearFraction :: Double+ } deriving (Show, Eq)++instance DoubleVolatilityEstimator SimpleLocalEstimator where+ dveCalculate (SimpleLocalEstimator yf) series = M.fromList result+ where+ (result, _) = M.foldrWithKey volFunc ([], Nothing) series+ volFunc _ s (xs, Nothing) = (xs, Just s)+ volFunc k s (xs, Just s0) = ((k, estimator s0 s):xs, Just s)+ estimator s0 s1 = (abs $ log (s1/s0))/yf++-- | Garman-Klass interval estimators+data GarmanKlass = GarmanKlass {+ gkYearFraction :: Double+ } deriving (Show, Eq)++instance IntervalVolatilityEstimator GarmanKlass where+ iveCalculate (GarmanKlass yf) ipc series = M.fromList result+ where result = M.foldrWithKey volFunc [] series+ volFunc k s xs = (k, (abs $ calculatePoint s)/yf):xs+ calculatePoint = ipcCalculatePoint ipc++-- | Types of Garman-Klass estimators+data GarmanKlassPoint = GarmanKlassSimpleSigma+ | ParkinsonSigma++instance IntervalPointCalculator GarmanKlassPoint where+ ipcCalculatePoint GarmanKlassSimpleSigma (IntervalPrice open _ _ close) = (log (close/open))**2++ ipcCalculatePoint ParkinsonSigma (IntervalPrice o h l _) = (u-d)**2 / 4.0 / log 2.0+ where u = log (h/o)+ d = log (l/o)