阳光飞狐

ycng 发表于 2019-8-11 16:09:40

飞狐交易师 (foxtrader) 连结 DLL 的方法

许多年以前,我曾经在
理想公式区发布了
"
如何用 Foxtrader(飞狐)连结 C++动态程式库 DLL及 80x86Macro Assembly (组合语言)
"

现在更新foxtrader(飞狐交易师)
连结 DLL的方法

foxtrader- - > DLL (C++ and assembly) = ( foxfunc.h + foxfunc.cpp +pow10.asm )
gauss- - > DLL (C++ and assembly) = ( foxfunc.cpp + meigj.asm )
gauss只用到函数参数传递,所以使用新的 c++compiler, 不受影响
foxtrader的 foxfunc.h宣告的结构型态 (struct)在 2004vc++ 6.0 全部有效

也就是这五个结构都能用
typedefstruct tagSTKDATA
typedefunion tagSTKDATAEx
typedefstruct tagSPLITDATA
typedefstruct tagCALCPARAM
typedefstruct tagCALCINFO

自2008年起,vc++ 2008, vc++ 2010, vc++2017 对struct的编译,已经完全 c++化,不再相容于 C
也就是这五个结构中
typedefstruct tagSTKDATA
typedefunion tagSTKDATAEx
typedefstruct tagSPLITDATA
typedefstruct tagCALCPARAM
typedefstruct tagCALCINFO
只有这两个可以用
typedefstruct tagCALCPARAM
typedefstruct tagCALCINFO
值得庆幸的是,下面这个结构的函数参数传递个数可以有无数个
typedefstruct tagCALCPARAM
例如:在 foxtrader中
MA1:=MA(CLOSE,3);
MA2:=MA(CLOSE,6);
MA3:=MA(CLOSE,12);
MA4:=MA(CLOSE,24);
MYBBI1:"MYFUNC2017@MYBBI"(MA1, MA2,MA3,MA4,MA3,MA4,5)*0.95,colorff00ff,linethick3; {2017 vc++ 15.0}
其中MYFUNC2017=MYFUNC2017.dll, MYBBI = MYFUNC2017.dll 中的MYBBI函数,这里 MYBBI函数传递的参数共有 7个
下面这两式计算结果相同
xx:(MA(CLOSE,3)+MA(CLOSE,6)+MA(CLOSE,12),MA(CLOSE,24),MA(CLOSE,12),),MA(CLOSE,24)/6*0.95,color0000ff,linethick2;{foxtrader 自行计算}
MYBBI1:"MYFUNC2017@MYBBI"(MA1, MA2,MA3,MA4,MA3,MA4,6)*0.95,colorff00ff,linethick3; {2017 vc++ 15.0 , dll计算}
其他例子
oooq:="MYFUNC2008good@MYMACLOSE"(c,,c,c,6),colorffffff,linethick5;(---> pow10.asm)
oooq1:"MYFUNC2010@MYMAVAR"(ma(c,5),5),colorgreen,linethick5;
其中pow10.asm里面有很多不同定义或宣告被注解不用,那是因为后来在逐步侦测法修改语码中才发现在foxfunc.cpp主程式中,下面这行错误,也就是新的 compiler不再相容于 C,因此在pow10.asm里面被注解不用的定义或宣告中,有些应该是可以用的
fTotal= pData->m_pData.m_fClose; // @@@@@@@ vc++ 2010 cl.exe 使pData->m_pData.m_fClose错误


