Пример #1
0
def Compound_Option_Pricing_Closed_Form(S0, X1, X2, r, T1, T2, sigma):
    # Use fslove and Black Scholes formula to sovle I
    f1 = lambda I: bsformula(1, I, X2, r, T2 - T1, sigma)[0] - X1[0]
    f2 = lambda I: bsformula(-1, I, X2, r, T2 - T1, sigma)[0] - X1[1]
    I = [fsolve(f1, S0), fsolve(f2, S0)]; I = np.array(I)

    y1 = (np.log((S0) / I) + (r + sigma ** 2 / 2) * T1) / (sigma * np.sqrt(T1))
    y2 = y1 - sigma * np.sqrt(T1)
    z1 = (np.log((S0) / X2) + (r + sigma ** 2 / 2) * T2) / (sigma * np.sqrt(T2))
    z2 = z1 - sigma * np.sqrt(T2)
    rho = np.sqrt(T1 / T2)

    # Compound option pricing
    low = np.array([-np.inf, -np.inf]); M = mvn.mvndst  # mvn.mvndst(low,upp,[0,0],rho)[1]  if INFIN(I) = 0, integration range is (-infinity, UPPER(I)
    CC = S0 * M(low, np.array([z1, y1[0]]), [0, 0], rho)[1] - \
         X2 * np.exp(-r * T2) * M(low, np.array([z2, y2[0]]), [0, 0], rho)[1] - \
         X1[0] * np.exp(-r * T1) * norm.cdf(y2[0])
    PC = X2 * np.exp(-r * T2) * M(low, np.array([z2, -y2[0]]), [0, 0], -rho)[1] - \
         S0 * M(low, np.array([z1, -y1[0]]), [0, 0], -rho)[1] + \
         X1[0] * np.exp(-r * T1) * norm.cdf(-y2[0])

    CP = X2 * np.exp(-r * T2) * M(low, np.array([-z2, -y2[1]]), [0, 0], rho)[1] - \
         S0 * M(low, np.array([-z1, -y1[1]]), [0, 0], rho)[1] - \
         X1[1] * np.exp(-r * T1) * norm.cdf(-y2[1])
    PP = S0 * M(low, np.array([-z1, y1[1]]), [0, 0], -rho)[1] - \
         X2 * np.exp(-r * T2) * M(low, np.array([-z2, y2[1]]), [0, 0], -rho)[1] + \
         X1[1] * np.exp(-r * T1) * norm.cdf(y2[1])
    return (CC, PC, CP, PP)
def newton(callput, S0, K, r, T, q, price, sigma, tolerance, it=100):
    """
    :param callput: Indicates if the option is a Call or Put option
    :param S0: Stock price
    :param K: Strike price
    :param r: Risk-free rate
    :param T: Time to expiration
    :param q: Dividend rate
    :param price: Price of option
    :param sigma: Initial Volatility
    :param tolerance: The precision of the solution
    :param it: Maximum number of iterations
    :return: Implied volatility
    """
    i = 0
    vega_init = 0
    while i < it:
        bsret = bsformula(callput, S0, K, r, T, sigma, q)
        optionValue = bsret[0]
        vega = bsret[2]

        if (vega == 0):
            return sigma
        vega_init = vega
        sigma_est = float(sigma) - (float(optionValue) -
                                    float(price)) / float(vega)
        if (abs(sigma_est - sigma) < tolerance):
            return sigma_est

        sigma = sigma_est
        i += 1
    return float('NaN')
def bsimpvol(callput,
             S0,
             K,
             r,
             T,
             price,
             q=0.,
             priceTolerance=0.01,
             method='bisect',
             reportCalls=False):
    '''
    :param callput: Callput is 1 for a call and -1 for a put
    :param S0: The stock price at time zero
    :param K: The strike price
    :param r: Risk-free interest rate
    :param T: The maturity time
    :param price: The price of the option
    :param q: A continuous return rate on the underlying
    :param priceTolerance:
    :param method: The method used to calculate sigma
    :param reportCalls: The record of call bsformula
    :return: sigma, numbers of calling bsformula
    '''

    y = lambda sigma: bsformula(callput, S0, K, r, T, sigma)[0]
    dy = lambda sigma: bsformula(callput, S0, K, r, T, sigma)[2]
    if method == 'bisect':
        if bisect(price, y, bounds=[0.01, 1])[0] == None:
            return None
        item = bisect(price, y, bounds=[0.01, 1])[0]
    elif method == 'newton':
        if newton(price, y, dy, start=1, bounds=[0.01, 1])[0] == None:
            return None
        item = newton(price, y, dy, start=1, bounds=[0.01, 1])[0]

    if item != None:
        sigma = item[-1]
    else:
        sigma = item
        return None
    if reportCalls == True:
        return (sigma, len(item))
    else:
        return sigma
