[MATLAB]金字塔扩展公式DLL与MATLAB交互

Posted fonjames

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[MATLAB]金字塔扩展公式DLL与MATLAB交互相关的知识,希望对你有一定的参考价值。

任务说明:

某塔的PEL里提供了许多的函数,但是也会存在某些情况下需要自行扩展的情况,某塔提供了集中扩展的方式,其中一种是使用DLL公式(VC的DLL编程)进行扩展,方便整合原有的公式。

而matlab里面提供了许多的信号,序列等处理方法,可以很方便的进行一些策略,计算等等。

现在需要使用matlab的自定函数(M函数)对金字塔的函数进行扩展。

前期调查:

VC与MATLAB交互的几种方式,见前篇:http://blog.csdn.net/fonjames/article/details/51554385

首先Matlab引擎(Engine)的方法据说效率比较低下,不推荐,依次尝试了 C++ shared library --> com组件 --> Matlab coder 的方式。

某塔中要求的DLL方式,参照某塔提供的 “栗子”项目FmlDevelope  位于   ...\\WeiSoft所在目录\\fmldevelop.zip

自己生成的dll放于   ...\\WeiSoft所在目录\\FmlDLL    

然后在某塔的公式编辑器里  使用  “mydll@myfun"(arg1,arg2)   即可,注意双引号是必须存在的。

/*
///
xxx塔“C语言接口”扩展程序调用接口规范V1.0
1.扩展函数可用于实现系统公式函数不能实现的特殊算法.
2.扩展函数用windows 32位动态链接库实现,建议使用Microsoft Visual C++编程.
3.调用时在公式编辑器中书写"动态库名称@函数名称"(参数表)即可,例如下面函数可以写为"STOCKFUNC@MYMACLOSE"(5)
4.动态链接库名称和函数名称可以自己定义.
5.使用时必须将动态库文件放置在与*.stk文档相同目录下使用.  //原文错误,应该是fmldll目录
6.请注意所运行xx塔的版本,如果是x64位版本,请将DLL编译为64位版本环境下才能正常运行。

从xxx塔的2.34版后,接口支持逐K线模式调用,增加RUNMODE系统函数,用于告知调用的公式系统本接口的运行模式。
xxx塔的公式系统运行模式分序列模式和逐K线模式,序列模式模式整个公式系统解释时只会调用一次本接口,传递和
返回序列参数数据到接口,而逐K线模式会在解释时每个K线都调用本接口,传递和返回也都是单值数据。
传统的接口是设计在序列模式下运行的,虽然在逐K线模式下xxx塔也可以调用运行传统的接口,但是这是效率很低并且是不
稳定的,因此如果需要在逐K线模式下使用接口,请使用此种专用模式。
*//*//调用接口信息数据结构

typedef struct tagCALCINFO{ ... } CALCINFO; 
注1: 
	1.函数调用参数由m_pfParam1--m_pfParam4带入,若为NULL则表示该参数无效.
	2.当一个参数无效时,则其后的所有参数均无效.
		如:m_pfParam2为NULL,则m_pfParam3,m_pfParam4也为NULL.
	3.参数1可以是常数参数或序列数参数,其余参数只能为常数参数.
	4.若m_nParam1Start<0, 则参数1为常数参数,参数等于*m_pfParam1;
	5.若m_nParam1Start>=0,则参数1为序列数参数,m_pfParam1指向一个浮点型数组,
		数组大小为m_nNumData,数据有效范围为 m_nParam1Start 至 m_nNumData-1.
		在时间上m_pData[x] 与 m_pfParam1[x]是一致的
注2: 
	1.该扩展结构使调用参数在技术上可以是无限数目的,且每个参数都为数值序列。
	2.CALCPARAM结构用于带入参数信息和实际数据,m_pCalcParam数组大小为m_nNumParam,数据有效范围为 0 至 m_nNumParam-1.
	3.按参数的顺序,m_pCalcParam[0]为第一个参数的数据,m_pCalcParam[1]为第二个参数的数据...,为了保持兼容,原m_nParam1Start、m_pfParam1等5个属性依然有赋值。
	4.取用m_pCalcParam[i].m_pfParam,数组大小为m_nNumData,数据有效范围为m_pCalcParam[i].m_nParamStart 至 m_nNumData-1. 若m_pCalcParam[i].m_nParamStart<0, 则此数组中无有效数据。
	5.由于可以调用多个序列,许多序列的计算可以先在公式中进行,然后作为调用的参数即可。
*/
/* 函数输出

__declspec(dllexport) int xxxxxxxx(CALCINFO* pData);
1.函数名称需全部大写.
2.函数必须以上述形式声明,请用实际函数名称替代xxxxxxxx;
	对于C++程序还需包括在 extern "C" {   } 括号中.
3.函数计算结果用pData->m_pResultBuf带回.
4.函数返回-1表示错误或全部数据无效,对于序列模式返回第一个有效值位置,即:
	m_pResultBuf[返回值] -- m_pResultBuf[m_nNumData-1]间为有效值.逐K线模式返回值大于等于0均表示成功
*/
//DLL公式的运行模式,系统系统调用该DLL时,告知公式系统该DLL公式运行在何种模式下
//返回值:	  0本DLL运行序列模式 1本DLL运行逐周期模式
__declspec(dllexport) int WINAPI RUNMODE();
//示例函数,使用时用实际名称替换  
__declspec(dllexport) int WINAPI MYMAVAR(CALCINFO* pData)

例子中的实现

 //计算均价,2个参数,参数1为待求均线的数据,参数2表示计算周期
//调用方法: "STOCKFUNC@MYMAVAR"(CLOSE-OPEN,5)
__declspec(dllexport) int WINAPI MYMAVAR(CALCINFO* pData)//对于逐K线模式,的处理方式的示范代码
{	if(pData->m_pfParam1 && pData->m_pfParam2)
	{	//对于逐K线模式,由于传递数据都是数值,因此需要一个数组用来保存传递过来的参数,用来计算.
		//本例只是简单演示这个用法,如果用户在公式多次调用了接口,则会出现重复使用该变量导致计算出错
		//因此要根据情况做几个这种全局静态变量用于保存各种数据。
		static std::vector<double> arMaData;		
		//第一个周期初始化数据
		if(pData->m_dwBarpos == 0)		{ arMaData.clear(); }
		double dbData = *pData->m_pfParam1;
		//防止使用仅刷最后K线的反复刷新问题
		if(arMaData.size() >= pData->m_nNumData)  arMaData[arMaData.size()-1] = dbData; //仅仅更新最后一个数据
		else			arMaData.push_back(dbData);
		DWORD dwCyc = (DWORD) *pData->m_pfParam2;		
		if(pData->m_dwBarpos < dwCyc-1)
		{	/*对于未到计算周期,返回无效数据*/	return -1;		}
		//先累加
		float fAdd = 0;
		for(DWORD i = pData->m_dwBarpos-(dwCyc-1); i <= pData->m_dwBarpos; i++)
		{			fAdd += arMaData[i];		}
		*pData->m_pResultBuf = fAdd / dwCyc;
	}
	return 1;*/
}

生成matlab的共享dll