理解BS期权定价

开局放图

1.完整图示

开局一张图!全篇编的尽可能通俗化,有些地方避免不了用公式解释,内容的完整流程图示绘制如下,建议全篇读完后再看流程图。

2.背景知识

期权介绍

首先简单介绍下期权背景知识,期权(Option)是一种赋予期权买方在约定日期以约定的价格买入或卖出约定数量标的资产的权利的合约,而期权卖方必须履行承诺。

按照期权买方执行期权的时限,又可以分成欧式期权和美式期权:1. 欧式期权,即期权买方只能在期权的到期日才能行权的期权;2. 美式期权,即期权买方可以在到期日之前的任一交易日或到期日行权的期权,文章后续内容都假定是欧式期权。按照期权的行权方是买方还是卖方划分:1. 认购期权买方行权,即看涨期权,当 "约定行权价格 + 权利金 < 市场价格" 时盈利,当 "约定行权价格 < 市场价格" 时,即为实值期权,通常买方会行权;2. 认沽期权卖方行权,即看跌期权,显然逻辑相反,文章后续示例假定是看涨期权。

例如:当前某股票期权 A 的价格是 100 元,约定行权的价格是 90 元,权利金是 5 元。假定一年后行权时 A 的市场价格涨到了 120 元,那么此时以 90 元价格行权显然净利润挣了 120-90-5=25 元!!!以上就是简单且非严谨的理解下挣钱利器期权(Option)的概念,示例图如下:

期权定价

文章讨论的是理论模型,即决定期权定多少价合理,定少了都像上面图那样卖出肯定亏死,因此引入文章的主要内容:BS 公式,但是模型的有效性依赖一系列的假设,例如:交易连续发生,资产价格符合几何布朗运动等等。文章比较简单,不展开讨论

原理解析

1.标准布朗运动

布朗运动是一个连续随机过程,什么是随机过程?画了一张图:

沿着竖线看,当 <math xmlns="http://www.w3.org/1998/Math/MathML"> t = t 1 t=t1 </math>t=t1时,显然 <math xmlns="http://www.w3.org/1998/Math/MathML"> X ( t 1 ) X(t_1) </math>X(t1)是一个随机变量,因为变量可能取到不同颜色曲线上的值,同理对于 <math xmlns="http://www.w3.org/1998/Math/MathML"> X ( t 2 ) X(t_2) </math>X(t2),这样沿着 <math xmlns="http://www.w3.org/1998/Math/MathML"> t t </math>t的无限多个随机变量组成随机过程,因此随机过程是一个整体概念,是多维随机变量的延伸。如果只看一种颜色的曲线,则这条曲线 <math xmlns="http://www.w3.org/1998/Math/MathML"> x i ( t ) x_i(t) </math>xi(t)对应随机过程的一次全程观测,是关于 <math xmlns="http://www.w3.org/1998/Math/MathML"> t t </math>t的函数 <math xmlns="http://www.w3.org/1998/Math/MathML"> x i ( t ) x_i(t) </math>xi(t),可理解成把组成随机过程的全部随机变量都采样一次。有没发现单个曲线好像和股票走势长得很像!想象成三条曲线分别对应连续 3 日 0-24 小时的股票走势!

那么布朗运动就是一种特殊的随机过程,又称为维纳过程,这里准确的说是零初值标准布朗运动,具有一系列的特性,比如轨迹会频繁穿越时间轴t,且任意时刻不偏离时间轴一个正负标准差 <math xmlns="http://www.w3.org/1998/Math/MathML"> √ t √t </math>√t,还是一个马尔可夫过程,即从业务角度理解,布朗运动的当前值包含对其未来做预测所需的全部信息等等,反正更适合描述股票运动,我们记成 <math xmlns="http://www.w3.org/1998/Math/MathML"> B ( t ) B(t) </math>B(t)吧

2.描述股票价格

描述股票收益率

有了标准的布朗运动 <math xmlns="http://www.w3.org/1998/Math/MathML"> B ( t ) B(t) </math>B(t),继续构建一个带漂移的布朗运动,这样更贴近股票运动的业务特性,无穷小变化量形式如下:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d X ( t ) = μ d t + σ d B ( t ) dX(t)=μdt+σdB(t) </math>dX(t)=μdt+σdB(t)

