日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

合并二叉树进行期权定价

發布時間:2023/12/16 编程问答 60 豆豆
生活随笔 收集整理的這篇文章主要介紹了 合并二叉树进行期权定价 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

合并二叉樹進行期權定價 – 潘登同學的Quant筆記

文章目錄

    • 合并二叉樹進行期權定價 -- 潘登同學的Quant筆記
  • 理論背景
  • 合并二叉樹
  • 疊期望定理
  • Gisanov's Theorem(戈薩諾夫定理)
  • 計算合并二叉樹的關鍵點
    • 模型參數
    • 中間結果
  • 構建合并二叉樹
    • 構建二叉樹節點
    • 構建合并二叉樹
    • 完整代碼
    • 算例

理論背景

合并二叉樹對期權的定價是建立在單期模型向多期模型拓展的基礎之上的,而多期模型與單期模型的最大區別在于: 單期模型只在最初做決策,而多期模型在多個時點連續作出投資決策; 為了將套利定價理論拓展到多期、動態的情形下,必須要滿足的條件就是動態完備;

對于單期模型來說,資產個數至少大于狀態的數量,市場才可能是完備的; 而在動態模型中,如果長存資產的數目不低于樹中各個結點引出的直接后繼節點數量的最大值,那么市場就是完備的;

合并二叉樹

大家對二叉樹都很熟悉,一個節點有兩個子節點,子節點的個數與層數的關系就是2n2^n2n(從第0層算起), 那么最終的子節點個數就會呈指數級增加,而金融里面的資產價格變動往往是用乘積因子做變化的; 如從0時刻到1時刻,資產價格從S0S_0S0?變化到uS0uS_0uS0?dS0dS_0dS0?(u表示上升,d表示下降),到2時刻資產價格從uS0uS_0uS0?變化到uuS0uuS_0uuS0?udS0udS_0udS0?, 從dS0dS_0dS0?變化到udS0udS_0udS0?ddS0ddS_0ddS0?,可以發現其中的udS0udS_0udS0?同時出現在1時刻的兩個子節點上; 在不關心路徑的前提下,可以將兩個節點合并,如下圖所示

但是有的期權不能這樣,比如:回望期權,他是路徑依賴的,取決于標的資產在期權有效期內的最低或最高價格;

疊期望定理

期權本質上是一種資產,但這個資產的payoff只有在最后一期才能知道(European options),所以要在第一期知道其期望就需要用到疊期望定理:

在t時刻對某隨機變量x~\tilde{x}x~的期望應當嚴格地寫成:
E[x~∣Ft],Ft表示在t時刻擁有的信息E[\tilde{x}|F_t]\quad , \quad F_t表示在t時刻擁有的信息 E[x~Ft?],Ft?表示在t時刻擁有的信息

疊期望定理表示為
Et[x~]=Et[Et+1[x~]]E_t[\tilde{x}] = E_t[E_{t+1}[\tilde{x}]] Et?[x~]=Et?[Et+1?[x~]]

Gisanov’s Theorem(戈薩諾夫定理)

假設一個單位長度為△t\triangle tt,在真實世界中的資產波動率為σ\sigmaσ,在風險中性的概率下,在一個單位內股價回報率為(u?1)(u-1)(u?1)的概率為q,回報為(d?1)(d-1)(d?1)的概率為(1-q),運用公式var(X)=E(X2)?[E(X)]2var(X) = E(X^2) - [E(X)]^2var(X)=E(X2)?[E(X)]2
q(u?1)2+(1?q)(d?1)2?[q(u?1)+(1?q)(d?1)]2=σ2△tq(u-1)^2 + (1-q)(d-1)^2 - [q(u-1)+(1-q)(d-1)]^2 = \sigma^2 \triangle t q(u?1)2+(1?q)(d?1)2?[q(u?1)+(1?q)(d?1)]2=σ2t
得到風險中性概率為
q=er△t?du?dq = \frac{e^{r \triangle t}-d}{u-d} q=u?dert?d?
注意上式的等號左邊是風險中性世界的方差,等號右邊卻是真實世界的方差,這兩個方差計算所用的概率都不一樣,為什么能放到一起, Girsanov’s Theorem告訴我們,在做概率測度變換的時候(如從真實世界概率轉換到風險中性概率),資產價格收益率的均值一般會發生變化,但其波動率不變。

計算合并二叉樹的關鍵點

對于European option的計算, 可以分為兩步-正向過程和反向過程,正向過程是根據資產的波動率計算未來時刻資產價格,反向過程是根據最后一期的資產價格計算最后一期的期權價格,再用疊期望定理將期權一步步折現得到期權的現值; 接下來我們就用python實現以下過程:

模型參數

  • σ\sigmaσ: 隱含波動率 用246個交易日的roll average計算得到的序列的方差, 資產價格波動率 σ\sigmaσ 被定義為,使得在△t\triangle tt 的時長上計算的回報率波動標準差等于σ△t\sigma\sqrt{\triangle t}σt?
  • r: 無風險利率 用七天回購利率的246個交易日的roll average計算得到的序列的均值
  • t: 一年的交易日數(246天)
  • underlying_asset_price: 標的資產的現值
  • k:行權價

