JAVAからNAG数値計算ライブラリを利用する : Example 5

テクニカルレポート

4.5. Example 5

Black–Scholes–Merton オプション価格公式、関数 s30aac

ここでは入力用に Nag_PutType、入出力用に配列引数を取る NAG C Library オプション価格関数 s30aac をコールする方法を示す。またCからJava属性にどうデータを戻すかについても説明する。

内容

  1. NAG C Library マニュアルからの関数プロトタイプ
  2. Javaプログラム中でのネイティブ関数の宣言
  3. Javaプログラムのコンパイル
  4. C用のヘッダファイルの生成
  5. ネイティブ関数のCによる実装
  6. 共用ライブラリ/DLLの作成
  7. プログラムの実行
  8. クイックサマリ

  1. NAG C Library マニュアルからの関数プロトタイプ
  2. 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 ルーチン仕様を参照されたい。

  3. Javaプログラム中でのネイティブ関数の宣言
  4. 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 戻り値を用いる。

  5. Javaプログラムのコンパイル
  6. 次に示すのはJavaプログラム EuropeanOptPrice.java のソースコードである。
    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 
    

  7. C用のヘッダファイルの生成
  8. EuropeanOptPrice.java コンパイルが終わると、javah を使ってCヘッダファイルを作成することができる。

      % javah -jni EuropeanOptPrice 
    
    生成されたヘッダファイル EuropeanOptPrice.h には次の関数プロトタイプが含まれている。
      JNIEXPORT jint JNICALL Java_EuropeanOptPrice_s30aac
      (JNIEnv *, jobject, jchar, jint, jint, jdoubleArray, jdouble, jdoubleArray, 
      jdouble, jdouble, jdouble, jdoubleArray); 
    

  9. ネイティブ関数のCによる実装
  10. ヘッダファイル EuropeanOptPrice.h が作成できたところで、今度は Java_EuropeanOptPrice_s30aac のCコードによる実装に移る。次はファイル EuropeanOptPriceImp.c の内容を記したものである。

    #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;
    } 
    
    注意事項:

    • これまでと同様、適切な NAG C Library ヘッダファイルをインクルードすると共に、s30aac へのfail引数として引渡すべく、型が NagError の変数 fail を宣言しておかなくてはならない。

    • 配列引数 x, t, pExample 2 で記したと同じ手法で取扱う必要がある。

    • s30aac に対するorder引数として引渡すべく、型が Nag_OrderType の変数 order を宣言しておかなくてはならない。この引数は2次元の記憶方式、すなわち行優先順(row-major ordering)、または列優先順(column-major ordering)が用いられることを指定する。Java言語によって定義された記憶方式は order=Nag_RowMajor という形で指定される。

    • s30aac に引渡す必要のあるもう一つの変数は型が Nag_PutTypeiput である。これはオプションが call であるか put であるかを規定する。その値は型が jchar の引数 calput に依存する。
      jcharjhi.h 中で次のように定義されている。
      typedef unsigned short jchar; 
      
      従って if 文を用いた簡単な比較によって iput に対し正しい値を設定することができる。

  11. 共用ライブラリ/DLLの作成
  12. このステップは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 
      

    関連するコンパイラフラグについては Example 1 セクション7 を参照されたい。

  13. プログラムの実行
  14. これまでの操作がすべて正常に行われたとすると、次のコマンドによってプログラムを実行できる。

      % 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 ヒント を参照)

  15. クイックサマリ
  16. 2つのソースファイル EuropeanOptPrice.javaEuropeanOptPriceImp.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 のインストレーションに合せて適宜調整を要す。

    • Javaプログラムの実行:
        % java EuropeanOptPrice 
      

Copyright 2009 Numerical Algorithms Group
Page last updated 2009-04-21 14:12:43 mick
[NP3671]


関連情報
Privacy Policy  /  Trademarks