上述是一个随机微分方程,满足均值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ t μt </math>μt,方差为 <math xmlns="http://www.w3.org/1998/Math/MathML"> σ 2 t σ^2t </math>σ2t的正态分布,其中漂移项系数 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ μ </math>μ是长期平均回报率,即股票期望年收益率, <math xmlns="http://www.w3.org/1998/Math/MathML"> σ σ </math>σ是股票年收益率的标准差。这个等式怎么理解?实际上,用上面的 <math xmlns="http://www.w3.org/1998/Math/MathML"> X ( t ) X(t) </math>X(t)描述股票的收益率,可以简单看成收益率曲线在期望年收益率 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ μ </math>μ上下波动,且不偏离年收益率的标准差 <math xmlns="http://www.w3.org/1998/Math/MathML"> σ σ </math>σ,看着符合现实情况,即A股除外股票长期收益是稳定的

为什么可以用布朗运动描述收益率?1. 股票的连续复利收益率近似地服从正态分布,和布朗运动一致;2. 布朗运动是一个马尔科夫过程,符合弱式有效市场假说;3. 股票收益率在时间上存在转折尖点,因此与布朗运动处处不可微的特性一致

描述股票价格

我们设股票价格是 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t),使其与收益率公式关联,考虑一个非常小的时间间隔内 <math xmlns="http://www.w3.org/1998/Math/MathML"> d S ( t ) dS(t) </math>dS(t)为股票价格的变化量,则收益率显然是 <math xmlns="http://www.w3.org/1998/Math/MathML"> d S ( t ) / S ( t ) dS(t)/S(t) </math>dS(t)/S(t),结合上面的收益率公式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d S ( t ) / S ( t ) = μ d t + σ d B ( t ) ⟹ d S ( t ) = μ S ( t ) d t + σ S ( t ) d B ( t ) dS(t)/S(t) =μdt+σdB(t)⟹dS(t)=μS(t)dt+σS(t)dB(t) </math>dS(t)/S(t)=μdt+σdB(t)⟹dS(t)=μS(t)dt+σS(t)dB(t)

上面得出无穷小变化量形式的股票价格 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t)

总结:我们得出了股票价格的表达式 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t),用布朗运动 <math xmlns="http://www.w3.org/1998/Math/MathML"> B ( t ) B(t) </math>B(t)进行描述,其自身称为一个几何布朗运动

3.伊藤引理形式

因为布朗运动是一个随机过程,且处处不可微,古典微积分解不出来上面一堆公式,因此需要随机分析知识,伊藤积分则是随机分析的基础,如果不喜欢看推导就直接看章节最后的结论。假定我们有一个关于布朗运动 <math xmlns="http://www.w3.org/1998/Math/MathML"> B t B_t </math>Bt的函数 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( B t ) f(B_t) </math>f(Bt),按照泰勒展开得到:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> f ( B t + Δ B t ) − f ( B t ) = f ′ ( B t ) ( Δ B t ) + f ″ ( B t ) / 2 ∗ ( Δ B t ) 2 + ⋯ f(B_t+ΔB_t )-f(B_t )=f' (B_t )(ΔB_t )+f^″ (B_t )/2*(ΔB_t )^2+⋯ </math>f(Bt+ΔBt)−f(Bt)=f′(Bt)(ΔBt)+f″(Bt)/2∗(ΔBt)2+⋯

同时布朗运动有个性质,二次变分非零,因此右式第二项不是第一项的高阶无穷小,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( d B t ) 2 = d t (dB_t)2=dt </math>(dBt)2=dt,不能够省略掉,得到伊藤引理的基本形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d f ( B t ) = f ′ ( B t ) d B t + 1 / 2 f ″ ( B t ) d t df(B_t )=f' (B_t )dB_t+1/2 f^″ (B_t )dt </math>df(Bt)=f′(Bt)dBt+1/2f″(Bt)dt

