NtRandが素晴らしすぎてそれにインスパイアされた僕はVBAでクレイトン・コピュラ(clayton copula)を作ってみた
NtRandはニューメリカルテクノロジー社さんが作られてフリーで公開されているExcel用乱数生成関数アドインです。
公式サイトはコチラ。
これでもうVBAの質の悪い一様乱数生成器Rnd()関数を使うのやめようね!
まずは http://www.ntrand.com/jp/download/ からアドインを落としてインストール。
基本的な使い方は上記のサイトにあるサンプルエクセルファイルを見るべし。
今回は題名にあるようにこのNtRandを使って二変量クレイトン・コピュラを生成する関数を作成してみた。
VBAからでもワークシートからでも関数として呼び出すことが可能。
ケンドールの順位相関係数が0.5になるように1000サンプルExcelで作ってみた結果は
な感じ。
以下コード。
※注意点
- VBAから乱数生成関数を呼ぶ時はApplication.Runを使ってる(こうするらしい。公式サイトより)
- ガンマ関数に従う乱数生成関数がなかったので逆変換法を使って生成するようにしている
- 乱数のシードは毎回初期化しちゃってる
これを標準モジュールに張り付けておけばシートからClaytonCopula関数を呼ぶ事ができます。
Option Explicit '逆関数法でガンマ分布に従う乱数生成 Public Function NTRANDGAMMA(size As Long, alpha As Double, beta As Double, seed1 As Long, seed2 As Long) As Variant Dim rand_uniform As Variant: rand_uniform = Application.Run("NTRAND", size, 0, seed1, seed2) Dim i As Long Dim result As Variant: ReDim result(1 To size, 1 To 1) If size = 1 Then result(1, 1) = Application.WorksheetFunction.GammaInv(CDbl(rand_uniform(1)), alpha, beta) Else For i = 1 To size result(i, 1) = Application.WorksheetFunction.GammaInv(CDbl(rand_uniform(i, 1)), alpha, beta) Next End If NTRANDGAMMA = result End Function Public Function ClaytonCopula(size As Long, alpha As Double, dimension As Long) As Variant '標準ガンマ分布に従う乱数を次元の個数分取得 Dim rand_gammas As Variant: rand_gammas = NTRANDGAMMA(size, 1 / alpha, 1, Rnd() * 2147483647, Rnd() * 2147483647) Dim result As Variant: ReDim result(1 To size, 1 To dimension) Dim rand_uniform As Variant: rand_uniform = Application.Run("NTRAND", size * dimension, 0, Rnd() * 2147483647, Rnd() * 2147483647) Dim i As Long, j As Long For i = 1 To size For j = 1 To dimension result(i, j) = (1 - 1 / rand_gammas(i, 1) * Log(rand_uniform(j + dimension * (i - 1), 1))) ^ (-1 / alpha) Next Next ClaytonCopula = result End Function
ちなみにここで使ってる方法はコピュラの生成方法はマーシャル=オルキン法という物で、
「コピュラの金融実務での具体的な活用方法の解説」戸坂 凡展/吉羽 要直
のP135以降に解説がある。順位相関とコピュラで指定するパラメーターαの変換公式的なものは同資料P159。
※ここで作ったサンプルExcelファイルはココからダウンロードできるようにしました。
※Excelのバージョンは2007です。無保証。変更・再配布ご自由に
※サンプルでは2変量でやってるけど、コードは多変量対応。チェックはしてない。