Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save gnm3000/2bbbe4ef63a4f7fda7ab7b15777da0ac to your computer and use it in GitHub Desktop.
Save gnm3000/2bbbe4ef63a4f7fda7ab7b15777da0ac to your computer and use it in GitHub Desktop.

Revisions

  1. gnm3000 revised this gist Jul 20, 2021. 1 changed file with 65 additions and 28 deletions.
    93 changes: 65 additions & 28 deletions Cox-Ross-Rubinstein-binomial-option-pricing.py
    Original file line number Diff line number Diff line change
    @@ -1,26 +1,28 @@
    from math import sqrt, exp
    import pydotplus as pydot
    import numpy as np
    from numpy import exp,sqrt

    class Call(object):
    def __init__(self, S0, K, rate, sigma, n_periods, tyears):
    self.S0 = S0
    self.K = K
    self.S0 = S0 # Today's stock price
    self.K = K # Strike Price
    self.rate = rate
    self.sigma = sigma
    self.tyears = tyears
    self.n_periods = n_periods
    self.up_factor = exp(self.sigma * sqrt(self.tyears / self.n_periods))
    self.down_factor = 1 / self.up_factor
    self.tree = self.option_tree()
    self.option_price = self.tree["option_tree"][0][0]

    def option_tree(self):
    num = (np.exp(self.rate * self.tyears / self.n_periods) - self.down_factor)
    den = (self.up_factor - self.down_factor)
    p = num / den

    p = (np.exp(self.rate * self.tyears / self.n_periods) - self.down_factor) / (self.up_factor - self.down_factor)

    # Option Payoff
    contingent_payoff = lambda st, k: max(st - k, 0)
    contingent_payoff = np.vectorize(contingent_payoff)

    # Creating the branches at different times of the tree.
    # Each branch is the possible martingale price

    # Creating the branches at different times of the tree. Each branch is the possible martingale price
    # of the stock at time t
    stock_price_tree = []
    for i in range(1,self.n_periods+1):
    @@ -29,36 +31,71 @@ def option_tree(self):
    for j in range(i+1):
    up_factor_repeat = i-j
    down_factor_repeat = j
    values = np.append(np.repeat(self.up_factor, up_factor_repeat),
    np.repeat(self.down_factor, down_factor_repeat))

    values = np.append(np.repeat(self.up_factor, up_factor_repeat),
    np.repeat(self.down_factor, down_factor_repeat))
    stock_price = values.prod() * self.S0
    period_prices.append(stock_price)
    stock_price_tree.append(period_prices)

    # Getting the payoff of the call at the end of the tree
    payoffs = contingent_payoff(stock_price_tree[self.n_periods-1], self.K).tolist()

    option_prices = [payoffs]
    # Contingent option price at period n-1
    branch_n = payoffs # brach at n-1

    for t in range(self.n_periods):
    branch_nm1 = []
    for i in range(len(branch_n)-1):
    #cu: Contingent price at time n if price rises
    #cd: Contingent price at time n if price decreases
    cu, cd = np.array(branch_n)[[i, i+1]]
    price = np.exp(-self.rate * self.tyears / self.n_periods)*(p*cu + (1-p)*cd)
    branch_nm1.append(price)
    option_prices.append(branch_nm1)
    branch_n = branch_nm1
    option_prices = option_prices[::-1]
    for i in range(len(branch_n)-1):
    #cu: Contingent price at time n if price rises
    #cd: Contingent price at time n if price decreases
    cu, cd = np.array(branch_n)[[i, i+1]]
    price = np.exp(-self.rate * self.tyears / self.n_periods)*(p*cu + (1-p)*cd)
    branch_nm1.append(price)
    option_prices.append(branch_nm1)
    branch_n = branch_nm1

    option_prices = option_prices[::-1]
    stock_price_tree.insert(0, [self.S0])

    return {"stock_tree": stock_price_tree,
    "option_tree": option_prices}

    def graph_tree(self, file_name = ""):
    option_prices = self.tree["option_tree"]
    stock_price_tree = self.tree["stock_tree"]

    graph = pydot.Dot(graph_type='digraph', rankdir='LR')

    branch = 0
    counter = 1
    for i, prices in enumerate(option_prices[:-1]):
    next_prices = option_prices[i+1]
    for np, c_price in enumerate(prices):
    c_price = str(round(c_price,2))

    nprice1 = str(round(next_prices[np], 2))
    nprice2 = str(round(next_prices[np+1], 2))

    increment = len(prices)-1
    from_branch, to_branch1, to_branch2 = branch, counter + increment, counter + increment + 1
    #print(from_branch,"->",to_branch1, to_branch2)

    up_price = round(stock_price_tree[i][np] * self.up_factor, 2)
    down_price = round(stock_price_tree[i][np] * self.down_factor, 2)
    edge = pydot.Edge(from_branch, to_branch1, label = str(up_price)); graph.add_edge(edge)
    edge = pydot.Edge(from_branch, to_branch2, label = str(down_price)); graph.add_edge(edge)

    node = pydot.Node(to_branch1, label = str(nprice1)); graph.add_node(node)
    node = pydot.Node(to_branch2, label = str(nprice2)); graph.add_node(node)

    counter += 1
    branch += 1

    c0 = round(self.option_price, 2)
    node = pydot.Node("0", label = str(c0)); graph.add_node(node)
    graph.write_png(file_name)
    a=Call(S0=100,K=90,rate=0.001,sigma=0.001,n_periods=1,tyears=0.01)
    print(a.option_tree())
    print(a.option_tree())
    a.graph_tree(file_name="filename.png")
  2. gnm3000 created this gist Jul 20, 2021.
    64 changes: 64 additions & 0 deletions Cox-Ross-Rubinstein-binomial-option-pricing.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,64 @@
    import numpy as np
    from numpy import exp,sqrt
    class Call(object):
    def __init__(self, S0, K, rate, sigma, n_periods, tyears):
    self.S0 = S0
    self.K = K
    self.rate = rate
    self.sigma = sigma
    self.tyears = tyears
    self.n_periods = n_periods
    self.up_factor = exp(self.sigma * sqrt(self.tyears / self.n_periods))
    self.down_factor = 1 / self.up_factor
    def option_tree(self):
    num = (np.exp(self.rate * self.tyears / self.n_periods) - self.down_factor)
    den = (self.up_factor - self.down_factor)
    p = num / den

    # Option Payoff
    contingent_payoff = lambda st, k: max(st - k, 0)
    contingent_payoff = np.vectorize(contingent_payoff)

    # Creating the branches at different times of the tree.
    # Each branch is the possible martingale price
    # of the stock at time t
    stock_price_tree = []
    for i in range(1,self.n_periods+1):
    # Number of prices per period
    period_prices = []
    for j in range(i+1):
    up_factor_repeat = i-j
    down_factor_repeat = j

    values = np.append(np.repeat(self.up_factor, up_factor_repeat),
    np.repeat(self.down_factor, down_factor_repeat))
    stock_price = values.prod() * self.S0
    period_prices.append(stock_price)
    stock_price_tree.append(period_prices)

    # Getting the payoff of the call at the end of the tree
    payoffs = contingent_payoff(stock_price_tree[self.n_periods-1], self.K).tolist()

    option_prices = [payoffs]
    # Contingent option price at period n-1
    branch_n = payoffs # brach at n-1

    for t in range(self.n_periods):
    branch_nm1 = []
    for i in range(len(branch_n)-1):
    #cu: Contingent price at time n if price rises
    #cd: Contingent price at time n if price decreases
    cu, cd = np.array(branch_n)[[i, i+1]]
    price = np.exp(-self.rate * self.tyears / self.n_periods)*(p*cu + (1-p)*cd)
    branch_nm1.append(price)
    option_prices.append(branch_nm1)
    branch_n = branch_nm1

    option_prices = option_prices[::-1]
    stock_price_tree.insert(0, [self.S0])

    return {"stock_tree": stock_price_tree,
    "option_tree": option_prices}

    a=Call(S0=100,K=90,rate=0.001,sigma=0.001,n_periods=1,tyears=0.01)
    print(a.option_tree())