上面确实和古典微积分不同。继续推导伊藤引理的一般形式,令 <math xmlns="http://www.w3.org/1998/Math/MathML"> f ( x , X ( t ) ) f(x,X(t)) </math>f(x,X(t))是 <math xmlns="http://www.w3.org/1998/Math/MathML"> X ( t ) X(t) </math>X(t)的二阶连续可导函数,且对 <math xmlns="http://www.w3.org/1998/Math/MathML"> t t </math>t一阶可导。首先不限定 <math xmlns="http://www.w3.org/1998/Math/MathML"> μ μ </math>μ和 <math xmlns="http://www.w3.org/1998/Math/MathML"> σ σ </math>σ是常数,假定是时间的函数(其实可以是任意函数),重写 <math xmlns="http://www.w3.org/1998/Math/MathML"> d X ( t ) dX(t) </math>dX(t)的表达式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d X ( t ) = R t d t + A t d B ( t ) dX(t)=R_t dt+A_t dB(t) </math>dX(t)=Rtdt+AtdB(t)

然后把 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f按照上面的伊藤引理的基本形式展开:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d f ( t , X ( t ) ) = ∂ f / ∂ t d t + d f ( X ( t ) ) = ∂ f / ∂ t d t + ∂ f / ∂ X ( t ) d X ( t ) + 1 / 2 ( ∂ 2 f ) / ( ∂ 2 X ( t ) ) ( d X ( t ) ) 2 df(t,X(t))=∂f/∂t dt+df(X(t))=∂f/∂t dt+∂f/∂X(t) dX(t)+1/2 (∂^2 f)/(∂^2 X(t) ) (dX(t))^2 </math>df(t,X(t))=∂f/∂tdt+df(X(t))=∂f/∂tdt+∂f/∂X(t) dX(t)+1/2 (∂2f)/(∂2X(t))(dX(t))2

注意上面不能用二次变分直接把 <math xmlns="http://www.w3.org/1998/Math/MathML"> ( d X ( t ) ) 2 (dX(t))^2 </math>(dX(t))2换成 <math xmlns="http://www.w3.org/1998/Math/MathML"> d t dt </math>dt,因为 <math xmlns="http://www.w3.org/1998/Math/MathML"> X ( t ) X(t) </math>X(t)不是 <math xmlns="http://www.w3.org/1998/Math/MathML"> B t B_t </math>Bt,实际上
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( d X ( t ) ) 2 = R t 2 ( d t ) 2 + A t 2 ( d B ( t ) ) 2 + 2 R t ∗ A t ∗ d t d B ( t ) (dX(t))^2=R_t^2 (dt)^2+A_t^2 (dB(t))^2+2R_t*A_t*dtdB(t) </math>(dX(t))2=Rt2(dt)2+At2(dB(t))2+2Rt∗At∗dtdB(t)

右边第1项和第3项是高阶无穷小,直接扔掉,得到
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( d X ( t ) ) 2 = A t 2 d t (dX(t))^2=A_t^2 dt </math>(dX(t))2=At2dt

再把 <math xmlns="http://www.w3.org/1998/Math/MathML"> d X ( t ) dX(t) </math>dX(t)代入到 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f的展开式,得到一般形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d f ( t , X ( t ) ) = ( ∂ f / ∂ t + ∂ f / ∂ X ( t ) R t + 1 / 2 ( ∂ 2 f ) / ( ∂ 2 X ( t ) ) A t 2 ) d t + ∂ f / ∂ X A t d B ( t ) df(t,X(t))=(∂f/∂t+∂f/∂X(t) R_t+1/2 (∂^2 f)/(∂^2 X(t) ) A_t^2 )dt+∂f/∂X A_t dB(t) </math>df(t,X(t))=(∂f/∂t+∂f/∂X(t) Rt+1/2 (∂2f)/(∂2X(t))At2)dt+∂f/∂XAtdB(t)

可以看到随机微分方程 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f和 <math xmlns="http://www.w3.org/1998/Math/MathML"> X X </math>X的随机性由同一个布朗运动确定,这点非常关键!!!

总结:上面求了一大堆就是让我们具备了展开分析 <math xmlns="http://www.w3.org/1998/Math/MathML"> d f ( t , X ( t ) ) df(t,X(t)) </math>df(t,X(t))这个随机微分方程的能力。应用随机积分还能得出上面股票价格关于时间的变化函数 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t),此处不再详细解释过程,假定已经计算出了 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t)

4.BS公式

