"""price an option by the Leisen-Preimer tree"""
from BinomialTreeOption import BinomialTreeOption
import math

class BinomialLROption(BinomialTreeOption):
    def _setup_parameters_(self):
        odd_N=self.N if (self.N%2==1) else (self.N+1)
        d1=(math.log(self.S0/self.K)+((self.r-self.div)+(self.sigma**2)/2.)*self.T)\
            /(self.sigma*math.sqrt(self.T))
        d2=(math.log(self.S0/self.K)+((self.r-self.div)-(self.sigma**2)/2.)*self.T)\
            /(self.sigma*math.sqrt(self.T))
        pp_2_inversion=lambda z,n:0.5+math.copysign(1,z)*math.sqrt(0.25-
                        0.25*math.exp(-((z/(n+1./3.+0.1/(n+1)))**2.)*(n+1./6.)))
        pbar=pp_2_inversion(d1,odd_N)
        self.p=pp_2_inversion(d2,odd_N)
        self.u=1/self.df*pbar/self.p
        self.d=(1/self.df-self.p*self.u)/(1-self.p)
        self.qu=self.p
        self.qd=1-self.p

if __name__=="__main__":
    from BinomialLROption import BinomialLROption
    eu_option=BinomialLROption(50,50,0.05,0.5,3,
                                {"sigma":0.3,"is_call":False})
    print("European put:%s" %eu_option.price())
    am_option=BinomialLROption(50,50,0.05,0.5,3,
                                {"sigma":0.3,"is_call":False,"is_eu":False})
    print("American put:%s" %am_option.price())
    

        
