二叉树期权定价与BSM期权定价

"""
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


# BSM定价函数
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定价
    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)

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值