第七节 RdotNet和C#的合并使用
RdotNet是一个使用C#开发的中介引擎,它可以让我们直接在.NET的程序之中与计算机中已安装的R程序互相沟通。亦即,我们可以在C#的程序之中,呼叫R程序帮我们进行运算,然后直接把结果取出,在进行C#下一步的运算。如此,可以补足C#链接库的不足,我们也不需要自行撰写复杂的矩阵与最适化运算程序。
RdotNet在CodePlex的网址为,https://rdotnet.codeplex.com,网站如下图。

圖4.7.1
最新版的RdotNet为1.7.0,读者可以在https://github.com/jmp75/rdotnet取得最新版的Source Code,自行编译。

圖4.7.2
链接库需要使用Visual Studio的Package管理工具NuGet来下载,在搜寻项目输入R.Net便可找到相关项目。

圖4.7.3
原来的网站为https://archive.codeplex.com/?p=rdotnet,旧版链接库已经被移除了。本书的范例是使用RdotNet 1.5.12版,搭配Visual Studio 2010以及R 3.2.0 i386版本。
一、Hello专案
首先,建立一个控制台的新项目,如下图。

圖4.7.4
点选右方方案总管内项目的参考项目,按鼠标右键,选取加入参考。出现下方窗口,在浏览页中,找到下载的RdotNet的DLL链接库,将两者都选取。

圖4.7.5
此时,参考中看到我们加入的两个DLL。

圖4.7.6
输入下面程序代码,编译项目。
#001 using System;
#002 usingSystem.Collections.Generic;
#003 using System.Linq;
#004 using System.Text;
#005
#006 using RDotNet;
#007 using RDotNet.NativeLibrary;
#008
#009 namespace HelloRdotNet
#010 {
#011 class Program
#012 {
#013 staticvoid Main(string[]args)
#014 {
#015 REngineengine = REngine.GetInstance();
#016 // Asomewhat contrived but customary Hello World:
#017 CharacterVectorcharVec1 = engine.CreateCharacterVector(
#018 new[]{ "Hello, R world!, .NET speaking"});
#019 engine.SetSymbol("greetings", charVec1);
#020
#021 // printout in the console
#022 engine.Evaluate("str(greetings)");
#023 string[]a = engine.Evaluate("'Hi there .NET, from theR engine'")
#024 .AsCharacter().ToArray();
#025 Console.WriteLine("R answered: '{0}'", a[0]);
#026 Console.WriteLine("Press any key to exit the program");
#027 Console.ReadKey();
#028
#029 engine.Dispose();
#030 }
#031 }
#032 }
程序行表4.7.1
#006、#007先加入这两个DLL的引用。#015产生中介引擎。#017、#018产生一个字符向量变量charVec1,此字符向量是R对应的数据结构,用来储存字符之用。#019则将此字符向量变量命名为greetings。greetings是R中此字符向量的名称,charVec1则是C#中此字符向量的名称。
#022透过中介引擎,要求R执行str(greetings)此指令,这相当于在R的控制台提示符号'>'后,直接打入指令str(greetings)。这就会在我们前面执行C#执行档后,输出画面的第一行文字,chr "Hello, Rworld!, .NET speaking"。
#023行要求R执行'Hi there .NET, from the R engine',并将输出结果以字符方式取得,再转成数组储存于变量a中。#025将a的内容输出,成为画面的第二行文字,R answered: 'Hi there .NET, from the Rengine'。
执行程序,输出画面如下。

圖4.7.7
二、使用RdotNet计算Cholesky分解
由于R语言有强大的数值运算链接库,如果C#能直接叫用R核心来执行数值运算,那便是一个强大无比的结合体。RdotNet就是这两者的黏合剂。下面的程序便是透过RdotNet呼叫R来进行Cholesky分解。
#001 static void Main(string[]args)
#002 {
#003 REngineengine = REngine.GetInstance();
#004 double[,]Ary_M = new double[2,2];
#005 Ary_M[0, 0] = 1.0; Ary_M[0, 1] = 0.8;
#006 Ary_M[1, 0] = 0.8; Ary_M[1, 1] = 1.0;
#007
#008 NumericMatrixR_M = engine.CreateNumericMatrix(Ary_M);
#009 engine.SetSymbol("M",R_M);
#010
#011 NumericMatrixR_U = engine.Evaluate("chol(M)").AsNumericMatrix();
#012 engine.SetSymbol("U",R_U);
#013 Console.WriteLine("Upper Matrix");
#014 Console.WriteLine("{0}, {1}", R_U[0, 0], R_U[0, 1]);
#015 Console.WriteLine("{0}, {1}", R_U[1, 0], R_U[1, 1]);
#016
#017 NumericMatrixR_L = engine.Evaluate("t(U)").AsNumericMatrix();
#018 engine.SetSymbol("L",R_L);
#019 Console.WriteLine("\nLower Matrix");
#020 Console.WriteLine("{0}, {1}", R_L[0, 0], R_L[0, 1]);
#021 Console.WriteLine("{0}, {1}", R_L[1, 0], R_L[1, 1]);
#022
#023 NumericMatrixR_A = engine.Evaluate("L %*% U").AsNumericMatrix();
#024 double[,]AryA = R_A.ToArray();
#025 Console.WriteLine("\nCorr Matrix");
#026 Console.WriteLine("{0}, {1}", AryA[0, 0], AryA[0, 1]);
#027 Console.WriteLine("{0}, {1}", AryA[1, 0], AryA[1, 1]);
#028
#029 Console.ReadKey();
#030 engine.Dispose();
#031 }
程序行表4.7.2
#003产生中介引擎。#004~#006设定相关系数矩阵。#008产生RdotNet中的数值矩阵变量R_M,#009将R_M指定给R中的变数M。#011呼叫chol()函数执行Cholesky分解,并将结果的上三角矩阵传回给R_U。#012将R_U指定给R中的变数U。#017呼叫t()函数执行矩阵转置,并将结果的下三角矩阵传回给R_L。#018将R_L指定给R中的变数L。#023执行下三角矩阵与上三角矩阵的矩阵相乘,结果传回给R_A。#024将R_A转为C#数据型态。程序执行输出画面如下。
圖4.7.8

通过C#呼叫RdotNet,我们可以把R的所有功能嵌入到我们所撰写的程序之中,这对于金融工程师而言,不异如虎添翼。我们在第二篇将进入Heston的随机波动模型,读者会发现,模型中的数学复杂度是以一个量级的增加。而在模型的参数校准中,非线性最适化是必要的计算。对于一般程序员而言,撰写此类程序不异天方夜谭,然而一旦我们会使用RdotNet,一切却变得轻而易举。这真是令人赞叹的好事一件。



雷达卡





京公网安备 11010802022788号







