{-# LANGUAGE RecordWildCards #-}
module Q.Options.Black76
  (
    module Q.Options
  , Black76(..)
  , atmf
  , euOption
  , eucall
  , euput
  )
  where

import           Q.Options
import           Q.Types
import           Statistics.Distribution        (cumulative, density)
import           Statistics.Distribution.Normal (standard)

data Black76 = Black76 {
    Black76 -> Forward
b76F   :: Forward
  , Black76 -> DF
b76DF  :: DF
  , Black76 -> YearFrac
b76T   :: YearFrac
  , Black76 -> Vol
b76Vol :: Vol
}

-- | At the money forward strike.
atmf :: Black76 -> Strike
atmf :: Black76 -> Strike
atmf Black76{Vol
DF
YearFrac
Forward
b76Vol :: Vol
b76T :: YearFrac
b76DF :: DF
b76F :: Forward
b76Vol :: Black76 -> Vol
b76T :: Black76 -> YearFrac
b76DF :: Black76 -> DF
b76F :: Black76 -> Forward
..} = Double -> Strike
Strike Double
f
  where (Forward Double
f) = Forward
b76F

-- | European option valuation with black 76
euOption :: Black76 -> OptionType -> Strike -> Valuation
euOption :: Black76 -> OptionType -> Strike -> Valuation
euOption b76 :: Black76
b76@Black76{Vol
DF
YearFrac
Forward
b76Vol :: Vol
b76T :: YearFrac
b76DF :: DF
b76F :: Forward
b76Vol :: Black76 -> Vol
b76T :: Black76 -> YearFrac
b76DF :: Black76 -> DF
b76F :: Black76 -> Forward
..} OptionType
cp Strike
k = Premium -> Delta -> Vega -> Gamma -> Valuation
Valuation Premium
premium Delta
delta Vega
vega Gamma
gamma where
  (Forward Double
f) = Forward
b76F
  n :: Double -> Double
n           = NormalDistribution -> Double -> Double
forall d. Distribution d => d -> Double -> Double
cumulative NormalDistribution
standard
  (Vol Double
sigmaSqt) = YearFrac -> Vol -> Vol
forall a. TimeScaleable a => YearFrac -> a -> a
scale YearFrac
b76T Vol
b76Vol
  d1 :: Double
d1          = (Forward -> Vol -> Strike -> YearFrac -> Double
dPlus  Forward
b76F Vol
b76Vol Strike
k YearFrac
b76T)
  d2 :: Double
d2          = (Forward -> Vol -> Strike -> YearFrac -> Double
dMinus Forward
b76F Vol
b76Vol Strike
k YearFrac
b76T)
  nd1 :: Double
nd1         = Double -> Double
n Double
d1
  nd2 :: Double
nd2         = Double -> Double
n Double
d2
  callDelta :: Double
callDelta   = DF
b76DF DF -> Double -> Double
`discount` Double
nd1
  putDelta :: Double
putDelta    = DF
b76DF DF -> Double -> Double
`discount` (- (Double -> Double
n (-Double
d1)))
  vega :: Vega
vega        = Double -> Vega
Vega  (Double -> Vega) -> Double -> Vega
forall a b. (a -> b) -> a -> b
$ DF
b76DF DF -> Double -> Double
`discount` (NormalDistribution -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
density NormalDistribution
standard Double
d1 ) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigmaSqt
  gamma :: Gamma
gamma       = Double -> Gamma
Gamma (Double -> Gamma) -> Double -> Gamma
forall a b. (a -> b) -> a -> b
$ DF
b76DF DF -> Double -> Double
`discount` (NormalDistribution -> Double -> Double
forall d. ContDistr d => d -> Double -> Double
density NormalDistribution
standard Double
d1) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigmaSqt)
  premium :: Premium
premium  = Double -> Premium
Premium (Double -> Premium) -> Double -> Premium
forall a b. (a -> b) -> a -> b
$ case OptionType
cp of
    OptionType
Call -> DF
b76DF DF -> Double -> Double
`discount` (Double
f Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
nd1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
nd2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
k')
    OptionType
Put  -> DF
b76DF DF -> Double -> Double
`discount` (Double -> Double
n (-Double
d2) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
k' Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
n (-Double
d1) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
f)
    where (Strike Double
k') = Strike
k
  delta :: Delta
delta | OptionType
cp OptionType -> OptionType -> Bool
forall a. Eq a => a -> a -> Bool
== OptionType
Call = Double -> Delta
Delta (Double -> Delta) -> Double -> Delta
forall a b. (a -> b) -> a -> b
$ Double
callDelta
        | OptionType
cp OptionType -> OptionType -> Bool
forall a. Eq a => a -> a -> Bool
== OptionType
Put  = Double -> Delta
Delta (Double -> Delta) -> Double -> Delta
forall a b. (a -> b) -> a -> b
$ Double
putDelta

-- | see 'euOption'
euput :: Black76 -> Strike -> Valuation
euput Black76
b76 =  Black76 -> OptionType -> Strike -> Valuation
euOption Black76
b76 OptionType
Put

-- | see 'euOption'
eucall :: Black76 -> Strike -> Valuation
eucall Black76
b76 = Black76 -> OptionType -> Strike -> Valuation
euOption Black76
b76 OptionType
Call

dPlus :: Forward -> Vol -> Strike -> YearFrac -> Double
dPlus (Forward Double
f) (Vol Double
sigma) (Strike Double
k) (YearFrac Double
t) =
  Double -> Double
forall a. Fractional a => a -> a
recip (Double
sigma Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sqrt Double
t) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
forall a. Floating a => a -> a
log (Double
fDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
k) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigma Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigma) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t)
dMinus :: Forward -> Vol -> Strike -> YearFrac -> Double
dMinus (Forward Double
f) (Vol Double
sigma) (Strike Double
k) (YearFrac Double
t) =
  Double -> Double
forall a. Fractional a => a -> a
recip (Double
sigma Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sqrt Double
t) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double -> Double
forall a. Floating a => a -> a
log (Double
fDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
k) Double -> Double -> Double
forall a. Num a => a -> a -> a
- (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigma Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
sigma) Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
t)