packages feed

hq-0.1.0.0: src/Q/Types.hs

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE DeriveGeneric              #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}

module Q.Types (
    Observables1(..)
  , Observables2(..)
  , Observables3(..)
  , Observables4(..)
  , Observables5(..)
  , OptionType(..)
  , Cash(..)
  , Spot(..)
  , Obs1(..)
  , Obs2(..)
  , Obs3(..)
  , Obs4(..)
  , Obs5(..)
  , Strike(..)
  , Forward(..)
  , Premium(..)
  , Delta(..)
  , Vega(..)
  , Gamma(..)
  , Expiry(..)
  , YearFrac(..)
  , Rate(..)
  , DF(..)
  , Vol(..)
  , TotalVar(..)
  , TimeScaleable(..)
  , cpi
  , discountFactor
  , discount
  , undiscount
  , rateFromDiscount
  , totalVarToVol
  , volToTotalVar
  , ($*$)
  , ($/$)
  , ($+$)
  ) where

import qualified Data.ByteString as B
import           Data.Csv        (FromField (..), ToField (..))
import           Data.Time
import           GHC.Generics    (Generic)
import           Q.Time
import           Q.Time.Date
import Foreign (Storable)
import Numeric.LinearAlgebra (Element(..))
import Data.Coerce
-- | Type for Put or Calls
data OptionType  = Put | Call deriving (Generic, Eq, Show, Read, Bounded)
instance Enum OptionType where
  succ Call = Put
  succ Put  = Call

  pred = succ
  toEnum x = if signum x == 1 then Call else Put
  fromEnum Call = 1
  fromEnum Put  = -1


cpi Call = 1
cpi Put  = -1

newtype Cash     = Cash    Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable) 

newtype Spot     = Spot    Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype Forward  = Forward Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype Strike   = Strike  Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)

($*$) :: (Coercible a Double, Coercible b Double) => a -> b -> a
x1 $*$ x2 = coerce $ (coerce x1::Double) * (coerce x2::Double)

($/$) :: (Coercible a Double, Coercible b Double) => a -> b -> a
x1 $/$ x2 = coerce $ (coerce x1::Double) / (coerce x2::Double)

($+$) :: (Coercible a Double, Coercible b Double) => a -> b -> a
x1 $+$ x2 = coerce $ (coerce x1::Double) + (coerce x2::Double)



-- Later on i should add roll.
newtype Expiry   = Expiry   Day    deriving (Generic, Eq, Show, Read, Ord)

newtype Premium  = Premium  Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype Delta    = Delta    Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype Vega     = Vega     Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype Gamma    = Gamma    Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)

newtype YearFrac = YearFrac {unYearFrac:: Double} deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)

newtype Rate     = Rate Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
newtype DF       = DF   Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)

discountFactor (YearFrac t) (Rate r) = DF $ exp ((-r) * t)
discount (DF df) p = p * df
undiscount (DF df) p = p / df

rateFromDiscount (YearFrac t) (DF df) = Rate $ - (log df) / t

newtype Vol      = Vol       Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)
-- | (\w(S_0, K, T) = \sigma_{BS}(S_0, K, T)T \)
newtype TotalVar = TotalVar  Double deriving (Generic, Eq, Show, Read, Ord, Num, Fractional, Real, RealFrac, RealFloat, Floating, Storable)

totalVarToVol (TotalVar v) (YearFrac t) = Vol $ sqrt (v / t)
volToTotalVar (Vol sigma) (YearFrac t) = TotalVar $ sigma * sigma * t

instance FromField OptionType where
  parseField s | (s == "C" || s == "c") = pure Call
               | (s == "P" || s == "p")  = pure Put
instance ToField OptionType where
  toField Call = toField ("C"::B.ByteString)
  toField Put  = toField ("P"::B.ByteString)

instance FromField Spot where
  parseField s = Spot <$> parseField s
instance ToField Spot where
  toField (Spot k) = toField k

instance FromField Cash where
  parseField s = Cash <$> parseField s
instance ToField Cash where
  toField (Cash k) = toField k


instance FromField Strike where
  parseField s = Strike <$> parseField s
instance ToField Strike where
  toField (Strike k) = toField k

instance FromField Expiry where
  parseField s = Expiry <$> parseField s
