"""
v1.0
本程序只适用于无股息股票上欧式看涨看跌期权定价
"""
import matplotlib.pyplot as plt
import time
from math import exp, sqrt, factorial, log
from scipy.stats import norm
import multiprocessing as mp
from functools import partial
def binary_tree(n, S0, K, T, r, sigma, type):
"""
n: 二叉树步数
S0: 股票价格
K: 执行价格
T: 期权期限
r: 无风险利率
sigma: 波动率
type: call or put
"""
dt = T / n
u = exp(sigma * sqrt(dt))
d = exp(-sigma * sqrt(dt))
p = (exp(r * dt) - d) / (u - d)
price = 0
for j in range(n + 1):
price += factorial(n) / (factorial(n - j) * factorial(j)) * pow(p, j) * pow(1 - p, n - j) * max([S0 * u ** j * d ** (n - j) - K, 0])
price = price * exp(-r * T)
return price
def BSM(S0, K, T, r, sigma):
d1 = (log(S0 / K) + (r + sigma ** 2 / 2) * T) / (sigma * sqrt(T))
d2 = d1 - sigma * sqrt(T)
c = S0 * norm.cdf(d1) - K * exp(-r * T) * norm.cdf(d2)
p = c + K * exp(-r * T) - S0
return c, p
def plot(prices, bsm_price):
"""
prices: 价格序列
bsm_price: BSM定价
"""
n = len(prices)
plt.figure()
plt.plot(range(1, n + 1), prices, label="binomial tree")
plt.plot(range(1, n+1), [bsm_price for i in range(1, n+1)], label="BSM")
plt.xlabel("n_step")
plt.ylabel("price")
plt.legend()
plt.show()
if __name__ == "__main__":
params = {
"S0": 50,
"K": 52,
"T": 2,
"r": 0.05,
"sigma": 0.3
}
n = 1000
t0 = time.time()
num_cores = int(mp.cpu_count())
print("本地计算机有: " + str(num_cores) + " 核心")
pool = mp.Pool(num_cores)
par = partial(binary_tree, **params, type="call")
prices = list(pool.imap(par, range(1, n + 1)))
print("共用时%.2f秒" % (time.time() - t0))
bsm_price = BSM(**params)[0]
plot(prices, bsm_price)
"""
v2.0
本程序适用于无股息股票上的欧式美式看涨看跌期权定价
由于BSM只适用于不提前行权的期权定价,因此这里不进行BSM定价
"""
import matplotlib.pyplot as plt
import time
from math import exp, sqrt
from scipy.stats import norm
import multiprocessing as mp
from functools import partial
def binary_tree(n, S0, K, T, r, sigma, is_Euro, is_call):
"""
n: 二叉树步数
S0: 股票价格
K: 执行价格
T: 期权期限
r: 无风险利率
sigma: 波动率
is_Euro: True or False
is_call: True or False
"""
dt = T / n
u = exp(sigma * sqrt(dt))
d = exp(-sigma * sqrt(dt))
p = (exp(r * dt) - d) / (u - d)
stock_price = []
for i in range(n + 1):
lst = []
for j in range(i + 1):
element = S0 * u ** (i - j) * d ** j
lst.append(element)
stock_price.append(lst)
if is_call:
price_last = [max([0, each - K]) for each in stock_price[n]]
for i in range(n):
price = []
for j in range(n - i):
price.append(p * price_last[j] + (1 - p) * price_last[j + 1])
price_last = price
else:
price_last = [max([0, K - each]) for each in stock_price[n]]
if is_Euro:
for i in range(n):
price = []
for j in range(n - i):
price.append(p * price_last[j] + (1 - p) * price_last[j + 1])
price_last = price
else:
for i in range(n):
price = []
for j in range(n - i):
p1 = p * price_last[j] + (1 - p) * price_last[j + 1]
value = max([p1, K - stock_price[n-i][j]])
price.append(value)
price_last = price
return price[0]
def plot(prices):
"""
prices: 价格序列
"""
n = len(prices)
plt.figure()
plt.plot(range(1, n + 1), prices)
plt.xlabel("n_step")
plt.ylabel("price")
plt.show()
if __name__ == "__main__":
params = {
"S0": 50,
"K": 52,
"T": 2,
"r": 0.05,
"sigma": 0.3,
"is_Euro": True,
"is_call": False
}
n = 1000
t0 = time.time()
num_cores = int(mp.cpu_count())
print("本地计算机有: " + str(num_cores) + " 核心")
pool = mp.Pool(num_cores)
par = partial(binary_tree, **params)
prices = list(pool.imap(par, range(1, n + 1)))
print("共用时%.2f秒" % (time.time() - t0))
plot(prices)