飞狐 DLL调用

来自tradeStar帮助系统
(版本间的差异)
跳转到: 导航, 搜索
(以“=DLL接口说明= #扩展函数可用于实现系统公式函数不能实现的特殊算法. #扩展函数用windows 32位动态链接库实现,建议使用Microsoft...”为内容创建页面)

2013年4月11日 (四) 20:54的版本

目录

DLL接口说明

  1. 扩展函数可用于实现系统公式函数不能实现的特殊算法.
  2. 扩展函数用windows 32位动态链接库实现,建议使用Microsoft Visual C++编程.
  3. 调用时在公式编辑器中书写"动态库名称@函数名称"(参数表)即可,例如下面函数"FOXFUNC@MYMACLOSE"(5)
  4. 动态链接库名称和函数名称可以自己定义.
  5. 使用时必须将动态库文件放置在飞狐交易师安装目录下的FmlDLL子目录下使用.

DLL函数格式

DLL名称和函数名称可以自行定义,由于原飞狐公式不区分大小写,DLL的函数名最好使用全大写, 避免某些环境下无法加载,新版本的DLL则无此限制。 下面的例子定义了一个 MYMACLOSE 的函数,函数的实现下面具体分析。

extern "C" __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData)

DLL函数返回值

首先注意上述函数的返回值是int,这个返回值表示在pData的m_pResultBuf里面有效位置的起始位, m_pResultBuf是DLL返回的数值序列的存放位置,0表示从第1位起有效,2表示从第3位起有效, 返回-1表示全部无效,公式将没有输出。m_pResultBuf和CALCINFO的类型下面讲述

DLL的参数类型

DLL的参数是一个结构体CALCINFO的指针,下面是定义

////////////////////////////////////////////////////
//调用接口信息数据结构
////////////////////////////////////////////////////
typedef struct tagCALCINFO
{
	//结构大小
	DWORD m_dwSize;
	//调用软件版本(V3.00 : 0x300)
	DWORD m_dwVersion;
	//调用软件序列号
	DWORD m_dwSerial;
	//软件用户名
	//char* m_strUserName;
	//股票代码
	char* m_strStkLabel;
	//大盘
	BOOL m_bIndex;
	//数据数量(pData,pDataEx,pResultBuf数据数量)
	int m_nNumData;
	//常规数据,注意:当m_nNumData==0时可能为 NULL
	STKDATA* m_pData;
	//扩展数据,分笔成交买卖盘,注意:可能为 NULL
	STKDATAEx* m_pDataEx;
	//参数1有效位置
	int m_nParam1Start;
	//调用参数1
	float*	 m_pfParam1;
	//调用参数2
	float*	 m_pfParam2;
	//调用参数3
	float*	 m_pfParam3;
	//调用参数4
	float*	 m_pfParam4;				
	//结果缓冲区
	float* m_pResultBuf;
	//数据类型
	int m_dataType;
	//财务数据
	float* m_pfFinData;	
	//以上与分析家兼容,所以沿用其结构和名称

	//以下为 FoxTrader 扩展
	// function type
	DWORD m_nFncType;
	// 调用参数数量
	int m_nNumParam;
	// 调用参数数组
	CALCPARAM* m_pCalcParam;
	//扩展结果缓冲区
	float* m_pResultBufExt[8];
	//扩展结果有效位置
	int m_nResultStart[8];
	// 用户数据(102400字节)
	void* m_pUserData;

	//内部函数计算用
	//参数2有效位置
	int m_nParam2Start; 
	//参数3有效位置
	int m_nParam3Start;
	//参数4有效位置
	int m_nParam4Start;			
	//股票名称
	char* m_strStkName;			
	//除权数据
	SPLITDATA* m_pSplitData;			
	//除权次数
	int m_nNumSplitData;		
	//计算当前下标数据
	int m_iCurIndex;			

	void* m_pReserved1;
	void* m_pReserved2;
	void* m_pReserved3;
	void* m_pReserved4;

} CALCINFO;

注意里面的float* m_pResultBuf;就是函数返回数值序列的存放位置,序列的类型是float, 长度是int m_nNumData;

DLL参数传递

传入DLL的参数是CALCINFO结构体里面的m_pfParam1,m_pfParam2,m_pfParam3,m_pfParam4; 最多可传4个序列。当m_pfParam1为NULL时,表示无参数;当m_pfParam1不为空而m_pfParam2为空表示有1个参数; 当m_pfParam1和m_pfParam2不为空但m_pfParam3为空则表示有两个参数,以此类推。 序列的有效起始位是m_nParam1Start,m_nParam2Start,m_nParam3Start,m_nParam4Start, 起始位小于0表示是单值(用 *m_pfParam1 来获取)。起始位大于等于0时,有效数据为: m_pfParam1[m_nParam1Start],m_pfParam1[m_nParam1Start+1],m_pfParam1[m_nParam1Start+2]...m_pfParam1[m_nNumData-1] 第2,3,4条序列也是同样的结构。

基本数据结构