中間結果

  • u: 資產上漲的幅度
  • d:資產下跌的幅度(假設d = 1/u)
  • q: 風險中性概率

構建合并二叉樹

構建二叉樹節點

二叉樹節點需要記錄以下數據

  • 當前的資產價格
  • 當前的期權價格
  • 當前的時刻
  • 其子節點
  • 其父節點
  • 節點的名稱(可有可無, 寫了能分辨出是哪個節點)
class TreeNode():'''### @Author : Pan Deng### @Time : 2022/10/02'''def __init__(self, key, s, left=None, right=None,time=0):self.key = keyself.asset_price = sself.options_price = Noneself.left = leftself.right = rightself.time = timeself.leftparent = Noneself.rightparent = None

構建合并二叉樹

合并二叉樹要有以下功能

  • 根據期數將所有二叉樹節點合并
  • 進行正向傳播計算資產價格
  • 進行反向傳播計算期權價格

所以二叉樹需要有如下屬性

  • 標的資產的現值
  • 上漲幅度,下跌幅度
  • 行權價
  • 風險中性概率
  • 折現率
  • 期權到期日
  • 根節點(只要知道根節點就能知道后續的資產價格)
class CombineBinaryTree():'''### @Author : Pan Deng### @Time : 2022/10/02'''def __init__(self,total_time,underlying_asset_price,is_European=True,is_call=True):self.underlying_asset_price = underlying_asset_priceself.rootnode = TreeNode('underlying_asset_price',underlying_asset_price)self.u = uself.d = dself.k = kself.q = q # 向右節點傳播的概率self.discount_rate = r_delta_t # 折現率self.total_time = total_timeself.is_European = is_European # 是否是 Eurpean optionsself.is_call = is_call # 是否是call optionsself._build([self.rootnode],total_time) # 構造合并二叉樹,方法在后面

然后就要根據資產變化的特點構建合并二叉樹,關鍵點是

  • 其中有一些父節點擁有相同的子節點,而實現的關鍵是這些擁有相同子節點的父節點往往是相鄰的(價格相鄰),構建過程使用了類似雙指針的方法分別指向父節點與子節點,依次移動兩個指針將其連接上
def _build(self, node, total_time):parent_node = nodenow = parent_node[0].time+1if now <= total_time:children_node = [TreeNode(f'{now}-u ** {now} d ** {i}',u**(now-i)*d**(i)*self.underlying_asset_price,time=now,u=now,d=i) for i in range(now+1)]i,j = 0,0while i < len(parent_node) and j < len(children_node):parent_node[i].right = children_node[j]children_node[j].leftparent = parent_node[i]j += 1parent_node[i].left = children_node[j]children_node[j].rightparent = parent_node[i]i += 1self._build(children_node,total_time)

然后就是一個工具方法,用于顯示資產價格或期權價格,現在還沒算到期權,后面會計算,計算完再調用該方法就能顯示期權價格變化,關鍵點是

  • 使用BFS從根節點進行搜索,將節點放入一個隊列,依次從隊列中取出節點,記錄其資產價格,其子節點入隊,直到隊列為空;
  • 將資產價格保存在一個矩陣中打印輸出;
  • 其中的_calrow方法是用于計算一個上三角矩陣,當元素按列放的時候,其行號的函數;
def BFS(self, item, phase='資產價格'):'''遍歷打印node的某個item'''result = np.zeros((self.total_time+1,self.total_time+1))queue = [self.rootnode]i = 0while queue:temp = queue.pop(0)i += 1if temp.left:if temp.right not in queue:queue.append(temp.right)if temp.left not in queue:queue.append(temp.left)row = self._calrow(i)col = temp.timeif item == 'asset':result[row,col] = round(temp.asset_price,3)self.all_asset_price = resultif item == 'options':result[row,col] = round(temp.options_price,3)self.all_options_price = resultprint(f'{phase}: \n',result)

計算期權價格,關鍵點是

  • 期權價值是從后往前計算的,所以要采用遞歸的方式進行;
  • 對于American options的計算需要關注最優停時,也就是在每個地方判斷一下當前行權的價值與未來行權的期望,選大的那個即可;
  • 而對于Call options來說,根據Put-Call parity,American options是不會行權的,當然可以直接用European Options代替,但是為了嚴謹與完整,還是單獨寫了,后面有個驗證的例子;
def _cal_option_value(self,node):if node.options_price:return node.options_priceelif node.time == self.total_time:if self.is_call:node.options_price = max(node.asset_price - self.k, 0)else:node.options_price = max(self.k - node.asset_price, 0)return node.options_priceelse:if self.is_European:node.options_price = 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left))else:if self.is_call:# 一般來說美式買入期權是不會提前行權的, 這里只是為了保證完整性, 最后可以驗證一下node.options_price = max(node.asset_price - self.k, 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left)))else:node.options_price = max(self.k - node.asset_price, 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left)))return node.options_pricedef cal_option_value(self):self._cal_option_value(self.rootnode)