Пример #4
0
def binomialAmerican(S0, Ks, r, T, sigma, q, callputs, M):
    """ Computed values """

    dt = T / M  # Single time step, in years
    df = np.exp(-(r - q) * dt)  # Discount factor

    u = np.exp(sigma * np.sqrt(dt))
    d = 1. / u
    p = (np.exp((r - q) * dt) - d) / (u - d)
    q = 1 - p

    # Initialize a 2D tree at T=0
    STs = [np.array([S0])]

    # Simulate the possible stock prices path
    for i in range(M):
        prev_branches = STs[-1]
        st = np.concatenate((prev_branches * u, [prev_branches[-1] * d]))
        STs.append(st)  # Add nodes at each time step

    payoffs = np.maximum(0, (STs[M] - Ks) if callputs == 1 else (Ks - STs[M]))

    for j in reversed(range(M)):
        # The payoffs from NOT exercising the option
        payoffs = (payoffs[:-1] * p + payoffs[1:] * q) * df
        early_ex_payoff = (STs[j] - Ks) if callputs == 1 else (Ks - STs[j])
        payoffs = np.maximum(payoffs, early_ex_payoff)

    price = bsformula(callput=callputs,
                      S0=S0,
                      K=Ks,
                      r=r,
                      T=T,
                      sigma=sigma,
                      q=q)[0]
    error = price - payoffs[0]

    return payoffs[0], error
 def targetfunction(x):
     return bsformula(callput, S0, K, r, T, x, q)[0]
S0, r, T1, T2 = [50.0, 0.025, 1.0, 2.0]; X2 = S0
# Different client's view
views = {'Mrs Smith': ([r + 0.03, 0.15], [r + 0.005, 0.3]), 'Mr Johnson': ([r - 0.03, 0.2], [r - 0.01, 0.18]),
         'Ms Williams': ([r - 0.03, 0.18], [r + 0.03, 0.12]), 'Mr Jones': ([r + 0.02, 0.35], [r + 0.02, 0.1]),
         'Miss Brown': ([r + 0.03, 0.15], [r - 0.05, 0.15])}
names = ('Mrs Smith', 'Mr Johnson', 'Ms Williams', 'Mr Jones', 'Miss Brown')

# in different views
'Question c1-Antithetic Sampling methods. ComOpt4 and ComOpt5 is the prices of compound options'
ComOpt4 = [0] * len(names); option = ('Call', 'Put')
ComOpt5 = [0] * len(names)
j = 0
for v in names:
    mu1, sigma1, mu2, sigma2 = views[v][0][0], views[v][0][1], views[v][1][0], views[v][1][1]
    # At the money
    X1 = [bsformula(1, S0, X2, r, T2 - T1, sigma2)[0], bsformula(-1, S0, X2, r, T2 - T1, sigma2)[0]]

    print()
    print("Antithetic Sampling")
    # For different underlying options
    ComOpt4[j] = [0] * 2; i = 0
    for underlying in option:
        # Antithetic Sampling
        start_c1 = time.clock()
        ComOpt4[j][i] = [0] * 4
        ComOpt4[j][i] = Comp_Opt_Var_Vol(S0, X1, X2, r, T1, T2, mu1, mu2, sigma1,
                        sigma2).antiSampling(underlying, int(10000), 777)
        # Get enough size of number to satisfy The Central Limit Theorem
        N = int(floor(std(ComOpt4[j][i][3]) ** 2.0 * 1.96 ** 2.0 * 1002001 /
                      (mean(ComOpt4[j][i][3]) ** 2.0)))
        print("Using Antithetic Sampling, simulaiton number is", N)
Пример #7
0
        def vega(sigma, callput, S0, K, r, T):

            return bsformula(callput, S0, K, r, T, sigma, q=0.)[2]
Пример #8
0
        def bsmvsact(sigma, callput, S0, K, r, T, price):

            return bsformula(callput, S0, K, r, T, sigma, q=0.)[0] - price
Пример #9
0
 def f_prime(x):
     return bsformula(callput, S0, K, r, T, x, q)[2]
Пример #10
0
 def f(x):
     return bsformula(callput, S0, K, r, T, x, q)[0] - price
