Python

Binomial Valuation of American Options with CRR

  1. # Binomial Valuation
  2. #
  3. # Valuation of American Options
  4. # with the Cox-Ross-Rubinstein Model
  5. # Primal Algorithm
  6. # Case 1: American Put Option (APO)
  7. # Case 2: Short Condor Spread (SCS)
  8. #
  9. import math
  10. import numpy as np
  11. # General Parameters and Option Values
  12. def set_parameters(otype, M):
  13. ''' Sets parameters depending on valuation case.
  14. Parameters
  15. ==========
  16. otype: int
  17. option type
  18. 1 = American put option
  19. 2 = Short Condor Spread
  20. '''
  21. if otype == 1:
  22. # Parameters -- American Put Option
  23. S0 = 36. # initial stock level
  24. T = 1.0 # time-to-maturity
  25. r = 0.06 # short rate
  26. sigma = 0.2 # volatility
  27. elif otype == 2:
  28. # Parameters -- Short Condor Spread
  29. S0 = 100. # initial stock level
  30. T = 1.0 # time-to-maturity
  31. r = 0.05 # short rate
  32. sigma = 0.5 # volatility
  33. else:
  34. raise ValueError('Option type not known.')
  35. # Numerical Parameters
  36. dt = T / M # time interval
  37. df = math.exp(-r * dt) # discount factor
  38. u = math.exp(sigma * math.sqrt(dt)) # up-movement
  39. d = 1 / u # down-movement
  40. q = (math.exp(r * dt) - d) / (u - d) # martingale probability
  41. return S0, T, r, sigma, M, dt, df, u, d, q
  42. def inner_value(S, otype):
  43. ''' Inner value functions for American put option and short condor spread
  44. option with American exercise.
  45. Parameters
  46. ==========
  47. otype: int
  48. option type
  49. 1 = American put option
  50. 2 = Short Condor Spread
  51. '''
  52. if otype == 1:
  53. return np.maximum(40. - S, 0)
  54. elif otype == 2:
  55. return np.minimum(40., np.maximum(90. - S, 0)
  56. + np.maximum(S - 110., 0))
  57. else:
  58. raise ValueError('Option type not known.')
  59. def CRR_option_valuation(otype, M=500):
  60. S0, T, r, sigma, M, dt, df, u, d, q = set_parameters(otype, M)
  61. # Array Generation for Stock Prices
  62. mu = np.arange(M + 1)
  63. mu = np.resize(mu, (M + 1, M + 1))
  64. md = np.transpose(mu)
  65. mu = u ** (mu - md)
  66. md = d ** md
  67. S = S0 * mu * md
  68. # Valuation by Backwards Induction
  69. h = inner_value(S, otype) # innver value matrix
  70. V = inner_value(S, otype) # value matrix
  71. C = np.zeros((M + 1, M + 1), dtype=np.float) # continuation values
  72. ex = np.zeros((M + 1, M + 1), dtype=np.float) # exercise matrix
  73. z = 0
  74. for i in range(M - 1, -1, -1):
  75. C[0:M - z, i] = (q * V[0:M - z, i + 1]
  76. + (1 - q) * V[1:M - z + 1, i + 1]) * df
  77. V[0:M - z, i] = np.where(h[0:M - z, i] > C[0:M - z, i],
  78. h[0:M - z, i], C[0:M - z, i])
  79. ex[0:M - z, i] = np.where(h[0:M - z, i] > C[0:M - z, i], 1, 0)
  80. z += 1
  81. return V[0, 0]
# Binomial Valuation
#
# Valuation of American Options
# with the Cox-Ross-Rubinstein Model
# Primal Algorithm
# Case 1: American Put Option (APO)
# Case 2: Short Condor Spread (SCS)
#
import math
import numpy as np

# General Parameters and Option Values
def set_parameters(otype, M):
    ''' Sets parameters depending on valuation case.
    Parameters
    ==========
    otype: int
    option type
    1 = American put option
    2 = Short Condor Spread
    '''
    if otype == 1:
        # Parameters -- American Put Option
        S0 = 36. # initial stock level
        T = 1.0 # time-to-maturity
        r = 0.06 # short rate
        sigma = 0.2 # volatility
    elif otype == 2:
        # Parameters -- Short Condor Spread
        S0 = 100. # initial stock level
        T = 1.0 # time-to-maturity
        r = 0.05 # short rate
        sigma = 0.5 # volatility
    else:
        raise ValueError('Option type not known.')
    # Numerical Parameters
    dt = T / M # time interval
    df = math.exp(-r * dt) # discount factor
    u = math.exp(sigma * math.sqrt(dt)) # up-movement
    d = 1 / u # down-movement
    q = (math.exp(r * dt) - d) / (u - d) # martingale probability
    return S0, T, r, sigma, M, dt, df, u, d, q

def inner_value(S, otype):
    ''' Inner value functions for American put option and short condor spread
    option with American exercise.
    Parameters
    ==========
    otype: int
    option type
    1 = American put option
    2 = Short Condor Spread
    '''
    if otype == 1:
        return np.maximum(40. - S, 0)
    elif otype == 2:
        return np.minimum(40., np.maximum(90. - S, 0)
                          + np.maximum(S - 110., 0))
    else:
        raise ValueError('Option type not known.')
    
def CRR_option_valuation(otype, M=500):
    S0, T, r, sigma, M, dt, df, u, d, q = set_parameters(otype, M)
    # Array Generation for Stock Prices
    mu = np.arange(M + 1)
    mu = np.resize(mu, (M + 1, M + 1))
    md = np.transpose(mu)
    mu = u ** (mu - md)
    md = d ** md
    S = S0 * mu * md
    # Valuation by Backwards Induction
    h = inner_value(S, otype) # innver value matrix
    V = inner_value(S, otype) # value matrix
    C = np.zeros((M + 1, M + 1), dtype=np.float) # continuation values
    ex = np.zeros((M + 1, M + 1), dtype=np.float) # exercise matrix
    z = 0
    for i in range(M - 1, -1, -1):
        C[0:M - z, i] = (q * V[0:M - z, i + 1]
        + (1 - q) * V[1:M - z + 1, i + 1]) * df
        V[0:M - z, i] = np.where(h[0:M - z, i] > C[0:M - z, i],
        h[0:M - z, i], C[0:M - z, i])
        ex[0:M - z, i] = np.where(h[0:M - z, i] > C[0:M - z, i], 1, 0)
        z += 1
    return V[0, 0]