4.5. Example 5
Black–Scholes–Merton オプション価格公式、関数 s30aac |
内容
- nAG C Library マニュアルからの関数プロトタイプ
- Javaプログラム中でのネイティブ関数の宣言
- Javaプログラムのコンパイル
- C用のヘッダファイルの生成
- ネイティブ関数のCによる実装
- 共用ライブラリ/DLLの作成
- プログラムの実行
- クイックサマリ
- nAG C Library マニュアルからの関数プロトタイプ
- Javaプログラム中でのネイティブ関数の宣言
- Javaプログラムのコンパイル 次に示すのはJavaプログラム EuropeanOptPrice.java のソースコードである。
- C用のヘッダファイルの生成 EuropeanOptPrice.java のコンパイルが終わると、javah を使ってCヘッダファイルを作成することができる。
- ネイティブ関数のCによる実装 ヘッダファイル EuropeanOptPrice.h が作成できたところで、今度は Java_EuropeanOptPrice_s30aac のCコードによる実装に移る。次はファイル EuropeanOptPriceImp.c の内容を記したものである。
- これまでと同様、適切な nAG C Library ヘッダファイルをインクルードすると共に、s30aac へのfail引数として引渡すべく、型が NagError の変数 fail を宣言しておかなくてはならない。
- 配列引数 x, t, p を Example 2 で記したと同じ手法で取扱う必要がある。
- s30aac に対するorder引数として引渡すべく、型が Nag_OrderType の変数 order を宣言しておかなくてはならない。この引数は2次元の記憶方式、すなわち行優先順(row-major ordering)、または列優先順(column-major ordering)が用いられることを指定する。Java言語によって定義された記憶方式は order=Nag_RowMajor という形で指定される。
- s30aac に引渡す必要のあるもう一つの変数は型が Nag_PutType
の iput である。これはオプションが call であるか put
であるかを規定する。その値は型が jchar の引数 calput
に依存する。
jchar は jhi.h 中で次のように定義されている。typedef unsigned short jchar;
従って if 文を用いた簡単な比較によって iput に対し正しい値を設定することができる。 - 共用ライブラリ/DLLの作成 このステップはOS依存となる。
- Linux上での作成
% cc -c -fPIC -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux \ -I/opt/nAG/cll6a09dgl/include EuropeanOptPriceImp.c % ld -G -z defs EuropeanOptPriceImp.o -o libnagCJavaInterface.so \ /opt/nAG/cll6a09dgl/lib/libnagc_nag.so -lm -lc -lpthread
他のUNIX系マシン上ではさらなるライブラリの追加がリンク時に必要となる場合がある(Example 1 の注意参照)。
- Windows上でのVisual C++による作成
C:\> cl -Ic:\jdk1.6.0_11\include -Ic:\jdk1.6.0_11\include\win32 -I"c:\Program Files\nAG\cldll094zl\include" /Gz -LD EuropeanOptPriceImp.c "c:\Program Files\cldll094zl\lib\CLDLL094Z_nag.lib" -FenagCJavaInterface.dll
- プログラムの実行 これまでの操作がすべて正常に行われたとすると、次のコマンドによってプログラムを実行できる。
- クイックサマリ 2つのソースファイル EuropeanOptPrice.java と EuropeanOptPriceImp.c が与えられたとして、次のコマンドを発行する。
- Javaクラスのコンパイル:
% javac EuropeanOptPrice.java
- ヘッダファイルの作成:
% javah -jni EuropeanOptPrice
- インタフェースライブラリのコンパイル:
- (Linux)
% gcc -c -fPIC -I/opt/jdk1.6.0_11/include -I/opt/jdk1.6.0_11/include/linux \ -I/opt/nAG/cll6a09dgl/include EuropeanOptPriceImp.c % ld -G -z defs EuropeanOptPriceImp.o -o libnagCJavaInterface.so \ /opt/nAG/cll6a09dgl/lib/libnagc_nag.so -lm -lc -lpthread
ただしディレクトリ名称 /opt/jdk1.6.0_11/include, /opt/jdk1.6.0_11/include/linux, /opt/nAG/cll6a09dgl/include, /opt/nAG/cll6a09dgl/lib, /opt/gfortran/irun/lib64/libgfortran.so はJavaと nAG C Library, GNU Fortran Library のインストレーションに合せて適宜調整を要す。 - (Windows/Visual C++)
C:\> cl -Ic:\jdk1.6.0_11\include -Ic:\jdk1.6.0_11\include\win32 -I"c:\Program Files\nAG\cldll094zl\include" /Gz -LD EuropeanOptPriceImp.c "c:\Program Files\cldll094zl\lib\CLDLL094Z_nag.lib" -FenagCJavaInterface.dll
ただしディレクトリ名称 c:\jdk1.6.0_11\include, c:\jdk1.6.0_11\include\win32, "c:\Program Files\nAG\cldll094zl\include", "c:\Program Files\nAG\cldll094zl\lib" はJavaと nAG C Library のインストレーションに合せて適宜調整を要す。
- (Linux)
- Javaプログラムの実行:
% java EuropeanOptPrice
C Library マニュアルによれば関数 s30aac に対するプロトタイプは次のとおりである。
#include <nag.h> #include <nags.h> void s30aac(Nag_OrderType order, Nag_PutType iput, Integer m, Integer n, const double x[], double s, const double t[], double sigma, double r, double q, double p[], NagError *fail)関数 s30aac は欧州の call または put オプション(iput により決定される)の価格を Black–Scholes–Merton 公式を用いて計算する機能を提供する。ここに sigma は一定の変動性(volatility)を、r はリスクフリーの金利を、q は配当利回り(dividend yield)を意味する。
計算されたオプション価格は配列引数 p を介して戻される。
すべてのルーチン引数に関する詳細については nAG C Library マニュアル中の s30aac ルーチン仕様を参照されたい。
Example 1, Example 2, Example 3 の場合と同様、NagError 構造体の内容をJavaには戻さないものとする。従ってJavaプログラム内では関数を次のように宣言すれば良い。
// Declaration of the Native (C) function private native int s30aac(char calput, int m, int n, double[] x, double s, double[] t, double sigma, double r, double q, double[] p);これは int を応答として返すメソッドを意味する。
なお、許されるすべての引数を受渡しするわけではない点に注意。例えば order は含まれていない。もしそれが含んでいる情報をJavaに返したいのであればその引数を追加すれば良いのであるが、ここでは含めずにおく。また引数 iput は型が char の引数によって置き換えられている。後段でそれは Nag_PutType 引数に変換されることになる。また ifail 引数も使用しないことから、エラーコードの通知には int 戻り値を用いる。
public class EuropeanOptPrice { // Declaration of the Native (C) function private native int s30aac(char calput, int m, int n, double[] x, double s, double[] t, double sigma, double r, double q, double[] p); static { // The runtime system executes a class's static // initializer when it loads the class. System.loadLibrary("nagCJavaInterface"); } // The main program public static void main(String[] args) { double x[], t[], p[]; double s, sigma, r, q; int i, j, m, n, retCode; char calput; // Create an object of class EuropeanOptPrice EuropeanOptPrice price = new EuropeanOptPrice(); calput = 'C'; s = 55.0; sigma = 0.3; r = 0.1; q = 0.0; m = 3; n = 2; p = new double[m*n]; x = new double[m]; t = new double[n]; for (i = 0; i < m*n; i++) p[i] = 0.0; x[0] = 58.0; x[1] = 60.0; x[2] = 62.0; t[0] = 0.7; t[1] = 0.8; System.out.println(); System.out.println("Call of nAG Black-Scholes-Merton option pricing routine s30aac"); System.out.println(); // Call method s30aac of object price retCode = price.s30aac(calput, m, n, x, s, t, sigma, r, q, p); System.out.print("Return code from s30aac = "); System.out.println(retCode); System.out.println(); if (retCode == 0) { // Print the input values System.out.println("European Call:"); System.out.println("Spot " + s); System.out.println("Volatility " + sigma); System.out.println("Rate " + r); System.out.println("Dividend " + q); System.out.println(); // Print the solution System.out.println(" Strike Expiry Option Price"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) System.out.format("%8.4f %8.4f %8.4f%n",x[i],t[j],p[i*n + j]); } System.out.println(); } } }メインプログラムは単に引数の値をセットし、それらの引数を用いてネイティブメソッドをコールする。
Javaプログラムをコンパイルするには次のコマンドを使用すれば良い。
% javac EuropeanOptPrice.java
% javah -jni EuropeanOptPrice生成されたヘッダファイル EuropeanOptPrice.h には次の関数プロトタイプが含まれている。
JNIEXPORT jint JNICALL Java_EuropeanOptPrice_s30aac (JNIEnv *, jobject, jchar, jint, jint, jdoubleArray, jdouble, jdoubleArray, jdouble, jdouble, jdouble, jdoubleArray);
#include <jni.h> /* Java Native Interface headers */ #include "EuropeanOptPrice.h" /* Auto-generated header created by javah -jni */ #include <nag.h> /* nAG C Library headers */ #include <nags.h> /* Our C definition of the function s30aac declared in EuropeanOptPrice.java */ JNIEXPORT jint JNICALL Java_EuropeanOptPrice_s30aac (JNIEnv *env, jobject obj, jchar calput, jint m, jint n, jdoubleArray x, jdouble s, jdoubleArray t, jdouble sigma, jdouble r, jdouble q, jdoubleArray p) { static NagError fail; Nag_PutType iput; Nag_OrderType order; /* First extract the arrays from Java */ jdouble *xpt, *tpt, *ppt; jboolean isCopy; xpt = (*env)->GetDoubleArrayElements(env, x, &isCopy); tpt = (*env)->GetDoubleArrayElements(env, t, &isCopy); ppt = (*env)->GetDoubleArrayElements(env, p, &isCopy); /* Java stores arrays in row order */ order = Nag_RowMajor; /* Convert calput into Nag_PutType */ if (calput == 'P') { iput = Nag_Put; } else if (calput == 'C') { iput = Nag_Call; } /* Call s30aac */ fail.print = Nag_FALSE; s30aac(order, iput, m, n, xpt, s, tpt, sigma, r, q, ppt, &fail); /* Release the array elements back to Java */ (*env)->ReleaseDoubleArrayElements(env, x, xpt, 0); (*env)->ReleaseDoubleArrayElements(env, t, tpt, 0); (*env)->ReleaseDoubleArrayElements(env, p, ppt, 0); /* Return any fail code that the nagc.dll function s30aac returned. */ return fail.code; }注意事項:
関連するコンパイラフラグについては Example 1 セクション7 を参照されたい。
% java EuropeanOptPrice期待される出力は次のとおり。
Call of nAG Black-Scholes-Merton option pricing routine s30aac Return code from s30aac = 0 European Call: Spot 55.0 Volatility 0.3 Rate 0.1 Dividend 0.0 Strike Expiry Option Price 58.0000 0.7000 5.9198 58.0000 0.8000 6.5506 60.0000 0.7000 5.0809 60.0000 0.8000 5.6992 62.0000 0.7000 4.3389 62.0000 0.8000 4.9379
(ライブラリが見つけられないという趣旨のエラーメッセージが発行された場合には、Example 2 の ヒント を参照)
Copyright 2009 Numerical Algorithms Group
Page last updated 2009-04-21 14:12:43 mick
[NP3671]