import numpy as np
import matplotlib.pyplot as plt

"""
Explanation: iPython Cookbook - Analytic Pricing

A collection of various analytic pricing formulas, to be added to as and when needed
End of explanation
"""


from scipy.stats import norm

def bscall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d1 = (lnfs + 0.5 * sig2t) / sigsqrt
    d2 = (lnfs - 0.5 * sig2t) / sigsqrt
    fv = fwd * norm.cdf (d1) - strike * norm.cdf (d2)
    return df * fv

bscall(fwd=100, strike=100, sig=0.1, mat=1, df=1)

"""
Explanation: Black Scholes Pricing - Simple
European Call Option
In the below formula, $K$ is the option strike, and $T$ its maturity (in years). $df$ and $F$ are the discount factor to maturity and the forward at maturity respectively (in absence of dividends / foreign interest $df\times F$ equals the spot price), and $\sigma$ is the annualised volatility (eg 0.2 for 20%)
$$
\begin{eqnarray}
\mathrm{Call}(K,T; df,F,\sigma) &=& df \times (F N(d_1) - K N(d_2)) \
d_1 &=& \frac{\ln (F/K) + 0.5 \sigma^2 T}{\sigma \sqrt{T}} \
d_2 &=& \frac{\ln (F/K) - 0.5 \sigma^2 T}{\sigma \sqrt{T}}
\end{eqnarray}
$$
End of explanation
"""


from scipy.stats import norm

def bsput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d1 = (lnfs + 0.5 * sig2t) / sigsqrt
    d2 = (lnfs - 0.5 * sig2t) / sigsqrt
    fv = strike * norm.cdf (-d2) - fwd * norm.cdf (-d1)
    return df * fv

bsput(fwd=100, strike=100, sig=0.1, mat=1, df=1)

"""
Explanation: European Put Option
In the below formula, $K$ is the option strike, and $T$ its maturity (in years). $df$ and $F$ are the discount factor to maturity and the forward at maturity respectively (in absence of dividends / foreign interest $df\times F$ equals the spot price), and $\sigma$ is the annualised volatility (eg 0.2 for 20%)
$$
\begin{eqnarray}
\mathrm{Put}(K,T; df,F,\sigma) &=& df \times (K N(-d_2) - F N(-d_1)) \
d_1 &=& \frac{\ln (F/K) + 0.5 \sigma^2 T}{\sigma \sqrt{T}} \
d_2 &=& \frac{\ln (F/K) - 0.5 \sigma^2 T}{\sigma \sqrt{T}}
\end{eqnarray}
$$
End of explanation
"""


from scipy.stats import norm

def bsdcall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d2 = (lnfs - 0.5 * sig2t) / sigsqrt
    fv = norm.cdf(d2)
    return df * fv

def bsdput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d2 = (lnfs - 0.5 * sig2t) / sigsqrt
    fv = 1.0 - norm.cdf(d2)
    return df * fv

bsdcall(fwd=100, strike=100, sig=0.1, mat=1, df=1), bsdput(fwd=100, strike=100, sig=0.1, mat=1, df=1)

"""
Explanation: European Digital
The standard European digital call option pays one unit of the currency if and only if the spot price at expiry as above the strike $K$, ie the payoff is a step function. The price is given by the following formula ($d_2$ is defined as above)
$$
\mathrm{DCall}(K,T;df,F,\sigma)=df\times N(d_2)
$$
The price for a digitial put is $df\times(1-N(d_2))$
End of explanation
"""


from scipy.stats import norm

def bsdrcall(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d1 = (lnfs + 0.5 * sig2t) / sigsqrt
    fv = fwd * norm.cdf (d1)
    return df * fv

def bsdrput(strike=100,mat=1,fwd=100,sig=0.1,df=1):
    lnfs = log(1.0*fwd/strike)
    sig2t = sig*sig*mat
    sigsqrt = sig*sqrt(mat)
    d1 = (lnfs + 0.5 * sig2t) / sigsqrt
    fv = fwd * (1.0 - norm.cdf (d1))
    return df * fv

bsdrcall(fwd=100, strike=100, sig=0.1, mat=1, df=1), bsdrput(fwd=100, strike=100, sig=0.1, mat=1, df=1)

"""
Explanation: The reverse European digital call option pays one unit of the underlying asset if and only if the spot price at expiry as above the strike $K$. The price is given by the following formula ($d_1$ is defined as above)
$$
\mathrm{RDCall}(K,T;df,F,\sigma)=df\times F \times N(d_1)
$$
The price for the corresponding put is as above. Note that in the absence of dividends / foreign interest $df\times F=S$
End of explanation
"""


import sys
print(sys.version)

"""
Explanation: Licence and version
Copyright Stefan Loesch / oditorium 2014; all rights reserved
License: AGPL v3.0
End of explanation
"""