////////////////////////////////////////////////////////foxfunc.h
#ifndef__FOXFUNC_H_INCLUDE
#define__FOXFUNC_H_INCLUDE
/*
飞狐交易师“C语言接口”扩展程序调用接口规范V3.0
1.本规范适用于飞狐交易师V3.x公式系统.
2.扩展函数用于实现系统函数不能实现的特殊算法.
3.扩展函数用windows32位动态连接库实现,建议使用MicrosoftVisual C++编程.
4.调用时在公式编辑器中写"动态库名称@函数名称"(参数表)即可,例如下面函数可以写为"FOXFUNC@MYMACLOSE"(5)
5.动态连接库名称和函数名称可以自己定义.
6.使用时必须将动态库拷贝到飞狐交易师安装目录下的FmlDLL子目录下使用.
*/
#ifdef__cplusplus
extern"C"
{
#endif//__cplusplus
///////////////////////////////////////////////////////////////////////////
//分析周期
enumDATA_TYPE
{
TICK_DATA=2,//分笔成交
MIN1_DATA,//1分钟线
MIN5_DATA,//5分钟线
MIN15_DATA,//15分钟线
MIN30_DATA,//30分钟线
MIN60_DATA,//60分钟线
DAY_DATA,//日线
WEEK_DATA,//周线
MONTH_DATA,//月线
YEAR_DATA,//年线
MULTIDAY_DATA,//多日线
MULTIMIN_DATA//多分钟线
};
///////////////////////////////////////////////////////////////////////////
//定义取用股票基本数据的结构 只有 VC++ 6.0 能compile成功使用
typedefstruct tagSTKDATA
{
time_tm_time; //时间,UCT
floatm_fOpen; //开盘 open
floatm_fHigh; //最高 high
floatm_fLow; //最低 low
floatm_fClose; //收盘 close
floatm_fVolume; //成交量 Volume
floatm_fAmount; //成交额 amount
WORDm_wAdvance; //上涨家数 仅大盘有效
WORDm_wDecline; //下跌家数 仅大盘有效
}STKDATA;
定义STKDATA为 tagSTKDATA的简单别名,STKDATA
为真正方便使用名称,tagSTKDATA 为定目的的过水名称
////////////////////////////////////////////////////////////////////////////
//扩展数据,用于定义取用分笔成交数据的买卖盘 的结构
typedefunion tagSTKDATAEx
{
struct
{
floatm_fBuyPrice; //买1--买3价floatm_fOpen; //开盘 open
floatm_fHigh; //最高 high
floatm_fLow; //最低 low
floatm_fClose; //收盘 close
floatm_fVolume; //成交量 Volume
floatm_fAmount; //成交额 amount
floatm_fBuyVol; //买1--买3量
floatm_fSellPrice; //卖1--卖3价
floatm_fSellVol; //卖1--卖3量
};
floatm_fDataEx;
}STKDATAEx;
////////////////////////////////////////////////////////////////////////////
//定义取用除权数据的结构
typedefstruct tagSPLITDATA
{
time_tm_time; //时间,UCT
floatm_fHg; //红股
floatm_fPg; //配股
floatm_fPgj; //配股价
floatm_fHl; //红利
}SPLITDATA;
/////////////////////////////////////////////////////////////////////////////
/*财务数据顺序(m_pfFinData内容)
序号内容
0总股本(万股),
1国家股,
2发起人法人股,
3法人股,
4B股,
5H股,
6流通A股,
7职工股,
8A2转配股,
9总资产(千元),
10流动资产,
11固定资产,
12无形资产,
13长期投资,
14流动负债,
15长期负债,
16资本公积金,
17每股公积金,
18股东权益,
19主营收入,
20主营利润,
21其他利润,
22营业利润,
23投资收益,
24补贴收入,
25营业外收支,
26上年损益调整,
27利润总额,
28税后利润,
29净利润,
30未分配利润,
31每股未分配,
32每股收益,
33每股净资产,
34调整每股净资,
35股东权益比,
36净资收益率
*/
/////////////////////////////////////////////////////////////
//定义取用caller函数传递参数项 的结构
typedefstruct tagCALCPARAM
{
union
{
constfloat* m_pfParam; //指向序列参数的址标,指向一个浮点型数组pointertofloat variable parameter / ex. c,h,l,o, co2...co2=(c+o)/2
constfloat m_fParam; //数值参数 valueof parameter
};
constint m_nParamStart; //序列参数有效起始位置thestart address of variable parameter / ex. c,h,l,o,co2.....
}CALCPARAM;
/////////////////////////////////////////////////////////////////////////////
//定义全部取用址标 的总结构 (各指标指向前述各结构以便取的各结构的数据,接口信息数据的结构 )
typedefstruct tagCALCINFO
{
constDWORD m_dwSize; //结构大小
constDWORD m_dwVersion; //调用软件版本(V2.10: 0x210)
constDWORD m_dwSerial; //调用软件序列号
constchar* m_strStkLabel; //股票代码
constBOOL m_bIndex; //大盘
constint m_nNumData; //数据数量(pData,pDataEx,pResultBuf数据数量)数据长度
constSTKDATA* m_pData; //常规数据,注意:当m_nNumData==0时可能为NULL
constSTKDATAEx* m_pDataEx; //扩展数据,分笔成交买卖盘,注意:可能为NULL
constint m_nParam1Start; //参数1有效起始位置<0/ constant parameter >0 /variable parameter
constfloat* m_pfParam1; //调用参数1/pointer to variable parameter 1
constfloat* m_pfParam2; //调用参数2/pointer to variable parameter 2
constfloat* m_pfParam3; //调用参数3/pointer to variable parameter 3
constfloat* m_pfParam4; //调用参数4/pointer to variable parameter 4
float*m_pResultBuf; //结果缓冲区
constDWORD m_dataType; //数据类型
constfloat* m_pfFinData; //财务数据
//以上与分析家兼容,所以沿用其结构和名称
//以下为飞狐交易师扩展(fortagSTKDATAEx)
constDWORD m_dwReserved; // 保留
constint m_nNumParam; // 调用参数数量
constCALCPARAM* m_pCalcParam; // 调用参数数组
constDWORD m_dwReservedEx; // 保留
char*m_strStkName; //股票名称
SPLITDATA*m_pSplitData; //除权数据
intm_nNumSplitData; //除权次数
}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与 m_pfParam1是一致的
注2:(飞狐交易师扩展)
1.该扩展结构使调用参数在技术上可以是无限数目的,且每个参数都可为数值或序列,由公式中实际的调用参数决定。
2.CALCPARAM结构用于带入参数信息和实际数据,m_pCalcParam数组大小为m_nNumParam,数据有效范围为0 至m_nNumParam-1.
3.按参数的顺序,m_pCalcParam为第一个参数的数据,m_pCalcParam为第二个参数的数据...,为了保持兼容,原m_nParam1Start、m_pfParam1等5个属性依然有赋值。
4.若i位置的参数为数值,取用m_pCalcParam.m_fParam.
5.若i位置的参数为序列,取用m_pCalcParam.m_pfParam,数组大小为m_nNumData,数据有效范围为m_pCalcParam.m_nParamStart至 m_nNumData-1.若m_pCalcParam.m_nParamStart<0,则此数组中无有效数据。
6.由于可以调用多个序列,许多序列的计算可以先在公式中进行,然后作为调用的参数即可。
7.经此扩展,对分析家的DLL依然可以调用、兼容。
*/
///////////////////////////////////////////////////////////////////////////////////
/*函数输出
__declspec(dllexport)int xxxxxxxx(CALCINFO* pData);
1.函数名称需全部大写.
2.函数必须以上述形式声明,请用实际函数名称替代xxxxxxxx;
对于C++程序还需包括在extern"C" { } 括号中.
3.函数计算结果用pData->m_pResultBuf带回.
4.函数返回-1表示错误或全部数据无效,否则返回第一个有效值位置,即:
m_pResultBuf[返回值]-- m_pResultBuf间为有效值.
5.函数名称长度不能超过15字节,动态连接库文件名不能超过9字节(不包括扩展名),动态库名称不能叫SYSTEM,EXPLORER
*/
//示例函数,使用时用实际名称替换
__declspec(dllexport)int WINAPI MYMACLOSE(CALCINFO* pData);
__declspec(dllexport)int WINAPI SMOOTH(CALCINFO* pData);
//__declspec(dllexport) int WINAPI MYMAVAR(CALCINFO* pData);
__declspec(dllexport)int WINAPI MYBBI(CALCINFO* pData);
//WINAPI = _stdcall
#ifdef__cplusplus
}
#endif//__cplusplus
#endif//__FOXFUNC_H_INCLUDE

