def Delta(self, tp, cp):
        # if the option is EUROPEAN we have a closed formula
        if tp == "E" or (cp == "Call" and self.q == 0):
            x = np.append(np.linspace(self.S / 100, self.S * 2.5, 1000),
                          np.array([self.S]))
            # call formula
            if cp == "Call":
                y = np.exp(-self.q * self.t) * norm.cdf(self.d1(x))
            # put formula
            elif cp == "Put":
                y = -np.exp(-self.q * self.t) * norm.cdf(-self.d1(x))
            return (plot(x[:-1], y[:-1], "Delta", "", ""), y[-1])
        # if the option is AMERICAN we use the central difference estimator
        elif tp == "A":
            x = np.linspace(self.S / 100, self.S * 2.5, 1000)
            h = x[1] - x[0]
            values = np.array([
                binomial_model(u, self.K, self.t, 0, self.q, self.r, self.s,
                               50, "American", cp) for u in x
            ])
            delta = np.array([(values[i + 2] - values[i]) / (2 * h)
                              for i in range(values.size - 2)])
            x = x[1:len(x) - 1]

            delta_curr = binomial_model(self.S + h, self.K, self.t, 0, self.q,
                                        self.r, self.s, 50, "American", cp)
            delta_curr -= binomial_model(self.S - h, self.K, self.t, 0, self.q,
                                         self.r, self.s, 50, "American", cp)
            delta_curr /= 2 * h

            return (plot(x[:-1], delta[:-1], "Delta", "", ""), delta_curr)
 def Theta(self, tp, cp):
     x = np.append(np.linspace(self.S / 100, self.S * 2.5, 1000),
                   np.array([self.S]))
     if tp == "E" or (cp == "Call" and self.q == 0):
         if cp == "Call":
             y = -np.exp(-self.q * self.t) * x * norm.pdf(
                 self.d1(x)) * self.s / (2 * np.sqrt(self.t))
             y -= self.r * self.K * np.exp(-self.r * self.t) * norm.cdf(
                 self.d2(x))
             y += self.q * x * np.exp(-self.q * self.t) * norm.cdf(
                 self.d1(x))
             y /= 252
         elif cp == "Put":
             y = -np.exp(-self.q * self.t) * x * norm.pdf(
                 -self.d1(x)) * self.s / (2 * np.sqrt(self.t))
             y += self.r * self.K * np.exp(
                 -self.r * self.t) * norm.cdf(-self.d2(x))
             y -= self.q * x * np.exp(
                 -self.q * self.t) * norm.cdf(-self.d1(x))
             y /= 252
         return (plot(x[:-1], y[:-1], "Theta", "", ""), y[-1])
     elif tp == "A":
         h = 0.001
         theta = np.array(
             [(binomial_model(u, self.K, self.t - h, 0, self.q, self.r,
                              self.s, 50, "American", cp) -
               binomial_model(u, self.K, self.t + h, 0, self.q, self.r,
                              self.s, 50, "American", cp)) / (2 * h)
              for u in x]) / 252
         return (plot(x[:-1], theta[:-1], "Theta", "", ""), theta[-1])
 def Vega(self, tp, cp):
     x = np.append(np.linspace(self.S / 100, self.S * 2.5, 1000),
                   np.array([self.S]))
     if tp == "E" or (cp == "Call" and self.q == 0):
         y = 0.01 * x * np.exp(-self.q * self.t) * np.sqrt(
             self.t) * norm.pdf(self.d1(x))
         return (plot(x[:-1], y[:-1], "Vega", "", ""), y[-1])
     elif tp == "A":
         h = 0.001
         vega = 0.01 * np.array(
             [(binomial_model(u, self.K, self.t, 0, self.q, self.r,
                              self.s + h, 50, "American", cp) -
               binomial_model(u, self.K, self.t, 0, self.q, self.r,
                              self.s - h, 50, "American", cp)) / (2 * h)
              for u in x])
         return (plot(x[:-1], vega[:-1], "Vega", "", ""), vega[-1])
 def Rho(self, tp, cp):
     x = np.append(np.linspace(self.S / 100, self.S * 2.5, 1000),
                   np.array([self.S]))
     if tp == "E" or (cp == "Call" and self.q == 0):
         if cp == "Call":
             y = 0.01 * self.K * self.t * np.exp(
                 -self.r * self.t) * norm.cdf(self.d2(x))
         elif cp == "Put":
             y = 0.01 * -self.K * self.t * np.exp(
                 -self.r * self.t) * norm.cdf(-self.d2(x))
         return (plot(x[:-1], y[:-1], "Rho", "", ""), y[-1])
     elif tp == "A":
         # the plot will be Rho on the y axis and S on the x axis
         # therefore we calculate the derivative with respect to r
         # for each value of S (this is done also in the other greeks)
         h = 0.001
         rho = 0.01 * np.array(
             [(binomial_model(u, self.K, self.t, 0, self.q, self.r + h,
                              self.s, 50, "American", cp) -
               binomial_model(u, self.K, self.t, 0, self.q, self.r - h,
                              self.s, 50, "American", cp)) / (2 * h)
              for u in x])
         return (plot(x[:-1], rho[:-1], "Rho", "", ""), rho[-1])
    def Gamma(self, tp, cp):
        if tp == "E" or (cp == "Call" and self.q == 0):
            x = np.append(np.linspace(self.S / 100, self.S * 2.5, 1000),
                          np.array([self.S]))
            # here we don't need two formulas since gamma is the same for calls and puts
            y = np.exp(-self.q * self.t) * norm.pdf(
                self.d1(x)) / (x * self.s * np.sqrt(self.t))
            return (plot(x[:-1], y[:-1], "Gamma", "", ""), y[-1])
        elif tp == "A":
            x = np.linspace(self.S / 100, self.S * 2.5, 1000)
            h = x[1] - x[0]
            values = np.array([
                binomial_model(u, self.K, self.t, 0, self.q, self.r, self.s,
                               50, "American", cp) for u in x
            ])
            delta = np.array([(values[i + 2] - values[i]) / (2 * h)
                              for i in range(values.size - 2)])
            gamma = np.array([(delta[i + 2] - delta[i]) / (2 * h)
                              for i in range(delta.size - 2)])
            x = x[2:len(x) - 2]

            delta_curr = binomial_model(self.S + h, self.K, self.t, 0, self.q,
                                        self.r, self.s, 50, "American", cp)
            delta_curr -= binomial_model(self.S - h, self.K, self.t, 0, self.q,
                                         self.r, self.s, 50, "American", cp)
            delta_curr /= 2 * h

            delta_curr_2 = binomial_model(self.S + (2 * h), self.K, self.t, 0,
                                          self.q, self.r, self.s, 50,
                                          "American", cp)
            delta_curr_2 -= binomial_model(self.S, self.K, self.t, 0, self.q,
                                           self.r, self.s, 50, "American", cp)
            delta_curr_2 /= 2 * h

            gamma_curr = (delta_curr_2 - delta_curr) / (2 * h)

            return (plot(x[:-1], gamma[:-1], "Gamma", "", ""), gamma_curr)