QuantLib 金融計算——數學工具之隨機數發生器

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

QuantLib 金融計算——數學工具之隨機數發生器

載入模塊dom

import QuantLib as ql
import scipy

print(ql.__version__)
1.12

概述

隨機模擬一般從產生均勻分佈的隨機數開始。假設 \(X \sim U [0, 1]\) 是均勻分佈的隨機變量。任意分佈的隨機數一般須要對 \(X\) 施加某種變換獲得,通常狀況下是用累積分佈函數的逆函數 \(F^{−1}\)\(F^{−1}(X)\) 的分佈就是 \(F\)。其餘的變換算法可能不須要 \(F^{−1}\),好比用於生成正態分佈的 Box Muller 變換算法。函數

均勻分佈的隨機數發生器主要分兩種:工具

  • 僞隨機數(wiki
  • 擬隨機數,也稱低誤差序列(wiki

僞隨機數

quantlib-python 提供瞭如下三種均勻分佈的(僞)隨機數發生器:spa

  • KnuthUniformRng,高德納(Knuth)算法
  • LecuyerUniformRng,L'Ecuyer 算法
  • MersenneTwisterUniformRng,著名的梅森旋轉(Mersenne-Twister)算法

隨機數發生器的構造函數,code

Rng(seed)

其中orm

  • seed,整數,默認值是 0,做爲種子用於初始化相應的肯定性序列;

隨機數發生器的成員函數:對象

  • next():返回一個 SampleNumber 對象,做爲模擬的結果。
r = rng.next()
v = r.value(r)

用戶經過反覆調用成員函數 next() 得到一連串的隨機數,須要注意的是 r 的類型是 SampleNumber,須要調用 value() 獲得對應的浮點數。ip

例子 1,

def testingRandomNumbers1():
    seed = 1

    unifMt = ql.MersenneTwisterUniformRng(seed)
    unifLec = ql.LecuyerUniformRng(seed)
    unifKnuth = ql.KnuthUniformRng(seed)

    print('{0:<25}{1:<25}{2:<25}'.format(
        'Mersenne Twister', 'Lecuyer', 'Knut'))

    for i in range(10):
        print('{0:<25}{1:<25}{2:<25}'.format(
            unifMt.next().value(),
            unifLec.next().value(),
            unifKnuth.next().value()))


testingRandomNumbers1()
Mersenne Twister         Lecuyer                  Knut                     
0.41702199855353683      0.2853808990946861       0.4788952510312594       
0.9971848082495853       0.2533581892659171       0.7694635535665499       
0.7203244894044474       0.09346853100919404      0.47721285286866455      
0.9325573613168672       0.6084968907396475       0.15752737762851         
0.00011438119690865278   0.90342026007861         0.6065713927733087

正態分佈(僞)隨機數

隨機模擬中最多見的分佈是正態分佈,quantlib-python 提供的正態分佈隨機數發生器有 4 類:

  • CentralLimitABCGaussianRng
  • BoxMullerABCGaussianRng
  • MoroInvCumulativeABCGaussianRng
  • InvCumulativeABCGaussianRng

其中 ABC 特指一種均勻隨機數發生器。

具體來說 4 類發生器分爲 12 種:

  • CentralLimitLecuyerGaussianRng
  • CentralLimitKnuthGaussianRng
  • CentralLimitMersenneTwisterGaussianRng
  • BoxMullerLecuyerGaussianRng
  • BoxMullerKnuthGaussianRng
  • BoxMullerMersenneTwisterGaussianRng
  • MoroInvCumulativeLecuyerGaussianRng
  • MoroInvCumulativeKnuthGaussianRng
  • MoroInvCumulativeMersenneTwisterGaussianRng
  • InvCumulativeLecuyerGaussianRng
  • InvCumulativeKnuthGaussianRng
  • InvCumulativeMersenneTwisterGaussianRng

隨機數發生器的構造函數:

rng = Rng(seed)
grng = Gaussianrng(rng)

正態分佈隨機數發生器接受一個對應的均勻分佈隨機數發生器做爲源,以 BoxMullerMersenneTwisterGaussianRng 爲例,須要配置一個 MersenneTwisterUniformRng 對象做爲隨機數的源,使用經典的 Box-Muller 算法獲得正態分佈隨機數。

例子 2,

def testingRandomNumbers2():
    seed = 12324
    unifMt = ql.MersenneTwisterUniformRng(seed)
    bmGauss = ql.BoxMullerMersenneTwisterGaussianRng(unifMt)

    for i in range(5):
        print(bmGauss.next().value())


testingRandomNumbers2()
-1.1756781173398896
0.14110041851886157
1.569582906805544
-0.026736779238941934
-0.8220676600472409

擬隨機數

相較於以前描述的「僞」隨機數,隨機模擬中另外一類重要的隨機數成爲「擬」隨機數,也稱爲低誤差序列。由於收斂性更好,擬隨機數一般用於高維隨機變量的模擬。quantlib-python 提供的擬隨機數有兩類,

  • HaltonRsg: Halton 序列
  • SobolRsg: Sobol 序列

HaltonRsg

HaltonRsg 的構造函數,

HaltonRsg(dimensionality,
          seed,
          randomStart,
          randomShift)

其中,

  • dimensionality:整數,設置維度;
  • seed,整數,默認值是 0,做爲種子用於初始化相應的肯定性序列;
  • randomStart:布爾值,默認是 True,是否隨機開始;
  • randomShift:布爾值,默認是 False,是否隨機平移。

HaltonRsg 的成員函數,

  • nextSequence():返回一個 SampleRealVector 對象,做爲模擬的結果;
  • lastSequence():返回一個 SampleRealVector 對象,做爲上一個模擬的結果;
  • dimension():返回維度。

SobolRsg

SobolRsg 的構造函數,

SobolRsg(dimensionality,
         seed,
         directionIntegers=Jaeckel)

其中,

  • dimensionality:整數,設置維度;
  • seed,整數,默認值是 0,做爲種子用於初始化相應的肯定性序列;
  • directionIntegers,quantlib-python 的內置變量,默認值是 SobolRsg.Jaeckel,用於 Sobol 序列的初始化。

SobolRsg 的成員函數,

  • nextSequence():返回一個 SampleRealVector 對象,做爲模擬的結果;
  • lastSequence():返回一個 SampleRealVector 對象,做爲上一個模擬的結果;
  • dimension():返回維度。
  • skipTo(n)n 是整數,跳轉到抽樣結果的第 n 個維度;
  • nextInt32Sequence():返回一個 IntVector 對象。

例子 3,

def testingRandomNumbers4():
    dim = 5
    haltonGen = ql.HaltonRsg(dim)
    sobolGen = ql.SobolRsg(dim)

    sampleHalton = haltonGen.nextSequence().value()
    sampleSobol = sobolGen.nextSequence().value()

    print('{0:<25}{1:<25}'.format(
        'Halton', 'Sobol'))

    for i in range(dim):
        print('{0:<25}{1:<25}'.format(
            sampleHalton[i],
            sampleSobol[i]))


testingRandomNumbers4()
Halton                   Sobol                    
0.04081786540336907      0.5                      
0.8535710143553551       0.5                      
0.69400573329408         0.5                      
0.818105927979147        0.5                      
0.878826694887864        0.5

兩類隨機數的收斂性比較

最後用一個例子比較兩類隨機數的收斂性,分別產生正態分佈的僞隨機數和擬隨機數,計算分佈的四個統計指標:

  • 均值(理論值等於 0.0);
  • 方差(理論值等於 1.0);
  • 偏度(理論值等於 0.0);
  • 超額峯度(理論值等於 0.0)。
def testingRandomNumbers5():
    sobolGen = ql.SobolRsg(1)

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

    boxMullerStat = ql.IncrementalStatistics()
    sobolStat = ql.IncrementalStatistics()

    invGauss = ql.MoroInverseCumulativeNormal()

    numSim = 10000

    for j in range(numSim):
        boxMullerStat.add(bmGauss.next().value())
        currSobolNum = sobolGen.nextSequence().value()[0]
        sobolStat.add(invGauss(currSobolNum))

    stats = {
        "BoxMuller Mean:": boxMullerStat.mean(),
        "Sobol Mean:": sobolStat.mean(),
        "BoxMuller Var:": boxMullerStat.variance(),
        "Sobol Var:": sobolStat.variance(),
        "BoxMuller Skew:": boxMullerStat.skewness(),
        "Sobol Skew:": sobolStat.skewness(),
        "BoxMuller Kurtosis:": boxMullerStat.kurtosis(),
        "Sobol Kurtosis:": sobolStat.kurtosis()}

    for k, v in stats.items():
        print('{0:>25}{1:>30}'.format(k, v))


testingRandomNumbers5()
BoxMuller Mean:          0.005966482725988245
              Sobol Mean:        -0.0002364019095203635
           BoxMuller Var:            1.0166044844467006
               Sobol Var:            0.9986010126883317
          BoxMuller Skew:           0.02100635339070779
              Sobol Skew:        -7.740573185322994e-05
      BoxMuller Kurtosis:           -0.0340476839897507
          Sobol Kurtosis:         -0.020768126049145776

直觀上看 Sobol 序列的結果更加接近理論值,這證實使用擬隨機數作模擬的收斂速度更好。

相關文章
相關標籤/搜索