<jupyter_start><jupyter_text>![](../images/rivacon_frontmark_combined_header.png)  Binomial Trees<jupyter_code>import math
def exp(x):
    return math.exp(x)<jupyter_output><empty_output><jupyter_text>Application of Binomial TreesBinomial trees are a popular technique for pricing options. This method relies on the assumption that stock prices follow a random walk and at each time step, it has a certain probability of moving up or down by a certain percentage. Furthermore, it requires the assumption that no arbitrage opportunities exist. The binomial tree represents the different paths a stock price can follow. In the limit, this model converges to the Black-Scholes-Merton model, which is described [here](european_plain_vanilla_option.ipynb). Example - One-Step Binomial TreeConsider a stock which currently trades at 50. We are interested in pricing a European call option with a strike of 50 and maturity in six months from now. We know that at maturity, the stock will either move up to 55 or move down to 45. Hence, if the stock price moves up, the option will have a value of 5; if the stock price moves down, the option will have the value zero. Assuming a risk neutral world, we can set up a portfolio of the stock itself and the option so that we already know the value of the portfolio at maturity. Therefore, we need to calculate the delta of shares we need to hold to make the portfolio riskless. We can calculate delta as $$\Delta=\frac{c_u-c_d}{S_0u-S_0d},$$where $c_u$ and $c_d$ is the value of the option assuming the stock moves up respectively down and $S_0u$ and $S_0d$ is the value of the stock if it moves up respectively down. Hence, delta is given as $$\Delta=\frac{5-0}{55-45}=0.5.$$Now, we can create a riskless portfolio by holding a long position in $\Delta$ shares and short one call option. If the stock price moves up to 55, the value of the portfolio is $55\cdot0.5-5=22.5$; if the stock price moves down to 45, the value of the portfolio is $45\cdot0.5-0=22.5$. Discounting the portfolio value at maturity assuming a risk-free interest rate $r$ of 0.05 gives as a present value of the portfolio of $$22.5e^{-0.05\cdot6/12}=21.94.$$In order to determine the option price today, we know that the portfolio value is the value of the long position in $\Delta$ shares and the short position in one option and we further now that this value is $21.94$. Hence, it follows that $$50\cdot0.5-c=21.94$$ or $$c = 3.06.$$The following code shows how the option value can be calculated.<jupyter_code>S0 = 50
K = 50
S0_u = 55
S0_d = 45
r= 0.05
T = 0.5

c_u = max(S0_u-K,0)
c_d = max(S0_d-K, 0)

delta = (c_u-c_d)/(S0_u-S0_d)

pf_value_u = (S0_u*delta-c_u)*exp(-r*T)
pf_value_d = (S0_d*delta-c_d)*exp(-r*T)

c = -(pf_value_u-(S0*delta))
print(c)<jupyter_output><empty_output><jupyter_text>Generalization of the One-Step Binomial TreeThe following formula allows the pricing of an option using a one-step binomial tree. The value of an option $o$ is defined as$$ o = e^{-rT}[po_u+(1-p)o_d]$$where $o_u$ describes the value of the option in case of an upward-movement of the stock and $o_d$ in case of a downward-movement of the stock with the probability of an upward-movement $p$ defined as$$p=\frac{e^{rT}-d}{u-d}$$where $u$ is the upward-moving factor and $d$ is the downward-moving factor, i.e. $u-1$ is the percentage increase in case of an upward-movement and $1-d$ is the percentage decrease in case of an downward-movement.For a detailed description how the formulas are derived please refer to Hull, *Options, futures, and other derivatives, 8th Edition,* 2012, p. 265.We now can take the example from before using these formulas.<jupyter_code>S0 = 50
K = 50
r = 0.05
T = 0.5
u = 1.1
d = 0.9
S0_u = S0*u
S0_d = S0*d

#Call
o_u = max(S0_u-K,0)
o_d = max(S0_d-K, 0)