//////////////////////////////////////////comment 注解
__declspec(dllexport)int WINAPI MYMAVAR(CALCINFO* pData)
pData是指向 址标总结构 CALCINFO的 总址标
取用第二个参数数值floatfParam = *pData→m_pfParam2
取用第一个序列参数的址标constfloat* pValue = pData->m_pfParam1;
取用股票数据长度intndata = pData→m_nNumData;
第一个参数存在且为数值pData->m_pfParam1&& pData→m_nParam1Start<0
第一个参数存在且为序列pData->m_pfParam1&& pData→m_nParam1Start>=0
第一个及第二个参数存在且为序列,第三个参数不存在pData->m_pfParam1&& pData->m_pfParam2 && pData->m_nParam1Start>=0&& pData->m_pfParam3==NULL
constfloat* cpParam = pData->m_pfParam1; 定义cpParam为第一个序列参数的址标
取用股票数据结构
pData→m_nNumData= 变数数据长度
pData→m_pData= pointer to struc STKDATA 的址标
pData→m_pData数据结构的第x个数据
pData→m_pData.m_fHigh数据结构的第x个数据中的 High
取用结果缓冲序列
pData->m_pResultBuf
取得第一个序列参数的起始序位,如 2,...5 , . 7...
intnFirst = pData->m_nParam1Start;
for( i = nFirst+nPeriod-1; i < pData->m_nNumData; i++ )
取得第二个数值参数的数值
floatfParam = *pData->m_pfParam2;
intnPeriod = (int)fParam;
取用第一个序列参数的址标constfloat* pValue = pData→m_pfParam1;
取用序列参数的单个直pValue
取用缓冲序列的单个值pData->m_pResultBuf
constCALCPARAM* m_pCalcParam; // 调用参数数组
m_pCalcParam为序列址标,指向各序列参数的指标
第一个序列参数pData→m_pCalcParam
constfloat* m_pfParam; //指向序列参数的址标
第一个序列参数的起始序位pData->m_pCalcParam.m_nParamStart
第一个序列参数的址标constfloat* pValue1 = pData→m_pCalcParam.m_pfParam;
取用第一个序列参数的单个直pValue1
第二个序列参数pData→m_pCalcParam
第二个序列参数的起始序位pData->m_pCalcParam.m_nParamStart
第二个序列参数的址标constfloat* pValue1 = pData→m_pCalcParam.m_pfParam;
取用第二个序列参数的单个直pValue2
第三个序列参数pData→m_pCalcParam
第三个序列参数的起始序位pData->m_pCalcParam.m_nParamStart
第三个序列参数的址标constfloat* pValue1 = pData→m_pCalcParam.m_pfParam;
取用第三个序列参数的单个直pValue3
第四个序列参数pData→m_pCalcParam
第四个序列参数的起始序位pData->m_pCalcParam.m_nParamStart
第四个序列参数的址标constfloat* pValue1 = pData→m_pCalcParam.m_pfParam;
取用第四个序列参数的单个直pValue4
如果有四个序列参数,则取用序位最高的那一个序位
if( pData->m_pCalcParam.m_nParamStart >= 0 &&
pData->m_pCalcParam.m_nParamStart>= 0 &&
pData->m_pCalcParam.m_nParamStart>= 0 &&
pData->m_pCalcParam.m_nParamStart>= 0 ) //4个序列都含有效数值
{
//计算返回的序列的第一个有效值位置
intnFirst = pData->m_pCalcParam.m_nParamStart;//已知返回的序列的第一个有效值位置与第4个序列一致
//若不知,则
/*
intnFirst = pData->m_pCalcParam.m_nParamStart;
if( nFirst < pData->m_pCalcParam.m_nParamStart )
nFirst= pData->m_pCalcParam.m_nParamStart;
if( nFirst < pData->m_pCalcParam.m_nParamStart )
nFirst= pData->m_pCalcParam.m_nParamStart;
if( nFirst < pData->m_pCalcParam.m_nParamStart )
nFirst= pData→m_pCalcParam.m_nParamStart;
constfloat* pValue1 = pData->m_pCalcParam.m_pfParam;
constfloat* pValue2 = pData->m_pCalcParam.m_pfParam;
constfloat* pValue3 = pData->m_pCalcParam.m_pfParam;
constfloat* pValue4 = pData->m_pCalcParam.m_pfParam;
//-------------------
floatm_fOpen; //开盘 open
floatm_fHigh; //最高 high
floatm_fLow; //最低 low
floatm_fClose; //收盘 close
floatm_fVolume; //成交量 Volume
floatm_fAmount; //成交额 amount
调用收盘据
pData→m_nNumData= 变数数据长度
pData→m_pData= pointer to struc STKDATA
pData→m_pData第x个数据
pData→m_pData.m_fHigh第x个数据中的 High
@@@@@@@@@@@important !!!!!!!
sinceVC++ 2008, cl.exe will make ‘pData→m_pData.m_fClose’ anerror
so,pass the high,low,open and close just from the function parameter ,that is use ‘ CALCPARAM’ struct
pData->m_pData.m_fOpen// to use open , there is no way in using a varable for calculationoutside foxtrader
pData→m_pData.m_fHighto use high
pData->m_pData.m_fLow
pData->m_pData.m_fClose
m_pData= pointer to struc STKDATA
incalling C++ dll function
m_pDatais passed to pData (CALCINFO* pData . A CALCINFO* type pointer)
touse a single value in variable ‘High’
pData→m_pData.m_fHighto use high
constfloat* m_pfParam1; //调用参数1/pointer to variable parameter 1
constfloat* m_pfParam2; //调用参数2/pointer to variable parameter 2
constfloat* m_pfParam3; //调用参数3/pointer to variable parameter 3
constfloat* m_pfParam4;
m_pfParam1,m_pfParam2, m_pfParam3, m_pfParam4 = pointer to caller function 的参数
pData→m_pfParam1= pointer to 第一个(序列)参数
pData→m_pfParam1= 取用第一个(序列)参数的第x 个值
constfloat* cpParam = pData→m_pfParam1; =定义 cpParam为 pointerto 第一个(序列)参数
cpParam = 取用第一个(序列)参数的第x 个值
m_pResultBuf= 结果缓冲列
pData→m_pResultBuf= pointer to 结果缓冲列
pData→m_pResultBuf = 取用结果缓冲列的第 x个值
//////////////////////////////////////////comment
//////////////////////////////////////////comment 注解
constint m_nParam1Start; //统杅1衄虴宎弇离
constfloat* m_pfParam1; //覃蚚统杅1
constfloat* m_pfParam2; //覃蚚统杅2
constfloat* m_pfParam3; //覃蚚统杅3
constfloat* m_pfParam4; //覃蚚统杅4,parameters must be <= 4
//const float* m_pfParam5; // parameters must be <= 4
//const float* m_pfParam6;
//const float* m_pfParam7;
//const float* m_pfParam8;
//pData->m_pfParam1 && pData->m_pfParam2 &&pData->m_pfParam3 && pData->m_nParam1Start>=0 &&
pData->m_pCalcParam.m_nParamStart>=0&& pData->m_pCalcParam.m_nParamStart>=0
&&pData->m_pCalcParam.m_nParamStart>=0)
{
floatfParam = *pData->m_pfParam4; //pointer ,pData->m_pCalcParam.m_nParamStart >= 0
intnPeriod = (int)fParam; //统杅1
//const float* cpParam = pData->m_pfParam2; // cpParam = pointer to第一个序列参数,cpParam = 取用第一个序列参数的第i 个值
constfloat* cpParam1 =pData->m_pCalcParam.m_pfParam; // cpParam =pointer to 第一个序列参数,cpParam = 取用第一个序列参数的第i 个值
constfloat* cpParam2 =pData->m_pCalcParam.m_pfParam; // cpParam =pointer to 第一个序列参数,cpParam = 取用第一个序列参数的第i 个值
constfloat* cpParam3 =pData->m_pCalcParam.m_pfParam; // cpParam =pointer to 第一个序列参数,cpParam = 取用第一个序列参数的第i 个值//parameters must be <= 4
//const float* cpParam4 =pData->m_pCalcParam.m_pfParam; //cpParam = pointer to 第一个序列参数,cpParam = 取用第一个序列参数的第i 个值
//const float* cpParam5 =pData->m_pCalcParam.m_pfParam; //cpParam = pointer to 第一个序列参数,cpParam = 取用第一个序列参数的第i 个值
//m_pData = const struct pointer to struct STKDATA , pointer to structSTKDATA ,
touse pData→m_pData.m_fClose
pData→m_pData= | 1,2,3 , … , m_nNumParam | time_t m_time;
|1,2,3 , … , m_nNumParam | float m_fOime_t
|1,2,3 , … , m_nNumParam | float m_fHigh;
.. .
|1,2,3 , … , m_nNumParam | WORD m_wDecline;
m_nNumParam= 数据high,close,open,low的长度
touse high:
pData→m_pData.m_fHigh
contentof struct STKDATA
time_tm_time; //时间,UCT
floatm_fOpen; //开盘 open
floatm_fHigh; //最高 high
floatm_fLow; //最低 low
floatm_fClose; //收盘 close
floatm_fVolume; //成交量 Volume
floatm_fAmount; //成交额 amount
WORDm_wAdvance; //上涨家数 仅大盘有效
WORDm_wDecline; //下跌家数 仅大盘有效
调用传递参数及传回结果
调用传递参数
(pData->m_pfParam1 && //参数1有效Param1exists
pData->m_nParam1Start<0&& //参数1为常数
pData->m_pfParam2==NULL) //
localprocedure 定义使用变数
onstfloat* pValue = pData→m_pfParam1; //use constant参数1
intnFirst = pData->m_nParam1Start; //use 参数1效值起始位
floatfParam = *pData->m_pfParam2; //use 参数2
intnPeriod = (int)fParam;
传回结果
fTotal+= pValue;
pData->m_pResultBuf
//////////////////////////////////////////comment
页: [1]
查看完整版本: 飞狐交易师 (foxtrader) 连结 DLL 的方法