Пример #11
0
    r=np.interp(T,tenors,rateCurve)

    m=range(100,2010,100); n=range(1,101,1) # create dynamic M and N
    print('Varied N is %s'%n,'Varied M is %s'%m)
    'Vary N'
    error_n=np.zeros((len(n),3))
    checkpoints2 = [10,m[-1]]
    num1_1=0
    for k in n:
        samples2 = rand(k, m[-1])
        t2 = array([T / k] * k)  # Monthly
        num2_1 = 0
        for u in ['standard', 'euler', 'milstein']: # calculate error in different integrator methods
            test= MCOptionPrices(S0, K, T, rateCurve, sigma, t2, checkpoints2, samples2, u)
            TV = test['TV']
            error_n[num1_1,num2_1] = abs(TV[0] - bsformula(1, S0, K, r, T / 12., sigma)[0])
            num2_1+=1
        num1_1+=1

    'Vary M'
    error_m = np.zeros((len(m), 3))
    t2 = array([T / n[-1]] * n[-1])  # Monthly
    num1_2=0
    for l in m:
        samples2 = rand(n[-1], l)
        checkpoints2 = [10,l]
        num2_2 = 0
        for u in ['standard', 'euler', 'milstein']: # calculate error in different integrator methods
            test = MCOptionPrices(S0, K, T, rateCurve, sigma, t2, checkpoints2, samples2, u)
            TV = test['TV']
            error_m[num1_2, num2_2] = abs(TV[0] - bsformula(1, S0, K, r, T / 12., sigma)[0])
Пример #12
0
def fdAmerican(callput, S0, K, r, T, sigma, q, M, N, S_max, tol):
    
    #dS = S_max / float(M)
    dt = T / float(N)
    i_values = np.arange(M+1)
    j_values = np.arange(N+1)
    boundary_conds = np.linspace(0, S_max, M+1)
    
    if callput == 1:
        payoffs = np.maximum(
            boundary_conds[1:M]-K, 0)

        past_values = payoffs
    
        lower_boundary_values = np.maximum(S_max - K, 0) * \
                           np.exp(-r * dt * (N-j_values))
        upper_boundary_values = 0* j_values     
        
    elif callput == -1:
        payoffs = np.maximum(
            K-boundary_conds[1:M], 0)
        
        past_values = payoffs
        
        upper_boundary_values = K * \
                           np.exp(-r * dt * (N-j_values))
        lower_boundary_values = 0* j_values
    
    alpha = 0.25*dt*((sigma**2)*(i_values**2) - r* i_values)
    beta = -dt*0.5*((sigma**2)*(i_values**2) +r)
    gamma = 0.25*dt*((sigma**2)*(i_values**2) +r*i_values)
    M1 = -np.diag(alpha[2:M], -1) + \
                  np.diag(1-beta[1:M]) - \
                  np.diag(gamma[1:M-1], 1)
    M2 = np.diag(alpha[2:M], -1) + \
                  np.diag(1+beta[1:M]) + \
                  np.diag(gamma[1:M-1], 1)
    
    P, L, U = linalg.lu(M1)
    aux = np.zeros(M-1)
    new_values = np.zeros(M-1)

    for j in reversed(range(N)):
        aux[0] = alpha[1]*(upper_boundary_values[j] + upper_boundary_values[j+1])
        aux[M-2]= gamma[M-1]*(lower_boundary_values[j]+ lower_boundary_values[j+1])
        
        rhs = np.dot(M2, past_values) + aux
        old_values = np.copy(past_values)
        error = sys.float_info.max

        while tol < error:
            new_values[0] = \
                max(payoffs[0],
                    old_values[0] +
                    1.0/(1-beta[1]) *
                    (rhs[0] -
                     (1-beta[1])*old_values[0] +
                     (gamma[1]*old_values[1])))

            for k in range(M-2)[1:]:
                new_values[k] = \
                    max(payoffs[k],
                        old_values[k] + 
                        1.0/(1-beta[k+1]) *
                        (rhs[k] +
                         alpha[k+1]*new_values[k-1] -
                         (1-beta[k+1])*old_values[k] +
                         gamma[k+1]*old_values[k+1]))

            new_values[-1] = \
                max(payoffs[-1],
                    old_values[-1] +
                    1.0/(1-beta[-2]) *
                    (rhs[-1] +
                     alpha[-2]*new_values[-2] -
                     (1-beta[-2])*old_values[-1]))

            error = np.linalg.norm(new_values - old_values)
            old_values = np.copy(new_values)

        past_values = np.copy(new_values)

    values = np.concatenate(([upper_boundary_values[0]],
                                  new_values,
                                  [0]))
        
    price = bsformula(callput = callput, S0 = S0, K = K, r = r, T = T, sigma = sigma, q = q)[0]
    diff = price - np.interp(S0, boundary_conds, values)
    return np.interp(S0, boundary_conds, values), diff
Пример #13
0
 def optVega(x):
     return bsformula(callput, S0, K, r, T, x, q)[2]
Пример #14
0
 def optionValue(x):
     return bsformula(callput, S0, K, r, T, x, q)[0]