上面内容都有了,现在假定 <math xmlns="http://www.w3.org/1998/Math/MathML"> C ( t , S ( t ) ) C(t,S(t)) </math>C(t,S(t))是欧式看涨期权的价格,是时间 <math xmlns="http://www.w3.org/1998/Math/MathML"> t t </math>t和股票价格 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t)的函数,观察发现是不是可以按照伊藤引理一般形式展开:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> d C = ( ∂ C / ∂ S μ S + ∂ C / ∂ t + 1 / 2 ( ∂ 2 C ) / ( ∂ S 2 ) σ 2 S 2 ) d t + ∂ C / ∂ S σ S d B dC=(∂C/∂S μS+∂C/∂t+1/2 (∂^2 C)/(∂S^2 ) σ^2 S^2 )dt+∂C/∂S σSdB </math>dC=(∂C/∂SμS+∂C/∂t+1/2 (∂2C)/(∂S2)σ2S2)dt+∂C/∂SσSdB

之前提到伊藤过程 <math xmlns="http://www.w3.org/1998/Math/MathML"> X X </math>X的函数 <math xmlns="http://www.w3.org/1998/Math/MathML"> f f </math>f和 <math xmlns="http://www.w3.org/1998/Math/MathML"> X X </math>X的随机性来自同一个布朗运动,结合之前 <math xmlns="http://www.w3.org/1998/Math/MathML"> d S = μ S d t + σ S d B dS=μSdt+σSdB </math>dS=μSdt+σSdB的定义,观察很小时间区间 <math xmlns="http://www.w3.org/1998/Math/MathML"> Δ t Δt </math>Δt内股价 <math xmlns="http://www.w3.org/1998/Math/MathML"> Δ S ΔS </math>ΔS和期权价格 <math xmlns="http://www.w3.org/1998/Math/MathML"> Δ C ΔC </math>ΔC的关系,两个公式都看最后一项,发现啊!!!做空1份期权,同时做多 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∂ C / ∂ S ∂C/∂S </math>∂C/∂S份股票,组合两个公式后随机因子 <math xmlns="http://www.w3.org/1998/Math/MathML"> d B dB </math>dB就没有了,即我们的投资组合结果是确定的,这种方式就是Delta 对冲

如果采用上面的股票和期权投资组合,Δt时间内对冲后的结果是:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> Δ R = − Δ C + ∂ C / ∂ S Δ S = ( − ∂ C / ∂ t − 1 / 2 ( ∂ 2 C ) / ( ∂ S 2 ) σ 2 S 2 ) Δ t , ΔR=-ΔC+∂C/∂S ΔS=(-∂C/∂t-1/2 (∂^2 C)/(∂S^2 ) σ^2 S^2 )Δt, </math>ΔR=−ΔC+∂C/∂SΔS=(−∂C/∂t−1/2 (∂2C)/(∂S2)σ2S2)Δt,

而投资组合的价值是当前做空期权价值加上做多股票价值:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> R = − C + ∂ C / ∂ S S R=-C+∂C/∂S S </math>R=−C+∂C/∂SS

结合理论:市场中不存在无风险套利机会时,投资组合在 <math xmlns="http://www.w3.org/1998/Math/MathML"> Δ t Δt </math>Δt时间内的收益率等于无风险收益率 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r,即表示成 <math xmlns="http://www.w3.org/1998/Math/MathML"> Δ R = r R Δ t ΔR=rRΔt </math>ΔR=rRΔt,进一步组合全部公式,就得到了BS微分方程:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∂ C / ∂ t + r S ∂ C / ∂ S + 1 / 2 σ 2 S 2 ( ∂ 2 C ) / ( ∂ S 2 ) = r C ∂C/∂t+rS ∂C/∂S+1/2 σ^2 S^2 (∂^2 C)/(∂S^2 )=rC </math>∂C/∂t+rS∂C/∂S+1/2σ2S2 (∂2C)/(∂S2)=rC

上面就是个普通微分方程,描述股票和期权的投资组合,随机因子被对冲掉了,因为已假定上面 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( t ) S(t) </math>S(t)的价格已经用随机积分求解完了,这里可以求解出 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C,即期权定价多少钱比较好 #_#,大概原理就是上面这些

编写代码