完整代碼

class TreeNode():'''### @Author : Pan Deng### @Time : 2022/10/02'''def __init__(self, key, s, left=None, right=None,time=0):self.key = keyself.asset_price = sself.options_price = Noneself.left = leftself.right = rightself.time = timeself.leftparent = Noneself.rightparent = Noneclass CombineBinaryTree():'''### @Author : Pan Deng### @Time : 2022/10/02'''def __init__(self,total_time,underlying_asset_price,is_European=True,is_call=True):self.underlying_asset_price = underlying_asset_priceself.rootnode = TreeNode('underlying_asset_price',underlying_asset_price)self.u = uself.d = dself.k = kself.q = q # 向右節點傳播的概率self.discount_rate = r_delta_t # 折現率self.total_time = total_timeself.is_European = is_Europeanself.is_call = is_callself._build([self.rootnode],total_time)def _build(self, node, total_time):parent_node = nodenow = parent_node[0].time+1if now <= total_time:children_node = [TreeNode(f'{now}-u ** {now} d ** {i}',u**(now-i)*d**(i)*self.underlying_asset_price,time=now,u=now,d=i) for i in range(now+1)]i,j = 0,0while i < len(parent_node) and j < len(children_node):parent_node[i].right = children_node[j]children_node[j].leftparent = parent_node[i]j += 1parent_node[i].left = children_node[j]children_node[j].rightparent = parent_node[i]i += 1self._build(children_node,total_time)def BFS(self, item, phase='資產價格'):'''遍歷打印node的某個item'''result = np.zeros((self.total_time+1,self.total_time+1))queue = [self.rootnode]i = 0while queue:temp = queue.pop(0)i += 1if temp.left:if temp.right not in queue:queue.append(temp.right)if temp.left not in queue:queue.append(temp.left)row = self._calrow(i)col = temp.timeif item == 'asset':result[row,col] = round(temp.asset_price,3)self.all_asset_price = resultif item == 'options':result[row,col] = round(temp.options_price,3)self.all_options_price = resultprint(f'{phase}: \n',result)def _cal_option_value(self,node):if node.options_price:return node.options_priceelif node.time == self.total_time:if self.is_call:node.options_price = max(node.asset_price - self.k, 0)else:node.options_price = max(self.k - node.asset_price, 0)return node.options_priceelse:if self.is_European:node.options_price = 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left))else:if self.is_call:# 一般來說美式買入期權是不會提前行權的, 這里只是為了保證完整性, 最后可以驗證一下node.options_price = max(node.asset_price - self.k, 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left)))else:node.options_price = max(self.k - node.asset_price, 1/(1+self.discount_rate) * (self.q * self._cal_option_value(node.right) + (1 - self.q) * self._cal_option_value(node.left)))return node.options_pricedef cal_option_value(self):self._cal_option_value(self.rootnode)def _calrow(self,num):for i in range(1,num+1):if num <= i:breakelse:num -= ireturn num - 1

算例

# 模型參數 sigma = 0.26 # 隱含波動率 用246個交易日的roll average計算得到的序列的方差 # 資產價格波動率 σ 被定義為,使得在△t 的時長上計算的回報率波動標準差等于σ(△t)^(1/2) r = 0.03 # 無風險利率 用七天回購利率的246個交易日的roll average計算得到的序列的均值 t = 246 # 一年的交易日數 r_delta_t = r / t # 日利率underlying_asset_price_0 = 2.906 underlying_asset_price_1 = 2.5 # 2.906 u = np.exp(sigma * 1/t ** (1/2)) d = 1/uq = (np.exp(r_delta_t)-d) / (u-d) # 風險中性概率 k = 2.8 # 行權價print('European call options:') tree = CombineBinaryTree(8,underlying_asset_price_0) tree.BFS('asset','資產價格') tree.cal_option_value() tree.BFS('options','期權價格')print('American call options:') tree = CombineBinaryTree(8,underlying_asset_price_0,is_European=False) tree.BFS('asset','資產價格') tree.cal_option_value() tree.BFS('options','期權價格')print('European put options:') tree = CombineBinaryTree(8,underlying_asset_price_1,is_call=False) tree.BFS('asset','資產價格') tree.cal_option_value() tree.BFS('options','期權價格')print('American put options:') tree = CombineBinaryTree(8,underlying_asset_price_1,is_European=False,is_call=False) tree.BFS('asset','資產價格') tree.cal_option_value() tree.BFS('options','期權價格')

結果如下:

可以看出驗證結果與理論一致…

文章寫作不易,轉載請注明出處…

總結

以上是生活随笔為你收集整理的合并二叉树进行期权定价的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。