QuantLib財務計算 - DIYパッケージのPythonインタフェース(1)

QuantLib財務計算 - DIYパッケージのPythonインタフェース(1)

アウトライン

QuantLibは始まったは、PyPIは共通パケット区別できない上、使いやすいインストールするパッケージPythonインタフェースをリリース。そしてタイムリーに対応するQuantLibの最新バージョンを維持するために更新されます。

効果にPythonインタフェースの公式リリース広さ包括的には、欠点はある深さが不十分時には、ユーザーが正確に機能必要なパッケージ(ではない「曲線のイールドカーブの建設(3)」の記事で前に述べた)、それは再パッケージインタフェースすることが望ましい、あなたが機能を追加する必要があります。また、ユーザーは持っている、またはC ++ソースコード拡張または修理quantLib、梱包希望のレベルでの新機能が拡張され、公式のPythonインタフェースと組み合わせて使用。

これらの各場合には、ユーザー自身がPythonインタフェースをパッケージにそれを行う必要があります。

どのようにQuantLibパッケージのPythonインタフェース?

使用してQuantLib SWIGを自分の手をパッケージ化し、それゆえ、(他のインターフェース言語はまた、SWIGでパッケージされている)Pythonインタフェースをカプセル化するためには、Pythonのインターフェイスは、(参照、使用の少しがぶ飲みを理解する必要があり、ここここ)。

C ++ SWIGパッケージの流れは、おおよそ次の通り:

  1. 「インターフェース・ファイル」(ファイル拡張子があるの数の調製.iSWIGパッケージC ++ソースコードを通知する方法)。
  2. インターフェイスファイルコマンドのSWIGの実行は、それが生成されます.py(Pythonのインタフェースが定義された関数又はクラスの数を含む、カプセル化され記載されている)、およびファイルを.cppファイル(インターフェースの背後には、文書を生成するために、エンジンによって計算されます)。
  3. 書き込みおよび実行setup.pyコンパイルされ、.cppファイルを、得られたコンパイル.soしてファイル(ダイナミックリンクライブラリ)を.pyC ++の後ろにPythonのインタフェースおよび計算エンジンの表面を介して、ファイルバインド。
  4. 最後に(システムディレクトリに含まれる)Pythonパッケージを得ました。

SWIGインタフェースファイルのQuantLib異なるバージョンができ、ここで得られます。すべてのインタフェースファイルは、3つの部分に分けることができます。

  1. quantlib.i(この文書に係るトップインターフェイスファイル、SWIGインタフェース・コードが生成されている.py.cpp)。
  2. ql.i 中間層ファイル、インターフェース・ファイルが一緒に他の使用しました。
  3. bonds.idate.iなどは、特定のインターフェイスファイルをパッケージ化しています。

自分をパッケージ化するPythonインタフェース

本当の、実際のコンピューティングタスク、型チェックや例外処理、など実際にのC ++オブジェクトの背後に良いSWIGのPythonパッケージインタフェースの皮に、原則の少しSWIGがあります知って、これらは、C ++オブジェクトに委託されています。

あなたが推測することができますので、これはちょうどあるので、二つの異なるPythonのインターフェースにいくつかのC ++コードをパッケージには、インタフェースは、2を混合することができるはずです「別の服を着て同じ人。」

次のテスト実験により、このアイデア。

パッケージングArrayおよびMatrixクラス

QuantLibで二つのクラスArrayMatrix、例えば、彼らは独立している、QuantLibExパッケージとしてパッケージ名。特定のインターフェイスファイルは直接書き込む公式バージョン(バージョン1.15)のリリースを実行する必要はありません。

