QuantLib 金融計算——隨機過程之 Heston 過程

若是未作特別說明,文中的程序都是 Python3 代碼。算法

QuantLib 金融計算——隨機過程之 Heston 過程

載入模塊app

import QuantLib as ql
import pandas as pd
import numpy as np
import seaborn as sn

print(ql.__version__)
1.12

Heston 過程

著名的 Heston 模型描述了下列 SDE:ide

\[ \begin{aligned} d S_t & = \mu S_t d t + \sqrt { V_t } S_t d W_t^S \\ d V_t & = \kappa \left( \theta - V_t \right) d t + \sigma \sqrt { V_t } d W_t^V \\ d W_t^S d W_t^V & = \rho d t \end{aligned} \]函數

quantlib-python 中 Heston 過程的構造函數以下:spa

HestonProcess(riskFreeRate,
              dividendYield,
              s0,
              v0,
              kappa,
              theta,
              sigma,
              rho)

其中,code

  • riskFreeRateYieldTermStructureHandle 對象,描述無風險利率的期限結構;
  • dividendYieldYieldTermStructureHandle 對象,描述股息率的期限結構;
  • s0QuoteHandle 對象,資產價格的起始值;
  • v0:浮點數,波動率的起始值;
  • kappathetasigma:浮點數,描述波動率的 SDE 的參數;
  • rho:浮點數,模型中兩個布朗運動之間的相關性

除了一些檢查器以外,HestonProcess 沒有提過其餘特別的成員函數。component

因爲方程沒有顯式解,所以必須在 evolve 函數中使用算法進行離散化。quantlib-python 默認的離散化方法是 Quadratic Exponential Martingale 方法(或稱 Quadratic Exponential 方法),具體的算法細節請查看參考文獻(Andersen 和 Leif,2008)orm

因爲 evolve 函數將離散化計算中對布朗運動的離散化以參數形式暴露了出來,使得用戶能夠容易地顯現出隨機波動率對資產價格序列的影響。下面的例子比較了通常 Black Scholes 過程和 Heston 過程,所模擬的資產價格除了波動率結構之外,都徹底一致。對象

def testingStochasticProcesses2(seed):
    refDate = ql.Date(27, ql.January, 2019)
    riskFreeRate = 0.0321
    dividendRate = 0.0128
    spot = 52.0
    cal = ql.China()
    dc = ql.ActualActual()

    rdHandle = ql.YieldTermStructureHandle(
        ql.FlatForward(refDate, riskFreeRate, dc))
    rqHandle = ql.YieldTermStructureHandle(
        ql.FlatForward(refDate, dividendRate, dc))
    spotHandle = ql.QuoteHandle(
        ql.SimpleQuote(spot))

    kappa = 1.2
    theta = 0.08
    sigma = 0.05
    rho = -0.6

    v0 = theta

    hestonProcess = ql.HestonProcess(
        rdHandle, rqHandle, spotHandle, v0,
        kappa, theta, sigma, rho)

    volHandle = ql.BlackVolTermStructureHandle(
        ql.BlackConstantVol(refDate, cal, np.sqrt(v0), dc))

    bsmProcess = ql.BlackScholesMertonProcess(
        spotHandle, rqHandle, rdHandle, volHandle)

    unifMt = ql.MersenneTwisterUniformRng(seed)
    bmGauss = ql.BoxMullerMersenneTwisterGaussianRng(unifMt)

    dt = 0.004
    numVals = 250

    dw = ql.Array(2)
    x = ql.Array(2)

    x[0] = spotHandle.value()
    x[1] = v0
    y = x[0]

    htn = pd.DataFrame(
        dict(
            t=np.linspace(0, dt * numVals, numVals + 1),
            price=np.nan,
            vol=np.nan))

    bsm = pd.DataFrame(
        dict(
            t=np.linspace(0, dt * numVals, numVals + 1),
            price=np.nan,
            vol=v0))

    htn.loc[0, 'price'] = x[0]
    htn.loc[0, 'vol'] = x[1]

    bsm.loc[0, 'price'] = y

    for j in range(1, numVals + 1):
        dw[0] = bmGauss.next().value()
        dw[1] = bmGauss.next().value()

        x = hestonProcess.evolve(htn.loc[j, 't'], x, dt, dw)
        y = bsmProcess.evolve(bsm.loc[j, 't'], y, dt, dw[0])

        htn.loc[j, 'price'] = x[0]
        htn.loc[j, 'vol'] = x[1]

        bsm.loc[j, 'price'] = y

    htn = htn.melt(
        id_vars='t',
        var_name='component',
        value_name='path')

    htn['type'] = 'stochastic vol'

    bsm = bsm.melt(
        id_vars='t',
        var_name='component',
        value_name='path')

    bsm['type'] = 'constant vol'

    htn_bsm = pd.concat([htn, bsm])

    sn.relplot(
        x='t',
        y='path',
        data=htn_bsm,
        col='component',
        hue='type',
        kind="line",
        height=8,
        facet_kws=dict(sharey=False))


testingStochasticProcesses2(100)

參考文獻

  • Andersen, Leif. 2008. Simple and efficient simulation of the Heston stochastic volatility model. Journal of Computational Finance 11: 1–42.
相關文章
相關標籤/搜索