公式调用DLL时会把当前图形上的信息传入DLL,这些信息包括开高低收量额等, 定义在STKDATA* m_pData这个指针里,长度是m_nNumData, STKDATA结构体的定义如下:

////////////////////////////////////////////////////
//基本数据
////////////////////////////////////////////////////
typedef struct tagSTKDATA	
{
	TimeType m_time;		//时间,UCT
	float	m_fOpen;		//开盘
	float	m_fHigh;		//最高
	float	m_fLow;			//最低
	float	m_fClose;		//收盘
	float	m_fVolume;		//成交量(手)
	float	m_fAmount;		//成交额(元)/持仓(未平仓合约,仅期货有效)
	WORD	m_wAdvance;		//上涨家数(仅大盘有效)
	WORD	m_wDecline;		//下跌家数(仅大盘有效)
} STKDATA;

兼容时间格式

注意上述结构的m_time是TimeType类型,老版本的格式是time_t,由于新版本的time_t是64位的,老飞狐是32位, 所有原来time_t的字段,现在都用TimeType来表示。 使用vc6编译dll的,如果需要用到时间的,时间字段是vc6的time_t类型即可 使用vc2008以上版本的,time_t就是__int64,为了兼容老版本的DLL, 需要使用额外定义下面的TimeType类型(实际上就是int,32位的)

#define TimeType int

扩展数据格式

////////////////////////////////////////////////////
//扩展数据,用于描述分笔成交数据的买卖盘
////////////////////////////////////////////////////
typedef union tagSTKDATAEx
{
	struct
	{
		float m_fBuyPrice[3];		//买1--买3价
		float m_fBuyVol[3];			//买1--买3量
		float m_fSellPrice[3];		//卖1--卖3价	
		float m_fSellVol[3];		//卖1--卖3量
		DWORD m_dwToken;			//成交方向
	};
	float m_fDataEx[13];
} STKDATAEx;

除权数据

////////////////////////////////////////////////////
//除权数据
////////////////////////////////////////////////////
typedef struct tagSPLITDATA	
{
	TimeType	m_time;			//时间,UCT
	float		m_fHg;			//红股
	float		m_fPg;			//配股
	float		m_fPgj;			//配股价
	float		m_fHl;			//红利
} SPLITDATA;

扩展调用参数

////////////////////////////////////////////////////
//调用参数项结构
////////////////////////////////////////////////////
typedef struct tagCALCPARAM
{
	union 
	{
		const float m_fParam; //数值参数
		const float* m_pfParam; //序列参数,指向一个浮点型数组	
		const char* m_szParam; //字符串参数
	};
	//序列参数有效起始位置
	const int	m_nParamStart;
}CALCPARAM;

公式调用例子

公式里使用双引号来调用DLL, 例如下面的例子是调用MyDll.dll里面的MYMACLOSE函数,参数是5, 返回值输出成指标线k1。 下一节有建立DLL工程及调用公式的详细例子。

k1:"MyDll@MYMACLOSE"(5);

开发DLL的详细例子

这里例子是使用VS2012制作的,VS2010,VS2008,VC6也类似。

1. 首先创建Win32的工程项目,项目名称是MyDll

Fml dll create project.png

2. 项目设置成DLL

Fml dll project settings.png

3. 把TimeType, STKDATA, STKDATAEx,等等上述数据结构拷贝到MyDll.cpp

Fml dll edit src.png

4. 添加用户函数MYMACLOSE, 计算 N 日均线

//计算收盘价的均价,一个常数参数,表示计算周期
//调用方法:
//	"FOXFUNC@MYMACLOSE"(5)
extern "C" __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData)
{

	if ( pData->m_pfParam1 &&				//参数1有效
		 pData->m_nParam1Start<0 &&			//参数1为常数
		 pData->m_pfParam2==NULL )			//仅有一个参数
	{
		float fParam = *pData->m_pfParam1;
		int nPeriod = (int)fParam;			//参数1
		if(nPeriod>0)
		{
			float fTotal;
			int i, j;
			for ( i = nPeriod-1; i < pData->m_nNumData; i++ )//计算nPeriod周期的均线,数据从nPeriod-1开始有效
			{
				fTotal = 0.0f;
				for ( j = 0; j < nPeriod; j++ )				//累加
					fTotal += pData->m_pData[i-j].m_fClose;
				pData->m_pResultBuf[i] = fTotal/nPeriod;	//平均
			}
			return nPeriod-1;
		}
	}
	return -1;
}

5. 设置项目的输出路径为软件安装目录下的 FmlDll 下,输出名称为 MyDll.dll。 这一步可以省略,编译后手动拷贝dll到软件的FmlDll目录也可以

Fml dll linker output.png

6. 编译后,直接运行软件,或者在Debugging调试Command处添加软件的启动路径

7. 创建公式 测试DLL,并编译

Fml dll create fml.png

8. 拖放到图上运行

Fml dll run dll.png

示例DLL工程文件下载

个人工具
名字空间

变换
操作
导航
工具箱