直接写代码收尾,还有一大堆理论的东西解释起来太麻烦,不如直接跑代码拿结果。因为由上面的 BS 公式可以得到风险中性定价理论,即可以用无风险收益率 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r对衍生品收益期望进行贴现,从而简化求解过程,得到一组快速求解公式,这里不再列出公式,最终计算出期权理论价格只需要五个变量:当前股价 <math xmlns="http://www.w3.org/1998/Math/MathML"> S ( 0 ) S(0) </math>S(0),行权价格 <math xmlns="http://www.w3.org/1998/Math/MathML"> K K </math>K,行权日到当前的年单位时间 <math xmlns="http://www.w3.org/1998/Math/MathML"> T T </math>T,无风险收益率 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r,标的股票的年收益率的标准差 <math xmlns="http://www.w3.org/1998/Math/MathML"> σ σ </math>σ

代码中的函数 _volatility 结果就是对应的σ,即计算年收益率的标准差。完整如下:

python 复制代码
from typing import (  
    Union,  
    Sequence  
)  
from datetime import datetime  
  
import numpy as np  
import pandas as pd  
from scipy.stats import norm  
  
TableData = Union[pd.DataFrame, np.ndarray, Sequence[Sequence]]  
  
  
class BSM:  
  
    def __init__(self, data: TableData, data_column: int = 0, data_cycle: int = 365):  
        self.__data = data  
        self.__data_column = data_column  
        self.__data_cycle = data_cycle  
  
    def pricing_merton(self, S: float, K: float, r: float, T0: datetime, T1: datetime, otype: str = 'call') -> float:  
        """BSM 期权定价  
  
        Args:  
            S: 股票当前价格  
            K: 期权行权价格  
            r: 股票无风险收益率  
            T0: 期权定价日期  
            T1: 期权行权日期  
            otype: 期权类型(call or put)  
  
        Returns:  
            价格  
        """  
        if otype != 'call' and otype != 'put':  
            raise ValueError('The parameter value of `otype` is illegal')  
  
        sigma = self._volatility()  
        return self._price(S, K, sigma, r, T0, T1, otype)  
  
    def _price(self, S: float, K: float, sigma: float, r: float, T0: datetime, T1: datetime, otype: str) \  
            -> float:  
  
        T = (T1 - T0).days / 365  
        d1 = (np.log(S / K) + (r + pow(sigma, 2) / 2) * T) / (sigma * np.sqrt(T))  
        d2 = d1 - sigma * np.sqrt(T)  
  
        if otype == 'call':  
            # Call option  
            value_c = S * norm.cdf(d1) - K * np.exp(-r * T) * norm.cdf(d2)  
            return value_c  
        else:  
            # Put option  
            value_p = K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)  
            return value_p  
  
    def _volatility(self) -> float:  
        rate = np.log(self.__data.iloc[:, self.__data_column] / self.__data.iloc[:, self.__data_column].shift(1))  
        rate = rate.dropna()  
        rate_volatility = np.sqrt(self.__data_cycle) * rate.std()  
  
        return rate_volatility
相关推荐
秃头佛爷2 分钟前
Python学习大纲总结及注意事项
开发语言·python·学习
深度学习lover1 小时前
<项目代码>YOLOv8 苹果腐烂识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·苹果腐烂识别
API快乐传递者2 小时前
淘宝反爬虫机制的主要手段有哪些?
爬虫·python
阡之尘埃4 小时前
Python数据分析案例61——信贷风控评分卡模型(A卡)(scorecardpy 全面解析)
人工智能·python·机器学习·数据分析·智能风控·信贷风控
丕羽7 小时前
【Pytorch】基本语法
人工智能·pytorch·python
bryant_meng8 小时前
【python】Distribution
开发语言·python·分布函数·常用分布
m0_594526309 小时前
Python批量合并多个PDF
java·python·pdf
工业互联网专业9 小时前
Python毕业设计选题:基于Hadoop的租房数据分析系统的设计与实现
vue.js·hadoop·python·flask·毕业设计·源码·课程设计
钱钱钱端9 小时前
【压力测试】如何确定系统最大并发用户数?
自动化测试·软件测试·python·职场和发展·压力测试·postman
慕卿扬9 小时前
基于python的机器学习(二)—— 使用Scikit-learn库
笔记·python·学习·机器学习·scikit-learn