module Q.Payoff where

import Q.Types
import Q.Time


class Payoff a where
  payoff :: (Obs1 b) => a      -- ^ The instrument.
                    -> b      -- ^ The observable at the payoff time.
                    -> Cash -- ^ Payoff amount.

-- | Path independent payoffs based on a fixed strike.
data StrikedPayoff =
  -- | Vanilla option payoff \(max (s - k, 0)\)
  --   for call and \(max (k - s, 0)\) for put
  PlainVanillaPayoff
      OptionType         -- ^ Call/Put indicator
      Strike             -- ^ Strike \(k\)
  -- | Payoff with strike expressed as percentage
  | PercentagePayoff
      OptionType         -- ^ Call/Put indicator
      Strike             -- ^ Strike in percentage.
  -- | Binary asset or nothing payoff.
  | AssetOrNothingPayoff
      OptionType         -- ^ Call/Put indicator
      Strike             -- ^ Strike \(k\)
  -- | Binary cash or nothing payoff.
  | CashOrNothingPayoff
      OptionType         -- ^ Call/Put indicator
      Strike             -- ^ Strike \(k\)
      Cash               -- ^ Cash amount.
 

instance Payoff StrikedPayoff where
  payoff :: StrikedPayoff -> b -> Cash
payoff (PlainVanillaPayoff OptionType
cp (Strike Double
k)) b
obs = Double -> Cash
Cash (Double -> Cash) -> Double -> Cash
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. Ord a => a -> a -> a
max ((OptionType -> Double
forall p. Num p => OptionType -> p
cpi OptionType
cp) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
s Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k)) Double
0 where
    s :: Double
s = b -> Double
forall a. Obs1 a => a -> Double
get1 b
obs

  payoff (PercentagePayoff OptionType
cp (Strike Double
k)) b
_ =  Double -> Cash
Cash (Double -> Cash) -> Double -> Cash
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. Ord a => a -> a -> a
max ((OptionType -> Double
forall p. Num p => OptionType -> p
cpi OptionType
cp) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k)) Double
0

  payoff (AssetOrNothingPayoff OptionType
cp (Strike Double
k)) b
obs
    | (OptionType -> Double
forall p. Num p => OptionType -> p
cpi OptionType
cp) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
s Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 = Double -> Cash
Cash (Double -> Cash) -> Double -> Cash
forall a b. (a -> b) -> a -> b
$ Double
s
    | Bool
otherwise              = Double -> Cash
Cash (Double -> Cash) -> Double -> Cash
forall a b. (a -> b) -> a -> b
$ Double
0
    where s :: Double
s = b -> Double
forall a. Obs1 a => a -> Double
get1 b
obs
  payoff (CashOrNothingPayoff OptionType
cp (Strike Double
k) (Cash Double
amount)) b
obs
    | (OptionType -> Double
forall p. Num p => OptionType -> p
cpi OptionType
cp) Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
s Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
k) Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
0 = Double -> Cash
Cash (Double -> Cash) -> Double -> Cash
forall a b. (a -> b) -> a -> b
$ Double
amount
    | Bool
otherwise = Cash
0
    where s :: Double
s = b -> Double
forall a. Obs1 a => a -> Double
get1 b
obs