module QuantLib.PricingEngines.BlackFormula
        ( blackFormulaImpliedStdDev
        ) where

import           Data.Maybe
import           Numeric.GSL.Root
import           Numeric.GSL.Special.Erf
import           QuantLib.Options

blackFormulaImpliedStdDev :: OptionType->Double->Double->Double->Double->Double->Maybe Double->Double->Int->Maybe Double
blackFormulaImpliedStdDev :: OptionType
-> Double
-> Double
-> Double
-> Double
-> Double
-> Maybe Double
-> Double
-> Int
-> Maybe Double
blackFormulaImpliedStdDev OptionType
opType Double
strike Double
forward Double
blackPrice Double
discount Double
displacement Maybe Double
guess Double
accuracy Int
maxIter
        | Double
blackPrice Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.0      = Maybe Double
forall a. Maybe a
Nothing
        | Double
discount  Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0.0      = Maybe Double
forall a. Maybe a
Nothing
        | Double
strike     Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.0      = Maybe Double
forall a. Maybe a
Nothing
        | Double
forward   Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0.0      = Maybe Double
forall a. Maybe a
Nothing
        | Double
displacement Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.0    = Maybe Double
forall a. Maybe a
Nothing
        | Bool
otherwise             = Double -> Maybe Double
forall a. a -> Maybe a
Just Double
stdDev
        where
                realGuess :: Double
realGuess               = Double -> Maybe Double -> Double
forall a. a -> Maybe a -> a
fromMaybe Double
apprGuess Maybe Double
guess
                apprGuess :: Double
apprGuess               = OptionType
-> Double -> Double -> Double -> Double -> Double -> Double
blackFormulaImpliedStdDevApproximation OptionType
opType Double
strike Double
forward Double
blackPrice Double
discount Double
displacement
                blackFunction :: [Double] -> [Double]
blackFunction           = OptionType
-> Double -> Double -> Double -> Double -> [Double] -> [Double]
blackImpliedStdDevHelper OptionType
opType Double
strike Double
forward Double
blackPrice Double
displacement
                ([Double
stdDev], Matrix Double
_)           = RootMethod
-> Double
-> Int
-> ([Double] -> [Double])
-> [Double]
-> ([Double], Matrix Double)
root RootMethod
DNewton Double
accuracy Int
maxIter [Double] -> [Double]
blackFunction [Double
realGuess]

{-# ANN blackImpliedStdDevHelper "NoHerbie" #-}
blackImpliedStdDevHelper :: OptionType-> Double-> Double-> Double-> Double-> [Double]-> [Double]
blackImpliedStdDevHelper :: OptionType
-> Double -> Double -> Double -> Double -> [Double] -> [Double]
blackImpliedStdDevHelper OptionType
opType Double
strike Double
forward Double
blackPrice Double
displacement [Double
x] =
        [Double -> Double -> Double
forall a. Ord a => a -> a -> a
max Double
0.0 Double
result Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
blackPrice]
        where   result :: Double
result = Double
signedForward Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
cdf Double
signedD1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
signedStrike Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
cdf Double
signedD2
                signedD1 :: Double
signedD1 = Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
temp
                signedD2 :: Double
signedD2 = Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
temp
                d :: Double
d        = Double
signedMoneynessDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
x
                temp :: Double
temp     = Double
intOpType Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x
                intOpType :: Double
intOpType= OptionType -> Double
toDouble OptionType
opType
                signedMoneyness :: Double
signedMoneyness = Double
intOpTypeDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double -> Double
forall a. Floating a => a -> a
log ((Double
forwardDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
displacement)Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
strikeDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
displacement))
                signedForward :: Double
signedForward = Double
intOpTypeDouble -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
forwardDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
displacement)
                signedStrike :: Double
signedStrike  = Double
intOpTypeDouble -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
strike Double -> Double -> Double
forall a. Num a => a -> a -> a
+Double
displacement)

blackImpliedStdDevHelper OptionType
_ Double
_ Double
_ Double
_ Double
_ [Double]
_ = [Double]
forall a. HasCallStack => a
undefined

cdf ::  Double -> Double
cdf :: Double -> Double
cdf Double
x = Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double -> Double
erf (Double
x Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
sqrt Double
2))

blackFormulaImpliedStdDevApproximation :: OptionType-> Double-> Double-> Double-> Double-> Double-> Double
blackFormulaImpliedStdDevApproximation :: OptionType
-> Double -> Double -> Double -> Double -> Double -> Double
blackFormulaImpliedStdDevApproximation OptionType
opType Double
strike Double
forward Double
blackPrice Double
discount Double
displacement
        | Double
realStrike Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
realForward     = Double
blackPriceDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
discountDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
sqrt2piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
realForward
        | Bool
otherwise     = if Double
stdDev Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0.0 then Double
0.0 else Double
stdDev
        where   realForward :: Double
realForward     = Double
forward Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
displacement
                realStrike :: Double
realStrike      = Double
strike  Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
displacement
                intOpType :: Double
intOpType       = OptionType -> Double
toDouble OptionType
opType
                moneynessDelta :: Double
moneynessDelta  = Double
intOpType Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
forwardDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
strike)
                moneynessDeltaPi :: Double
moneynessDeltaPi= Double
moneynessDeltaDouble -> Double -> Double
forall a. Floating a => a -> a -> a
**Double
2Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
forall a. Floating a => a
pi
                temp1 :: Double
temp1           = Double
blackPriceDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
discount Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
moneynessDeltaDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2.0
                temp2 :: Double
temp2           = Double
temp1Double -> Double -> Double
forall a. Floating a => a -> a -> a
**Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
moneynessDeltaPi
                temp3 :: Double
temp3           = if Double
temp2Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<Double
0.0 then Double
0.0 else Double -> Double
forall a. Floating a => a -> a
sqrt Double
temp2
                temp :: Double
temp            = Double
sqrt2piDouble -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
temp1 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
temp3)
                sqrt2pi :: Double
sqrt2pi         = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
2.0Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
pi)
                stdDev :: Double
stdDev          = Double
tempDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/(Double
realForward Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
realStrike)