FpML to QuantLib 外滙歐式Barrier選擇權估值 fx-ex12-fx-barrier-option.xml
FpML to QuantLib 外滙歐式Barrier選擇權估值
Non-Copylefted 2019 Alvin Cho. Provided ‘AS IS’. 10 May 2019.
Any quantitative method used in this file may not 100% correct for some reasons. Please use them after you fully understand them.
版權沒有, 歡迎使用, 沒有任何保證. 裡面使用的估值方法只為說明方便, 可能因為任何理由不正確或是不適用你的情況, 請完全理解再使用.
FpML 解析
from lxml import etree
利用 etree.parse 將 xml 檔案載入並 parse. 這個 FpML 文檔是 FpML 5.11 Second Working Draft Comfirmation View 裡的 fx-ex12-fx-barrier-option.xml. 將 FpML.org 下載的最新版規格壓後就可以找到. 此 FpML 文檔的詳細說明請參考 這篇文章
fp=etree.parse('FpML/confirmation/products/fx-derivatives/fx-ex12-fx-barrier-option.xml')
Confirmation View 的 namespace 一律是這個, 在任何 xpath 搜尋都需要指定 namespace.
在 FpML 裡面 namespace 用得不是很複雜, 同一個 view 裡的都用一樣
ns={"ns":"http://www.fpml.org/FpML-5/confirmation"}
asset=fp.xpath('//ns:trade/*',namespaces=ns)[1].tag
找到 tag 為 trade 的 node, 裡面有交易的細節. 第二個子節點就是這筆交易的產品. 這個文檔是做 fxOption
asset
'{http://www.fpml.org/FpML-5/confirmation}fxOption'
exercise=fp.xpath('//ns:fxOption/ns:americanExercise | //ns:fxOption/ns:europeanExercise',namespaces=ns)[0].tag
判斷這個外滙選擇權是美式還是歐式. 此產品是歐式, 也就是只在到期日能行權.
exercise
'{http://www.fpml.org/FpML-5/confirmation}europeanExercise'
expiryDate=fp.xpath('//ns:expiryDate/text()',namespaces=ns)[0]
其他要素一一提出
expiryDate
'2002-02-06'
putCurrency=fp.xpath('//ns:putCurrencyAmount/ns:currency/text()',namespaces=ns)[0]
putCurrency
'USD'
putCurrencyAmount=fp.xpath('//ns:putCurrencyAmount/ns:amount/text()',namespaces=ns)[0]
putCurrencyAmount
'4500000'
callCurrency=fp.xpath('//ns:callCurrencyAmount/ns:currency/text()',namespaces=ns)[0]
callCurrency
'EUR'
callCurrencyAmount=fp.xpath('//ns:callCurrencyAmount/ns:amount/text()',namespaces=ns)[0]
putCurrencyAmount
'4500000'
strike=fp.xpath('//ns:strike/ns:rate/text()',namespaces=ns)[0]
strike
'0.9'
strikeQuoteBasis=fp.xpath('//ns:strike/ns:strikeQuoteBasis/text()',namespaces=ns)[0]
strikeQuoteBasis
'PutCurrencyPerCallCurrency'
檢查是不是複雜選擇權, 看看有沒有 features 節點.
features=fp.xpath('//ns:features',namespaces=ns)
if len(features)>0: print('complex')
else:print('vanilla')
complex
果然是個複雜選擇權, 檢查各種複雜要素. 我們知道這裡面只有 barrier 這一項, 就只檢查 barrier 了.
barriers=fp.xpath('//ns:barrier',namespaces=ns)
len(barriers)
1
只有一個 barrier 定義
barrierType=fp.xpath('//ns:barrierType/text()',namespaces=ns)[0]
barrierType
'Knockin'
是屬於 Knock-In 形式
spotRate=fp.xpath('//ns:spotRate/text()',namespaces=ns)[0]
spotRate
'0.8935'
triggerRate=fp.xpath('//ns:triggerRate/text()',namespaces=ns)[0]
triggerRate
'0.8975'
direction=fp.xpath('//ns:barrier/ns:direction/text()',namespaces=ns)[0]
direction
'Up'
spotRate < triggerRate, 表示 spotRate 上漲才會觸碰界限, 所以這是 Up and In 形式.
rateSource=fp.xpath('//ns:barrier//ns:rateSource/text()',namespaces=ns)[0]
rateSource
'Reuters'
rateSourcePage=fp.xpath('//ns:barrier//ns:rateSourcePage/text()',namespaces=ns)[0]
rateSourcePage
'EUR='
價格參考是路透社的 EUR=. 可能大多數讀者都沒有辦法取得路透數據, 在此就不多做說明. 未來制作實際的計算器再來介紹如何取得實際市場數據.
observationStartDate=fp.xpath('//ns:barrier//ns:observationStartDate/text()',namespaces=ns)[0]
observationStartDate
'2001-08-16'
observationEndDate=fp.xpath('//ns:barrier//ns:observationEndDate/text()',namespaces=ns)[0]
observationEndDate
'2002-02-06'
觀察期為 2001-08-16 到 2002-02-06.
到這裡我們結束了 lxml 的工作, 要進入到 QuantLib 的世界了
QuantLib 估值
from QuantLib import *
e=expiryDate.split('-')
e
['2002', '02', '06']
使用 QuantLib 的日期, 不但是估值過程需要, 對一些節假日調整和工作日計算也很有用.
expiry=Date(int(e[2]),int(e[1]),int(e[0]))
expiry
Date(6,2,2002)
日曆在 FpML 和 QuantLib 都處理得很仔細,這是在美國紐約的交易, 使用 QuantLib 內建的美國行事曆.
calendar=UnitedStates()
原本應該用今天的日期, 但這產品早就到期閮, 把估值日定為觀察期的開始日.
v=observationStartDate.split('-')
valuationDate=Date(int(v[2]),int(v[1]),int(v[0]))
valuationDate
Date(16,8,2001)
到美國 FED 提供的數據庫找滙率歷史價格
fredEXCode={'USDEUR':'DEXUSEU', 'CNYUSD':'DEXCNUS', 'JPYUSD':'DEXJPUS', 'USDGBP':'DEXUSUK', 'AUDUSD':'DEXUSAL'}
currencyPair=putCurrency+callCurrency
fred=fredEXCode[currencyPair]
取 253 個資料點, 可以做出 252 個報酬率數據, 用這些數據來計算歷史波動率 volatility. 注意: 這個歷史波動率所計算出來的價格跟市場價會有差距.
volStartDate=calendar.advance(valuationDate,Period(-253,Days))
volStartDate
Date(14,8,2000)
準備好日期之後, 我們要調用 FED 提供的匯率歷史數據. 利用 Pandas-datareader
import pandas_datareader.data as pddr
priceData=pddr.DataReader(fred,'fred',str(volStartDate.dayOfMonth())+'/'+str(volStartDate.month())+'/'+str(volStartDate.year()),str(valuationDate.dayOfMonth())+'/'+str(valuationDate.month())+'/'+str(valuationDate.year()))
priceData
DEXUSEU | |
---|---|
DATE | |
2000-08-14 | 0.9037 |
2000-08-15 | 0.9135 |
2000-08-16 | 0.9143 |
2000-08-17 | 0.9152 |
2000-08-18 | 0.9068 |
2000-08-21 | 0.9027 |
2000-08-22 | 0.8965 |
2000-08-23 | 0.8967 |
2000-08-24 | 0.9028 |
2000-08-25 | 0.9024 |
2000-08-28 | 0.9002 |
2000-08-29 | 0.8966 |
2000-08-30 | 0.8924 |
2000-08-31 | 0.8878 |
2000-09-01 | 0.8993 |
2000-09-04 | NaN |
2000-09-05 | 0.8876 |
2000-09-06 | 0.8702 |
2000-09-07 | 0.8740 |
2000-09-08 | 0.8664 |
2000-09-11 | 0.8624 |
2000-09-12 | 0.8596 |
2000-09-13 | 0.8640 |
2000-09-14 | 0.8617 |
2000-09-15 | 0.8572 |
2000-09-18 | 0.8523 |
2000-09-19 | 0.8514 |
2000-09-20 | 0.8462 |
2000-09-21 | 0.8558 |
2000-09-22 | 0.8793 |
... | ... |
2001-07-06 | 0.8465 |
2001-07-09 | 0.8474 |
2001-07-10 | 0.8557 |
2001-07-11 | 0.8614 |
2001-07-12 | 0.8530 |
2001-07-13 | 0.8527 |
2001-07-16 | 0.8549 |
2001-07-17 | 0.8549 |
2001-07-18 | 0.8701 |
2001-07-19 | 0.8690 |
2001-07-20 | 0.8713 |
2001-07-23 | 0.8676 |
2001-07-24 | 0.8752 |
2001-07-25 | 0.8797 |
2001-07-26 | 0.8765 |
2001-07-27 | 0.8749 |
2001-07-30 | 0.8750 |
2001-07-31 | 0.8752 |
2001-08-01 | 0.8793 |
2001-08-02 | 0.8813 |
2001-08-03 | 0.8843 |
2001-08-06 | 0.8802 |
2001-08-07 | 0.8775 |
2001-08-08 | 0.8778 |
2001-08-09 | 0.8886 |
2001-08-10 | 0.8940 |
2001-08-13 | 0.8983 |
2001-08-14 | 0.9025 |
2001-08-15 | 0.9114 |
2001-08-16 | 0.9138 |
264 rows × 1 columns
要估值的 valueDate 設定為 observationStartDate
Settings.instance().evaluationDate=valuationDate
好, 所有信息都齊備了, 我們要建立這個期權的基本信息
option=BarrierOption(Barrier.UpIn, float(triggerRate), 0.0, PlainVanillaPayoff(Option.Call, float(strike)),EuropeanExercise(expiry))
以下要進入估值階段了. 使用 numpy 的數學公式來計算 volatility. NaN的值未處理
import numpy
priceData['Log_Return']= numpy.log(priceData[fred] / priceData[fred].shift(1) )
volatility=numpy.std(priceData['Log_Return'])*numpy.sqrt(252)
volatility
0.11406364037803043
建立一個常數型的波動率, Day Count 是 Actual/365 Fixed
volatilityTS=BlackVolTermStructureHandle(BlackConstantVol(valuationDate, calendar, volatility, Actual365Fixed()))
下一步是準備 Garman Kohlagen Process 做外滙選擇權估值所需要的兩個貨幣的無風險利率, 要從網路取得免費的各國無風險利率值有點困難, 先定為 0.02 和 0.03 常數
r=0.02
rTS=YieldTermStructureHandle(FlatForward(valuationDate,r,Actual365Fixed()))
f=0.03
fTS=YieldTermStructureHandle(FlatForward(valuationDate,f,Actual365Fixed()))
Spot 價格可以取歷史數據最後一筆, 也可以直接用產品內容的 spotRate. 用 spotRate 比較不會有 Up 或 Down 矛盾的地方. 它是個 Handle, 跟變數一樣可以調整 Handle 的再重新估值, 以後再詳細說明這部份.
spot=float(spotRate)
spot
0.8935
spotHandle=QuoteHandle(SimpleQuote(spot))
再來是建立 Garman Kohlagen Process
gkProcess=GarmanKohlagenProcess(spotHandle, fTS, rTS, volatilityTS)
將 Process 指定給一個 AnalyticBarrierEngine
option.setPricingEngine(AnalyticBarrierEngine(gkProcess))
大功告成, 可以估值了!
option.NPV()
0.02283339143459734
再試試另一個 Finite-Differences Black Scholes Barrier Engine
grid=5; maxGrid=1000
option.setPricingEngine(FdBlackScholesBarrierEngine(gkProcess, grid, maxGrid))
option.NPV()
0.02295666531645272
FpML to QuantLib 外滙歐式Barrier選擇權估值 fx-ex12-fx-barrier-option.xml相关推荐
- FpML to QuantLib 外滙美式選擇權估值
FpML to QuantLib 外滙美式選擇權估值 Non-Copylefted 2019 Alvin Cho. Provided 'AS IS'. 7 May 2019. Any quantita ...
- pl/sql函数学习
7種函數的詳細介紹及用法: 1.錯誤報告(error reporting)函數 sqlcode 返回oracle錯誤號 sqlerrm 返回oracle錯誤信息 主要用於異常處理 ...
- VCD(俗称影音光碟)
VCD 影音光碟(),又稱影音壓縮光碟,是一種在光碟(Compact Disc)上存儲視訊信息的標準.VCD可以在個人電腦和VCD播放器[1]以及大部分DVD播放機中播放,但現時大部份藍光光碟播放機已 ...
- qq在线咨询代码,MSN在线代码,贸易通在线留言源代码!
QQ在线咨询代码,MSN在线代码,雅虎通在线代码,贸易通在线代码 ------------------------------------------------------------------- ...
- (转)jQuery 基础
[初探] jQuery 怎麼用來「快速選取元素」並且「做一些事情」呢?請看看程式碼: $("div").addClass("special"); 錢記號 $ 是 ...
- Jenkins:設定一次後就很方便的排程工具
Jenkins擁有定時排程功能 Jenlins可以結合GIt,達到維持本機端程式碼為最新版本 Jenkins可以結合Unity,達到定期自動編譯版本的功能 Jenkins可以結合CIFS(網路芳鄰), ...
- barrier linux,LinuxBarrierI/O的介绍有哪些呢? 爱问知识人
Barrier I/O的目的是使其之前的I/O在其之前写入存储介质,之后的I/O需要等到其写入完成后才能得到执行.为了实现这个要求,我们最多需要执行2次flush(刷新)操作.(注意,这儿所说的flu ...
- Iceberg 在基于 Flink 的流式数据入库场景中的应用
本文以流式数据入库的场景为基础,介绍引入 Iceberg 作为落地格式和嵌入 Flink sink 的收益,并分析了当前可实现的框架及要点. 应用场景 流式数据入库,是大数据和数据湖的典型应用场景.上 ...
- Python 线程障碍对象 Barrier - Python零基础入门教程
目录 一.Python 线程障碍对象 Barrier 简介 二.Python 线程障碍对象 Barrier 原理 三.Python 线程障碍对象 Barrier 函数介绍 四.Python 线程障碍对 ...
最新文章
- numpy库中ones和zeros函数传入的shape(表示各个维度的度数)参数的详解
- leetcode精选
- Betriebssystem I 操作系统课件 01. Evolution von Rechnersystemen 计算机操作系统的演变
- UA MATH566 统计理论10 Bootstrap简介
- 程序员面试题精选100题(52)-C++面试题(1)
- jupyter 数据分析可视化案例_Python数据分析及可视化实例之Anaconda、Jupyter简介
- 在定时器中service注入不进去的解决方案
- Tensorrt7: AttributeError: ‘NoneType‘ object has no attribute ‘create_execution_context‘
- java+classpath的理解_Java配置path和classpath的含义详解-Go语言中文社区
- Jquery打造AdRotator轮转图片
- WebWorker和Server-Sent Events和HTML5 WebSocket
- 六石编程学:方便调试输出的标准C代码
- windows 添加开机启动项
- 从远景论坛上学到的完美激活NERO8 NERO9的经验
- Robin广场舞案例实践分析之深入思考
- 罗克韦尔AB PLC安装Studio5000提示未安装Microsoft .NET Framework 3.5的解决方法
- 正则表达式验证中文或者英文
- 《C#零基础入门之百识百例》(三十五)方法返回 -- 自守数
- 数组转集合问题Arrays.asList()
- 使用皮皮影院搭建电影展
热门文章
- 华为WATCH GT3正式开售,健康监测和运动管理我全都要
- 灵魂的拷问 怎么将代码写得让人无法维护?
- 易淘食创始人口述:做外卖O2O的诀窍是“打穿商家”
- strongswan简单介绍
- js 捕获子元素的 focus 事件
- html边角效果图,PS制作卷边/卷角效果图2种方法,PS交错的作用,PS压缩图像方法,PSHTML+图像的解释,PS颜色位数的作用...
- 基于SSM医药后台管理系统
- FreeMaker语法大全及示例
- docker-compose模板指令 命令行指令
- echarts地图中增加图片的实例