instance ToField   Expiry where
  toField (Expiry k) = toField k

instance FromField Premium where
    parseField s = Premium <$> parseField s
instance ToField   Premium  where
  toField (Premium k) = toField k

instance FromField Delta where
    parseField s = Delta <$> parseField s
instance ToField   Delta  where
  toField (Delta k) = toField k

instance FromField Vega where
    parseField s =  Vega <$> parseField s
instance ToField   Vega  where
  toField (Vega k) = toField k

instance FromField Gamma where
    parseField s =  Gamma <$> parseField s
instance ToField   Gamma  where
  toField (Gamma k) = toField k

instance FromField YearFrac where
    parseField s =  YearFrac <$> parseField s
instance ToField   YearFrac  where
  toField (YearFrac k) = toField k

instance FromField Rate where
    parseField s =  Rate <$> parseField s
instance ToField   Rate  where
  toField (Rate k) = toField k


instance FromField Vol where
    parseField s =  Vol <$> parseField s
instance ToField   Vol  where
  toField (Vol k) = toField k

-- | Represents concepts that scale as a function of time such as 'Vol'
class TimeScaleable a where
  scale :: YearFrac -> a -> a

instance TimeScaleable Double where
  scale (YearFrac t) y = y * t
  
instance TimeScaleable Rate where
  scale (YearFrac t) (Rate r)  = Rate $ r * t
instance TimeScaleable Vol where
  scale (YearFrac t) (Vol sigma)  = Vol $ sigma * sqrt t


-- | Single-observable container.
data Observables1 = Observables1 {-# UNPACK #-} !Double
-- | Two observable container.
data Observables2 = Observables2 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
-- | Three observable container.
data Observables3 = Observables3 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
                                 {-# UNPACK #-} !Double
-- | Four observable container.
data Observables4 = Observables4 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
                                 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
-- | Five observable container.
data Observables5 = Observables5 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
                                 {-# UNPACK #-} !Double {-# UNPACK #-} !Double
                                 {-# UNPACK #-} !Double

class Obs1 a where
    get1 :: a -> Double

class (Obs1 a) => Obs2 a where
    get2 :: a -> Double

class (Obs2 a) => Obs3 a where
    get3 :: a -> Double

class (Obs3 a) => Obs4 a where
    get4 :: a -> Double

class (Obs4 a) => Obs5 a where
    get5 :: a -> Double

instance Obs1 Observables1 where
    get1 (Observables1 x) = x
    {-# INLINE get1 #-}

instance Obs1 Observables2 where
    get1 (Observables2 x _) = x
    {-# INLINE get1 #-}

instance Obs1 Observables3 where
    get1 (Observables3 x _ _) = x
    {-# INLINE get1 #-}

instance Obs1 Observables4 where
    get1 (Observables4 x _ _ _) = x
    {-# INLINE get1 #-}

instance Obs1 Observables5 where
    get1 (Observables5 x _ _ _ _) = x
    {-# INLINE get1 #-}

instance Obs2 Observables2 where
    get2 (Observables2 _ x) = x
    {-# INLINE get2 #-}

instance Obs2 Observables3 where
    get2 (Observables3 _ x _) = x
    {-# INLINE get2 #-}

instance Obs2 Observables4 where
    get2 (Observables4 _ x _ _) = x
    {-# INLINE get2 #-}

instance Obs2 Observables5 where
    get2 (Observables5 _ x _ _ _) = x
    {-# INLINE get2 #-}

instance Obs3 Observables3 where
    get3 (Observables3 _ _ x) = x
    {-# INLINE get3 #-}

instance Obs3 Observables4 where
    get3 (Observables4 _ _ x _) = x
    {-# INLINE get3 #-}

instance Obs3 Observables5 where
    get3 (Observables5 _ _ x _ _) = x
    {-# INLINE get3 #-}

instance Obs4 Observables4 where
    get4 (Observables4 _ _ _ x) = x
    {-# INLINE get4 #-}

instance Obs4 Observables5 where
    get4 (Observables5 _ _ _ x _) = x
    {-# INLINE get4 #-}

instance Obs5 Observables5 where
    get5 (Observables5 _ _ _ _ x) = x
    {-# INLINE get5 #-}