SWIGインタフェースファイルの公式リリースでは、ArrayMatrix対応する文書がありlinearalgebra.i、ファイルが(含まれ%includecommon.itypes.i2つのファイルを。

一緒に3つの文書上でquantlib.i(名前を変更quantlibex.i)とql.iQuantLibExを構築インターフェイスファイルとして、独立した、とのインタフェースパッケージのPythonに依存しないコードの一部を削除します。

5つのインターフェイスファイルが含まれているディレクトリに作成QuantLibExディレクトリを、その後、必要に応じて生成するがぶ飲みコマンドを実行.pyし、.cppファイルを:

swig -c++ -python -outdir QuantLibEx -o QuantLibEx/qlx_wrap.cpp quantlibex.i

QuantLibExディレクトリには、2つのファイルを表示されますQuantLibEx.pyqlx_wrap.cppQuantLibExがPythonパッケージになるようにするには、追加する必要がある__init__.pyファイル(コンテンツ参照の付録を)。

QuantLibEx.pyそして、qlx_wrap.cppあなたしている実行する準備ができてプリ書かれたsetup.py文書(コンテンツ参照の付録では)、コンパイル済みの.cppシステムディレクトリやPythonにパックファイルを、。

まず、構築物(buildコマンド)QuantLibExパッケージ:

python3 setup.py build
running build
running build_py
creating build
creating build/lib.linux-x86_64-3.6
creating build/lib.linux-x86_64-3.6/QuantLibEx
copying QuantLibEx/__init__.py -> build/lib.linux-x86_64-3.6/QuantLibEx
copying QuantLibEx/QuantLibEx.py -> build/lib.linux-x86_64-3.6/QuantLibEx
running build_ext
building 'QuantLibEx._QuantLibEx' extension
creating build/temp.linux-x86_64-3.6
creating build/temp.linux-x86_64-3.6/QuantLibEx
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/ql -I/usr/include/python3.6m -c QuantLibEx/qlx_wrap.cpp -o build/temp.linux-x86_64-3.6/QuantLibEx/qlx_wrap.o
x86_64-linux-gnu-g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.6/QuantLibEx/qlx_wrap.o -L/usr/lib/ -lQuantLib -o build/lib.linux-x86_64-3.6/QuantLibEx/_QuantLibEx.cpython-36m-x86_64-linux-gnu.so

成功したビルド後に表示されますbuildビルド済みQuantLibExパッケージを含む文書の数を、含まれているディレクトリ、。その後、インストール(入力installPythonのシステムディレクトリにパッケージ化コマンド)のリンクを、(sudoの権限が必要です)。

sudo python3 setup.py install
running install
running build
running build_py
running build_ext
running install_lib
copying build/lib.linux-x86_64-3.6/QuantLibEx/QuantLibEx.py -> /usr/local/lib/python3.6/dist-packages/QuantLibEx
copying build/lib.linux-x86_64-3.6/QuantLibEx/_QuantLibEx.cpython-36m-x86_64-linux-gnu.so -> /usr/local/lib/python3.6/dist-packages/QuantLibEx
byte-compiling /usr/local/lib/python3.6/dist-packages/QuantLibEx/QuantLibEx.py to QuantLibEx.cpython-36.pyc
running install_egg_info
Writing /usr/local/lib/python3.6/dist-packages/QuantLibEx-0.1.egg-info

実行pip3 listあなたがQuantLibExを見ることができます。

...
QuantLib                1.17
QuantLibEx              0.1
...

QuantLibExと公式のパッケージミックス

公式パッケージは、(QuantLib-1.17ベース)の使用を混合することができるかどうかを簡単にQuantLibExを確認され、次の(QuantLib-1.15ベース)と:

import QuantLib as ql
import QuantLibEx as qlx

array = ql.Array(5,0.2)
print(type(array))
print(array)

arrayX = qlx.Array(5,0.3)
print(type(arrayX))
print(arrayX)

print(array + arrayX)
<class 'QuantLib.QuantLib.Array'>
[ 0.2; 0.2; 0.2; 0.2; 0.2 ]
<class 'QuantLibEx.QuantLibEx.Array'>
[ 0.3; 0.3; 0.3; 0.3; 0.3 ]
[ 0.5; 0.5; 0.5; 0.5; 0.5 ]

もう少し複雑な例 - 次元補間:

xVec = [float(i) for i in range(10)]
yVec = [float(i) for i in range(10)]

m = ql.Matrix(len(xVec), len(yVec))
mX = qlx.Matrix(len(xVec), len(yVec))

for rowIt in range(len(xVec)):
    for colIt in range(len(yVec)):
        m[rowIt][colIt] = scipy.sin(xVec[rowIt]) + scipy.sin(yVec[colIt])
        mX[rowIt][colIt] = scipy.sin(xVec[rowIt]) + scipy.sin(yVec[colIt])

print(type(m))
print(m)

print(type(mX))
print(mX)

bicubIntp = ql.BicubicSpline(
    xVec, yVec, m)

bicubIntpX = ql.BicubicSpline(
    xVec, yVec, mX)

x = 0.5
y = 4.5

print("Analytical Value:  ", scipy.sin(x) + scipy.sin(y))
print("Bicubic Value(base on ql):  ", bicubIntp(x, y))
print("Bicubic Value(base on qlx):  ", bicubIntpX(x, y))
<class 'QuantLib.QuantLib.Matrix'>
| 0 0.841471 0.909297 0.14112 -0.756802 -0.958924 -0.279415 0.656987 0.989358 0.412118 |
| 0.841471 1.68294 1.75077 0.982591 0.0846685 -0.117453 0.562055 1.49846 1.83083 1.25359 |
| 0.909297 1.75077 1.81859 1.05042 0.152495 -0.0496268 0.629882 1.56628 1.89866 1.32142 |
| 0.14112 0.982591 1.05042 0.28224 -0.615682 -0.817804 -0.138295 0.798107 1.13048 0.553238 |
| -0.756802 0.0846685 0.152495 -0.615682 -1.5136 -1.71573 -1.03622 -0.0998159 0.232556 -0.344684 |
| -0.958924 -0.117453 -0.0496268 -0.817804 -1.71573 -1.91785 -1.23834 -0.301938 0.030434 -0.546806 |
| -0.279415 0.562055 0.629882 -0.138295 -1.03622 -1.23834 -0.558831 0.377571 0.709943 0.132703 |
| 0.656987 1.49846 1.56628 0.798107 -0.0998159 -0.301938 0.377571 1.31397 1.64634 1.06911 |
| 0.989358 1.83083 1.89866 1.13048 0.232556 0.030434 0.709943 1.64634 1.97872 1.40148 |
| 0.412118 1.25359 1.32142 0.553238 -0.344684 -0.546806 0.132703 1.06911 1.40148 0.824237 |

<class 'QuantLibEx.QuantLibEx.Matrix'>
| 0 0.841471 0.909297 0.14112 -0.756802 -0.958924 -0.279415 0.656987 0.989358 0.412118 |
| 0.841471 1.68294 1.75077 0.982591 0.0846685 -0.117453 0.562055 1.49846 1.83083 1.25359 |
| 0.909297 1.75077 1.81859 1.05042 0.152495 -0.0496268 0.629882 1.56628 1.89866 1.32142 |
| 0.14112 0.982591 1.05042 0.28224 -0.615682 -0.817804 -0.138295 0.798107 1.13048 0.553238 |
| -0.756802 0.0846685 0.152495 -0.615682 -1.5136 -1.71573 -1.03622 -0.0998159 0.232556 -0.344684 |
| -0.958924 -0.117453 -0.0496268 -0.817804 -1.71573 -1.91785 -1.23834 -0.301938 0.030434 -0.546806 |
| -0.279415 0.562055 0.629882 -0.138295 -1.03622 -1.23834 -0.558831 0.377571 0.709943 0.132703 |
| 0.656987 1.49846 1.56628 0.798107 -0.0998159 -0.301938 0.377571 1.31397 1.64634 1.06911 |
| 0.989358 1.83083 1.89866 1.13048 0.232556 0.030434 0.709943 1.64634 1.97872 1.40148 |
| 0.412118 1.25359 1.32142 0.553238 -0.344684 -0.546806 0.132703 1.06911 1.40148 0.824237 |

Analytical Value:   -0.498104579060894
Bicubic Value(base on ql):   -0.49656170664824184
Bicubic Value(base on qlx):   -0.49656170664824184

これまでのところ、すべてが期待される、カスタマイズされたパッケージとパッケージ実際に混合使用の公式リリースとして実行することができます。しかし、いくつかの判断の種類奇妙な

b = array + arrayX
c = arrayX + array

print(type(b))
print(type(c))
<class 'QuantLibEx.QuantLibEx.Array'>
<class 'QuantLibEx.QuantLibEx.Array'>

なぜ、bcにQuantLibExに決定しましたかArray

付録:インタフェースファイル、setup.pyおよび__init__.py

  • quantlibex.i
%module QuantLibEx

%include exception.i

%exception {
    try {
        $action
    } catch (std::out_of_range& e) {
        SWIG_exception(SWIG_IndexError,const_cast<char*>(e.what()));
    } catch (std::exception& e) {
        SWIG_exception(SWIG_RuntimeError,const_cast<char*>(e.what()));
    } catch (...) {
        SWIG_exception(SWIG_UnknownError,"unknown error");
    }
}

//#if defined(SWIGPYTHON)
%{
#include <ql/version.hpp>
const int    __hexversion__ = QL_HEX_VERSION;
const char* __version__    = QL_VERSION;
%}

const int __hexversion__;
%immutable;
const char* __version__;
%mutable;
//#endif

%include ql.i
  • ql.i
//#if defined(SWIGPYTHON)
%{
#ifdef barrier
#undef barrier
#endif
%}
//#endif

%{
#include <ql/quantlib.hpp>

#if QL_HEX_VERSION < 0x011400f0
    #error using an old version of QuantLib, please update
#endif

#ifdef BOOST_MSVC
#ifdef QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN
#define BOOST_LIB_NAME boost_thread
#include <boost/config/auto_link.hpp>
#undef BOOST_LIB_NAME
#define BOOST_LIB_NAME boost_system
#include <boost/config/auto_link.hpp>
#undef BOOST_LIB_NAME
#endif
#endif

// add here SWIG version check

%}

//#ifdef SWIGPYTHON
%{
#if PY_VERSION_HEX < 0x02010000
    #error Python version 2.1.0 or later is required
#endif
%}
//#endif

// common name mappings

%include common.i
%include linearalgebra.i
%include types.i
  • types.i
#ifndef quantlib_types_i
#define quantlib_types_i

%include common.i
%include std_common.i

%{
using QuantLib::Integer;
using QuantLib::BigInteger;
using QuantLib::Natural;
using QuantLib::BigNatural;
using QuantLib::Real;
using QuantLib::Decimal;
using QuantLib::Time;
using QuantLib::Rate;
using QuantLib::Spread;
using QuantLib::DiscountFactor;
using QuantLib::Volatility;
using QuantLib::Probability;
using QuantLib::Size;
%}

typedef int Integer;
typedef long BigInteger;
typedef unsigned int Natural;
typedef unsigned long BigNatural;
typedef double Real;

typedef Real Decimal;
typedef Real Time;
typedef Real Rate;
typedef Real Spread;
typedef Real DiscountFactor;
typedef Real Volatility;
typedef Real Probability;

//#if defined(SWIGPYTHON)
// needed for those using SWIG 1.3.21 in order to compile with VC++6
%typecheck(SWIG_TYPECHECK_INTEGER) std::size_t {
    $1 = (PyInt_Check($input) || PyLong_Check($input)) ? 1 : 0;
}
//#endif

typedef std::size_t Size;

#endif
  • common.i
#ifndef quantlib_common_i
#define quantlib_common_i

%include stl.i
%include exception.i

%define QL_TYPECHECK_BOOL       7210    %enddef

%{
// This is necessary to avoid compile failures on
// GCC 4
// see http://svn.boost.org/trac/boost/ticket/1793

#if defined(NDEBUG)
#define BOOST_DISABLE_ASSERTS 1
#endif

#include <boost/algorithm/string/case_conv.hpp>
%}

//#if defined(SWIGPYTHON)
%typemap(in) boost::optional<bool> %{
    if($input == Py_None)
        $1 = boost::none;
    else if ($input == Py_True)
        $1 = true;
    else
        $1 = false;
%}
%typecheck (QL_TYPECHECK_BOOL) boost::optional<bool> {
if (PyBool_Check($input) || Py_None == $input)
    $1 = 1;
else
    $1 = 0;
}
//#endif

%{
// generally useful classes
using QuantLib::Error;
using QuantLib::Handle;
using QuantLib::RelinkableHandle;
%}

namespace boost {

    template <class T>
    class shared_ptr {
      public:
        T* operator->();
        //#if defined(SWIGPYTHON)
        %extend {
            bool __nonzero__() {
                return !!(*self);
            }
            bool __bool__() {
                return !!(*self);
            }
        }
        //#endif
    };

}

template <class T>
class Handle {
  public:
    Handle(const boost::shared_ptr<T>& = boost::shared_ptr<T>());
    boost::shared_ptr<T> operator->();
    //#if defined(SWIGPYTHON)
    %extend {
        bool __nonzero__() {
            return !self->empty();
        }
        bool __bool__() {
            return !self->empty();
        }
    }
    //#endif
};

template <class T>
class RelinkableHandle : public Handle<T> {
  public:
    RelinkableHandle(const boost::shared_ptr<T>& = boost::shared_ptr<T>());
    void linkTo(const boost::shared_ptr<T>&);
};

%define swigr_list_converter(ContainerRType,
                            ContainerCType, ElemCType)
%enddef

%define deprecate_feature(OldName, NewName)
//#if defined(SWIGPYTHON)
%pythoncode %{
def OldName(*args, **kwargs):
    from warnings import warn
    warn('%s is deprecated; use %s' % (OldName.__name__, NewName.__name__))
    return NewName(*args, **kwargs)
%}
//#endif
%enddef

#endif
  • linearalgebra.i
#ifndef quantlib_linear_algebra_i
#define quantlib_linear_algebra_i

%include common.i
%include types.i
%include stl.i

%{
using QuantLib::Array;
using QuantLib::Matrix;
%}

%define QL_TYPECHECK_ARRAY       4210    %enddef
%define QL_TYPECHECK_MATRIX      4220    %enddef

//#if defined(SWIGPYTHON)
%{
bool extractArray(PyObject* source, Array* target) {
    if (PyTuple_Check(source) || PyList_Check(source)) {
        Size size = (PyTuple_Check(source) ?
                     PyTuple_Size(source) :
                     PyList_Size(source));
        *target = Array(size);
        for (Size i=0; i<size; i++) {
            PyObject* o = PySequence_GetItem(source,i);
            if (PyFloat_Check(o)) {
                (*target)[i] = PyFloat_AsDouble(o);
                Py_DECREF(o);
            } else if (PyInt_Check(o)) {
                (*target)[i] = Real(PyInt_AsLong(o));
                Py_DECREF(o);
            } else {
                Py_DECREF(o);
                return false;
            }
        }
        return true;
    } else {
        return false;
    }
}
%}

%typemap(in) Array (Array* v) {
    if (extractArray($input,&$1)) {
        ;
    } else {
        SWIG_ConvertPtr($input,(void **) &v, $&1_descriptor,1);
        $1 = *v;
    }
};
%typemap(in) const Array& (Array temp) {
    if (extractArray($input,&temp)) {
        $1 = &temp;
    } else {
        SWIG_ConvertPtr($input,(void **) &$1,$1_descriptor,1);
    }
};
%typecheck(QL_TYPECHECK_ARRAY) Array {
    /* native sequence? */
    if (PyTuple_Check($input) || PyList_Check($input)) {
        Size size = PySequence_Size($input);
        if (size == 0) {
            $1 = 1;
        } else {
            PyObject* o = PySequence_GetItem($input,0);
            if (PyNumber_Check(o))
                $1 = 1;
            else
                $1 = 0;
            Py_DECREF(o);
        }
    } else {
        /* wrapped Array? */
        Array* v;
        if (SWIG_ConvertPtr($input,(void **) &v,
                            $&1_descriptor,0) != -1)
            $1 = 1;
        else
            $1 = 0;
    }
}
%typecheck(QL_TYPECHECK_ARRAY) const Array & {
    /* native sequence? */
    if (PyTuple_Check($input) || PyList_Check($input)) {
        Size size = PySequence_Size($input);
        if (size == 0) {
            $1 = 1;
        } else {
            PyObject* o = PySequence_GetItem($input,0);
            if (PyNumber_Check(o))
                $1 = 1;
            else
                $1 = 0;
            Py_DECREF(o);
        }
    } else {
        /* wrapped Array? */
        Array* v;
        if (SWIG_ConvertPtr($input,(void **) &v,
                            $1_descriptor,0) != -1)
            $1 = 1;
        else
            $1 = 0;
    }
}

%typemap(in) Matrix (Matrix* m) {
    if (PyTuple_Check($input) || PyList_Check($input)) {
        Size rows, cols;
        rows = (PyTuple_Check($input) ?
                PyTuple_Size($input) :
                PyList_Size($input));
        if (rows > 0) {
            // look ahead
            PyObject* o = PySequence_GetItem($input,0);
            if (PyTuple_Check(o) || PyList_Check(o)) {
                cols = (PyTuple_Check(o) ?
                        PyTuple_Size(o) :
                        PyList_Size(o));
                Py_DECREF(o);
            } else {
                PyErr_SetString(PyExc_TypeError, "Matrix expected");
                Py_DECREF(o);
                return NULL;
            }
        } else {
            cols = 0;
        }
        $1 = Matrix(rows,cols);
        for (Size i=0; i<rows; i++) {
            PyObject* o = PySequence_GetItem($input,i);
            if (PyTuple_Check(o) || PyList_Check(o)) {
                Size items = (PyTuple_Check(o) ?
                                        PyTuple_Size(o) :
                                        PyList_Size(o));
                if (items != cols) {
                    PyErr_SetString(PyExc_TypeError,
                        "Matrix must have equal-length rows");
                    Py_DECREF(o);
                    return NULL;
                }
                for (Size j=0; j<cols; j++) {
                    PyObject* d = PySequence_GetItem(o,j);
                    if (PyFloat_Check(d)) {
                        $1[i][j] = PyFloat_AsDouble(d);
                        Py_DECREF(d);
                    } else if (PyInt_Check(d)) {
                        $1[i][j] = Real(PyInt_AsLong(d));
                        Py_DECREF(d);
                    } else {
                        PyErr_SetString(PyExc_TypeError,"doubles expected");
                        Py_DECREF(d);
                        Py_DECREF(o);
                        return NULL;
                    }
                }
                Py_DECREF(o);
            } else {
                PyErr_SetString(PyExc_TypeError, "Matrix expected");
                Py_DECREF(o);
                return NULL;
            }
        }
    } else {
        SWIG_ConvertPtr($input,(void **) &m,$&1_descriptor,1);
        $1 = *m;
    }
};
%typemap(in) const Matrix & (Matrix temp) {
    if (PyTuple_Check($input) || PyList_Check($input)) {
        Size rows, cols;
        rows = (PyTuple_Check($input) ?
                PyTuple_Size($input) :
                PyList_Size($input));
        if (rows > 0) {
            // look ahead
            PyObject* o = PySequence_GetItem($input,0);
            if (PyTuple_Check(o) || PyList_Check(o)) {
                cols = (PyTuple_Check(o) ?
                        PyTuple_Size(o) :
                        PyList_Size(o));
                Py_DECREF(o);
            } else {
                PyErr_SetString(PyExc_TypeError, "Matrix expected");
                Py_DECREF(o);
                return NULL;
            }
        } else {
            cols = 0;
        }

        temp = Matrix(rows,cols);
        for (Size i=0; i<rows; i++) {
            PyObject* o = PySequence_GetItem($input,i);
            if (PyTuple_Check(o) || PyList_Check(o)) {
                Size items = (PyTuple_Check(o) ?
                                        PyTuple_Size(o) :
                                        PyList_Size(o));
                if (items != cols) {
                    PyErr_SetString(PyExc_TypeError,
                        "Matrix must have equal-length rows");
                    Py_DECREF(o);
                    return NULL;
                }
                for (Size j=0; j<cols; j++) {
                    PyObject* d = PySequence_GetItem(o,j);
                    if (PyFloat_Check(d)) {
                        temp[i][j] = PyFloat_AsDouble(d);
                        Py_DECREF(d);
                    } else if (PyInt_Check(d)) {
                        temp[i][j] = Real(PyInt_AsLong(d));
                        Py_DECREF(d);
                    } else {
                        PyErr_SetString(PyExc_TypeError,"doubles expected");
                        Py_DECREF(d);
                        Py_DECREF(o);
                        return NULL;
                    }
                }
                Py_DECREF(o);
            } else {
                PyErr_SetString(PyExc_TypeError, "Matrix expected");
                Py_DECREF(o);
                return NULL;
            }
        }
        $1 = &temp;
    } else {
        SWIG_ConvertPtr($input,(void **) &$1,$1_descriptor,1);
    }
};
%typecheck(QL_TYPECHECK_MATRIX) Matrix {
    /* native sequence? */
    if (PyTuple_Check($input) || PyList_Check($input)) {
        $1 = 1;
    /* wrapped Matrix? */
    } else {
        Matrix* m;
        if (SWIG_ConvertPtr($input,(void **) &m,
                            $&1_descriptor,0) != -1)
            $1 = 1;
        else
            $1 = 0;
    }
}
%typecheck(QL_TYPECHECK_MATRIX) const Matrix & {
    /* native sequence? */
    if (PyTuple_Check($input) || PyList_Check($input)) {
        $1 = 1;
    /* wrapped Matrix? */
    } else {
        Matrix* m;
        if (SWIG_ConvertPtr($input,(void **) &m,
                            $1_descriptor,0) != -1)
            $1 = 1;
        else
            $1 = 0;
    }
}
//#endif

class Array {
    //#if defined(SWIGPYTHON) || defined(SWIGRUBY)
    %rename(__len__)   size;
    //#endif
  public:
    Array();
    Array(Size n, Real fill = 0.0);
    Array(const Array&);
    Size size() const;
    %extend {
        std::string __str__() {
            std::ostringstream out;
            out << *self;
            return out.str();
        }
        //#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGR)
        Array __add__(const Array& a) {
            return Array(*self+a);
        }
        Array __sub__(const Array& a) {
            return Array(*self-a);
        }
        Array __mul__(Real a) {
            return Array(*self*a);
        }
        Real __mul__(const Array& a) {
            return QuantLib::DotProduct(*self,a);
        }
        Array __mul__(const Matrix& a) {
            return *self*a;
        }
        Array __div__(Real a) {
            return Array(*self/a);
        }
        //#endif
        //#if defined(SWIGPYTHON)
        Array __rmul__(Real a) {
            return Array(*self*a);
        }
        Array __getslice__(Integer i, Integer j) {
            Integer size_ = static_cast<Integer>(self->size());
            if (i<0)
                i = size_+i;
            if (j<0)
                j = size_+j;
            i = std::max(0,i);
            j = std::min(size_,j);
            Array tmp(j-i);
            std::copy(self->begin()+i,self->begin()+j,tmp.begin());
            return tmp;
        }
        void __setslice__(Integer i, Integer j, const Array& rhs) {
            Integer size_ = static_cast<Integer>(self->size());
            if (i<0)
                i = size_+i;
            if (j<0)
                j = size_+j;
            i = std::max(0,i);
            j = std::min(size_,j);
            QL_ENSURE(static_cast<Integer>(rhs.size()) == j-i,
                      "arrays are not resizable");
            std::copy(rhs.begin(),rhs.end(),self->begin()+i);
        }
        bool __nonzero__() {
            return (self->size() != 0);
        }
        bool __bool__() {
            return (self->size() != 0);
        }
        //#endif
        //#if defined(SWIGPYTHON) || defined(SWIGRUBY)
        Real __getitem__(Integer i) {
            Integer size_ = static_cast<Integer>(self->size());
            if (i>=0 && i<size_) {
                return (*self)[i];
            } else if (i<0 && -i<=size_) {
                return (*self)[size_+i];
            } else {
                throw std::out_of_range("array index out of range");
            }
        }
        void __setitem__(Integer i, Real x) {
            Integer size_ = static_cast<Integer>(self->size());
            if (i>=0 && i<size_) {
                (*self)[i] = x;
            } else if (i<0 && -i<=size_) {
                (*self)[size_+i] = x;
            } else {
                throw std::out_of_range("array index out of range");
            }
        }
        //#endif
    }
};

// 2-D view

%{
typedef QuantLib::LexicographicalView<Array::iterator> DefaultLexicographicalView;
typedef QuantLib::LexicographicalView<Array::iterator>::y_iterator DefaultLexicographicalViewColumn;
%}

//#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGR)
class DefaultLexicographicalViewColumn {
  private:
    // access control - no constructor exported
    DefaultLexicographicalViewColumn();
  public:
    %extend {
        Real __getitem__(Size i) {
            return (*self)[i];
        }
        void __setitem__(Size i, Real x) {
            (*self)[i] = x;
        }
    }
};
//#endif

%rename(LexicographicalView) DefaultLexicographicalView;
class DefaultLexicographicalView {
  public:
    Size xSize() const;
    Size ySize() const;
    %extend {
        DefaultLexicographicalView(Array& a, Size xSize) {
            return new DefaultLexicographicalView(a.begin(),a.end(),xSize);
        }
        std::string __str__() {
            std::ostringstream s;
            for (Size j=0; j<self->ySize(); j++) {
                s << "\n";
                for (Size i=0; i<self->xSize(); i++) {
                    if (i != 0)
                        s << ",";
                    Array::value_type value = (*self)[i][j];
                    s << value;
                }
            }
            s << "\n";
            return s.str();
        }
        //#if defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGR)
        DefaultLexicographicalViewColumn __getitem__(Size i) {
            return (*self)[i];
        }
        //#endif
    }
};

%{
typedef QuantLib::Matrix::row_iterator MatrixRow;
using QuantLib::outerProduct;
using QuantLib::transpose;
using QuantLib::SVD;
%}

//#if defined(SWIGPYTHON) || defined(SWIGRUBY)
class MatrixRow {
  private:
    MatrixRow();
  public:
    %extend {
        Real __getitem__(Size i) {
            return (*self)[i];
        }
        void __setitem__(Size i, Real x) {
            (*self)[i] = x;
        }
    }
};
//#endif

class Matrix {
  public:
    Matrix();
    Matrix(Size rows, Size columns, Real fill = 0.0);
    Matrix(const Matrix&);
    Size rows() const;
    Size columns() const;
    %extend {
        std::string __str__() {
            std::ostringstream out;
            out << *self;
            return out.str();
        }
        //#if defined(SWIGPYTHON) || defined(SWIGRUBY)
        Matrix __add__(const Matrix& m) {
            return *self+m;
        }
        Matrix __sub__(const Matrix& m) {
            return *self-m;
        }
        Matrix __mul__(Real x) {
            return *self*x;
        }
        Array __mul__(const Array& x) {
            return *self*x;
        }
        Matrix __mul__(const Matrix& x) {
            return *self*x;
        }
        Matrix __div__(Real x) {
            return *self/x;
        }
        //#endif
        //#if defined(SWIGPYTHON) || defined(SWIGRUBY)
        MatrixRow __getitem__(Size i) {
            return (*self)[i];
        }
        //#endif
        //#if defined(SWIGPYTHON)
        Matrix __rmul__(Real x) {
            return x*(*self);
        }
        Array __rmul__(const Array& x) {
            return x*(*self);
        }
        Matrix __rmul__(const Matrix& x) {
            return x*(*self);
        }
        //#endif
    }
};

// functions

%{
using QuantLib::pseudoSqrt;
using QuantLib::SalvagingAlgorithm;
%}

struct SalvagingAlgorithm {
    //#if defined(SWIGPYTHON)
    %rename(NoAlgorithm) None;
    //#endif
    enum Type { None, Spectral };
};

Matrix transpose(const Matrix& m);
Matrix outerProduct(const Array& v1, const Array& v2);
Matrix pseudoSqrt(const Matrix& m, SalvagingAlgorithm::Type a);

class SVD {
  public:
    SVD(const Matrix&);
    const Matrix& U() const;
    const Matrix& V() const;
    Matrix S() const;
    const Array& singularValues() const;
};

#endif
  • setup.py
"""
setup.py file for QuantLibEx
"""

from distutils.core import setup, Extension

qlx_module = Extension(
    name='QuantLibEx._QuantLibEx',
    sources=['QuantLibEx/qlx_wrap.cpp'],
    include_dirs=['/usr/include/ql'], # QuantLib 头文件所在的目录
    library_dirs=['/usr/lib/'],       # QuantLib 库所在的目录
    libraries=['QuantLib']            # QuantLib 库的名字
    )

setup(
    name        = 'QuantLibEx',
    version     = '0.1',
    author      = "xrl",
    description = "Python bindings for the QuantLibEx library",
    ext_modules = [qlx_module],
    py_modules  = ['QuantLibEx.__init__','QuantLibEx.QuantLibEx'])
  • __init__.py
import sys
if sys.version_info.major >= 3:
    from .QuantLibEx import *
    from .QuantLibEx import _QuantLibEx
else:
    from QuantLibEx import *
    from QuantLibEx import _QuantLibEx
del sys

__author__ = 'xrl'

if hasattr(_QuantLibEx,'__version__'):
    __version__ = _QuantLibEx.__version__
elif hasattr(_QuantLibEx.cvar,'__version__'):
    __version__ = _QuantLibEx.cvar.__version__
else:
    print('Could not find __version__ attribute')

if hasattr(_QuantLibEx,'__hexversion__'):
    __hexversion__ = _QuantLibEx.__hexversion__
elif hasattr(_QuantLibEx.cvar,'__hexversion__'):
    __hexversion__ = _QuantLibEx.cvar.__hexversion__
else:
    print('Could not find __hexversion__ attribute')

__license__ = """
QuantLibEx ...
"""

おすすめ

転載: www.cnblogs.com/xuruilong100/p/12051908.html