#Put - uncomment the following lines to calculate the value of a put option instead of a call option
#o_u = max(K-S0_u,0)
#o_d = max(K-S0_d, 0)

p = (exp(r*T)-d)/(u-d)

o = exp(-r*T)*(p*o_u+(1-p)*o_d)
print(o)<jupyter_output><empty_output><jupyter_text>Two-Step Binomial TreeThe analysis of the option value using the one-step binomial tree can be extended to a two-step binomial tree. Hence, let A denote the node at start $S_0$. In the first step, the stock price either moves up by $u$ or down by $d$ to $S_0u$ or $S_0d$ where $S_0u$ is node B and $S_0d$ is node C of the binomial tree. In the second step, the stock price again goes up by $u$ or down by $d$ from each node. Hence from node B, the stock price goes up to $S_0uu$ (node D), or down to $S_0ud$ (node E). From node C, the stock price either goes up to $S_0du$ which equals $S_0ud$ (node E) or down to $S_0dd$ node (F). Hence, we derive the following nodes from the two-step binomial model.$A = S_0$,$B = S_0u$,$C = S_0d$,$D = S_0uu$,$E = S_0ud/S_0du$,$F = S_0dd$.In order to determine the option price today, we need to go backwards starting at the nodes at maturity to determine the option prices at the previous nodes. Therefore, we need the stock prices at each node A to F which are given as $A = 50.00$,$B = 55.00$,$C = 45.00$,$D = 60.50$,$E = 49.50$,$F = 40.50$.Hence, at nodes D to F the option price is either $max(S_T-K, 0)$ in case of call option or $max(K-S_T, 0)$ in case of a put option. This leads to the following option values at the terminal nodes D to F in case of a call option:$o_D = 10.50$,$o_E = 0.00$,$o_F = 0.00$.Having calculated the payoffs at maturity, we can determine the option values at nodes B and C. The values are calculated using the formula given in section 1.3 as $$o = e^{-rT}[po_u+(1-p)o_d].$$The probability of an upward-movement $p$ is defined as shown in section 1.2 as $$p=\frac{e^{rT}-d}{u-d}$$ which is approximately 0.63.Using this probability of an upward movement, the option value at node B is $o_B=e^{-0.05\cdot{0.5}}[0.63\cdot{10.50}+(1-0.63)\cdot{0}]=6.42$ and the option value at node C is $o_C=e^{-0.05\cdot{0.5}}[0.63\cdot{0}+(1-0.63)\cdot{0}]=0$.$o_B = 6.42$,$o_C = 0.00$.The same can be done for the last node A which is $o_A=e^{-0.05\cdot{0.5}}[0.63\cdot{6.42}+(1-0.63)\cdot{0}]=3.92$.Hence, the option value today at node A is 3.92.The procedure for deriving the option value can be reproduced using the following code cell.<jupyter_code>S0 = 50
K = 50
r = 0.05
T = 0.5
u = 1.1
d = 0.9

S0_u = S0*u
S0_d = S0*d

S0_uu = S0*u**2
S0_ud = S0*u*d #Equals S0_du == S0*d*u
S0_dd = S0*d**2

p = (exp(r*T)-d)/(u-d)


o_F = max(S0_dd-K, 0) #In the case of a put option this needs to be max(K-S0_dd, 0)
o_E = max(S0_ud-K, 0)
o_D = max(S0_uu-K, 0)

o_C = exp(-r*T)*(o_E*p+o_F*(1-p))
o_B = exp(-r*T)*(o_D*p+o_E*(1-p))

o_A = exp(-r*T)*(o_B*p+o_C*(1-p))

print('Value of the call option = ',o_A)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11536748329621381, 'fraction_numerical': 0.04424647364513734, 'mean_word_length': 4.2095901005413765, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '332867', 'license': 'MIT', 'n_tokens_mistral': 2563, 'n_tokens_neox': 2362, 'n_words': 996, 'path': 'instruments/binomial_trees.ipynb', 'repo_name': 'frontmark/jupyter-notebooks', 'size': '6735'}