前回に引き続きMT4ネタです。今回はMT4で行列計算用のライブラリを作って動かしてみます。
1から自分で作るのはかなりめんどいのでc++の行列演算ライブラリのeigenをラップしてMT4用のdllファイルを作って、動かそうと思います。
ライブラリ名をmqlmatにして、ライブラリを作成のフォルダ構成を次のようにします。
/mqlmat
    |- mqlmat.cpp
    |- mqlmat.def
    |- Makefile
    |- eigen/
まずはmqlmat.cppからです。MT4のDLL作成についていろいろと書いてくださっている方がおられるのでそちらを参考にしつつ、eigenのラッパーを作っていきます。
#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#include < windows.h >
#include < stdlib.h >
#include < stdio.h >
#include "eigen/Eigen/Dense"
using namespace Eigen;

//---
#define MT4_EXPFUNC __declspec(dllexport)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
  {
//---
   switch(ul_reason_for_call)
     {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
     }
//---
   return(TRUE);
  }

void doublep_to_eigen(MatrixXd& dst,
		      const double *src,
		      int nrow,
		      int ncol)
{
  dst.resize(nrow, ncol);
  for (int i = 0; i < nrow; i++)
    {
      for (int j = 0; j < ncol; j++)
	{
	  dst(i,j) = src[i*ncol+j];
	}
    }
}

void eigen_to_doublep(double *dst,
		      const MatrixXd& src)
{
  for (int i = 0; i < src.rows(); i++)
    {
      for (int j = 0; j < src.cols(); j++)
	{
	  dst[i*src.cols()+j] = src(i, j);
	}
    }
}

//+------------------------------------------------------------------+
//| 行列の掛け算                                                        |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall mqlmat_multiply(const double *amat,
					   const double *bmat,
					   const int    ra,
					   const int    carb,
					   const int    cb,
					   double*      cmat)
{
    MatrixXd a, b, c(ra, cb);
    doublep_to_eigen(a, amat, ra, carb);
    doublep_to_eigen(b, bmat, carb, cb);
    c = a*b;
    eigen_to_doublep(cmat, c);
}

//+------------------------------------------------------------------+
//| 転置行列                                                           |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall mqlmat_trans(const double *mat,
					const int    nrow,
					const int    ncol,
					double*      trmat)
{
    for (int i = 0; i < nrow; i++)
      {
	for (int j = 0; j < ncol; j++)
	  {
	    trmat[j*nrow+i] = mat[i*ncol+j];
	  }
      }
}

//+------------------------------------------------------------------+
//| 行列式                                                            |
//+------------------------------------------------------------------+
MT4_EXPFUNC double __stdcall mqlmat_det(const double *mat,
					const int    n)
{
    MatrixXd m, minv;
    doublep_to_eigen(m, mat, n, n);
    return m.determinant();
}

//+------------------------------------------------------------------+
//| 逆行列                                                            |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall mqlmat_inv(const double *mat,
				      const int    n,
				      double*      inv_mat)
{
    MatrixXd m;
    doublep_to_eigen(m, mat, n, n);
    eigen_to_doublep(inv_mat, m.inverse());
}

//+------------------------------------------------------------------+
//| コレスキー分解                                                      |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall mqlmat_chol(const double *mat,
				       const int    n,
				       double*      lmat)
  {
    MatrixXd m;
    doublep_to_eigen(m, mat, n, n);
    eigen_to_doublep(lmat, m.llt().matrixL());
  }

//+------------------------------------------------------------------+
//| 固有値                                                            |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall mqlmat_eig(const double *mat,
				      const int    n,
				      double*      lmd,
				      double*      pmat)
{
    MatrixXd a;
    doublep_to_eigen(a, mat, n, n);
    SelfAdjointEigenSolver< MatrixXd > es(a);
    eigen_to_doublep(lmd, es.eigenvalues());
    eigen_to_doublep(pmat, es.eigenvectors());
}
次にdefファイルです。
LIBRARY mqlmat

EXPORTS
	mqlmat_multiply  @1
	mqlmat_trans     @2
	mqlmat_det       @3
	mqlmat_inv       @4
	mqlmat_chol      @5
	mqlmat_eig       @6
最後にMakefile…
TARGETNAME=mqlmat
DEFFILE=mqlmat
OUTDIR=.\chk

ALL : "$(OUTDIR)\$(TARGETNAME).dll"


"$(OUTDIR)" :
    @if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"

CPP_PROJ=\
	/MT\
	/W4\
	/Fo"$(OUTDIR)\\"\
	/Fd"$(OUTDIR)\\"\
	/c

LINK32=link.exe

LINK32_FLAGS=\
	advapi32.lib\
	/subsystem:windows\
	/pdb:"$(OUTDIR)\$(TARGETNAME).pdb"\
	/debug\
	/RELEASE\
	/out:"$(OUTDIR)\$(TARGETNAME).dll"\
	/DLL\
	/DEF:$(DEFFILE).def

LINK32_OBJS= \
	"$(OUTDIR)\$(TARGETNAME).obj"


"$(OUTDIR)\$(TARGETNAME).dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
    $(LINK32) $(LINK32_FLAGS) $(LINK32_OBJS)


.cpp{$(OUTDIR)}.obj:
   $(CPP) $(CPP_PROJ) $< 
これで準備完了です。コマンドプロンプトでnmakeとうつとchkフォルダの中にmqlmat.dllというファイルができるのでこれをMT4のlibrariesフォルダに移します。次にmqlmat.mqhとテストプログラムのmqlmat_test.mq4を用意します。
mqlmat.mqh
#import "mqlmat.dll"
void mqlmat_multiply(double amat[], double bmat[],
		     int ra, int carb, int cb,
		     double& cmat[]);
void mqlmat_trans(double mat[],
		  int nrow, int ncol,
		  double& trmat[]);
double mqlmat_det(double mat[],
		  int    n);
void mqlmat_inv(double mat[],
		int    n,
		double& inv_mat[]);
void mqlmat_chol(double mat[],
		 int    n,
		 double& lmat[]);
void mqlmat_eig(double  mat[],
		int     n,
		double&      lmd[],
		double&      pmat[]);
#import
mqlmat_test.mq4
#include < mqlmat.mqh >

int start()
  {
    double mat[4] = {1.0, 2.0, 3.0, 4.0};
    double inv_mat[4];
    double ans[4];
    double eigval[2];
    double eigvec[2];
    double det = mqlmat_det(mat, 2);
    /* 逆行列の計算 */
    mqlmat_inv(mat, 2, inv_mat);
    /* 掛け算 */
    mqlmat_multiply(mat, inv_mat, 2, 2, 2, ans);
    /* 固有値計算 */
    mqlmat_eig(mat, 2, eigval, eigvec);
    Print("det:" + det);
    Print("m*inv(m):" + ans[0] + ", " + ans[1] + ", " + ans[2] + ", " + ans[3]);
    Print("eigval:" + eigval[0] + ", " + eigval[1]);
  }
これを実行してみると…、結果がちゃんと返って来ました!
これでMT4で行列演算ができますね。
作成したdllファイル等はこちらに置いてあります。-->> mqlmat