国庆奉献:简单支持大智慧公式dll接口

Discussion in '强者博弈证券期货自动交易系统' started by yzwyq, Sep 20, 2009.

  1. 国庆奉献:简单支持大智慧公式dll接口


    这次源自客户定制需要,考虑再三,决定支持大智慧公式dll接口

    大智慧公式dll语言规约和分析家一样.

    算是给大家的国庆节礼物

    调用大智慧/分析家公式dll接口函数

    在调用函数之前要创建缓冲区,并从对应历史数据接口填充k线数据
    这个与历史数据接口对应的缓冲区,数据长度固定为480,配有10个输入输出缓冲区,
    用作调用dll具体公式函数是时输入输出缓冲区

    XDll_Free(Dll相对路径文件名);//释放动态链接库
    XDll_Load(Dll相对路径文件名);//加载动态链接库

    功能:释放或加载动态链接库

    参数:Dll相对路径文件名

    例如:XDll_Load("autop\qml\xxxxx.dll");

    XDll_Exec(Dll相对路径文件名,
    函数名,K线缓冲区序号,输出缓冲区序号,
    参数1有效位置,参数1,参数2,参数3,参数4);//调用库函数

    功能:调用库函数

    参数:

    1.Dll相对路径文件名
    2.函数名(dll完全出口函数名,例如在大智慧中是macd,一般完全函数名是_macd)
    3.K线缓冲区序号 指的是与历史数据库接口相对应k线数据缓冲区的序号0,1,2
    4.输出缓冲区序号(可省) 指定调用库函数的输出缓冲区的序号,为0--9(可以是10个输入输出缓冲区中的任何一个)
    默认为0
    5.参数1有效位置(可省) 当有参数1时设定参数1的性质,<0时指定参数1是常数输入,这时参数1就是输入数据
    当其>=0时,参数1就是选定做输入缓冲区的输入输出缓冲区序号,在库函数调用前一定要设置好预定数据
    本参数值指定该系列输入数据的有效起始位置
    6.参数1  输入参数,当其明确输入时,与上一参数配合,省略时,库函数调用输入参数为空
    6.参数2,参数3,参数4 输入参数,当其明确输入时,将作为库函数调用参数,省略时,库函数对应调用参数为空


    例如:XDll_Exec("autop\qml\xxxxx.dll","_kxian",0,0);//调用库函数


    XDll_DBufDelete();//删除历史数据接口对应k线数据缓冲区
    XDll_DBufCreate(开始位置,结束位置);//创建历史数据接口对应k线数据缓冲区,并调入数据
    XDll_GetKXData(数据索引,k线数据编号0.t.1.o.2.h.3.l.4.c.5.v);//获取历史数据接口对应k线数据缓冲区数据
    XDll_GetIOData(输入输出数据缓冲区号0..9,数据索引);//获取历史数据接口对应数据缓冲区数据
    XDll_SetIOData(输入输出数据缓冲区号0..9,数据索引,数据);//设置历史数据接口对应数据缓冲区数据
    XDll_CopyIOData(源缓冲区号,目的缓冲区号);//拷贝历史数据接口对应数据缓冲区数据
    XDll_ClearIOData(缓冲区号);//清除历史数据接口对应数据缓冲区数据


    功能:历史数据接口对应k线数据缓冲区操作,具体功能看上面标示

    参数:

    1.开始位置 对应历史数据接口中的数据开始位置
    2.结束位置 对应历史数据接口中的数据结束位置,-1时将直接取值为最后位置
    当开始与结束位置的k线根数大于480时,系统会自动将开始位置裁剪为结束位置-450
    3 数据索引 等同历史数据库接口索引
    4.其他参数同表面意思


    注意:
    XDll_DBufCreate函数可以连续调入,并填入数据,其返回值为新的数据根数
    在程序中可用
    if(XDll_DBufCreate(0,-1))
    {
    XDll_Exec("autop\qml\xxxxx.dll","_kxian",0,0);//调用库函数 //
    .....
    }

    简单测试代码为:

    OpenLsLib("m1005",64,4,0);
    XDll_DBufCreate(0,-1);//创建历史数据接口对应k线数据缓冲区,并调入数据
    XDll_Load("autop\qml\xxxxx.dll");//加载动态链接库
    XDll_Exec("autop\qml\xxxxx.dll","_kxian",0,0);//调用库函数
    ......................

    int m_daya=XDll_GetIOData(0,m_dsp_dir);
     
    Last edited by a moderator: Nov 29, 2010
  2. #ifndef __DzhFUNC_H_INCLUDE
    #define __DzhFUNC_H_INCLUDE

    /*
    ///////////////////////////////////////////////////////////////////////////
    大智慧扩展函数规范V1.10
    1.本规范适用于大智慧1.10标准版和专业版公式系统.
    2.扩展函数用于实现系统函数不能实现的特殊算法.
    3.扩展函数用windows 32位动态连接库实现,建议使用Microsoft Visual C++编程.
    4.调用时在公式编辑器中写"动态库名称@函数名称"(参数表)即可,例如下面函数可以写为"DZHFUNC@MYCMALOSE"(5)
    5.动态连接库名称和函数名称可以自己定义.
    6.使用时可以将动态库拷贝到大智慧目录下使用.
    */

    #ifdef __cplusplus
    extern "C"
    {
    #endif //__cplusplus

    ///////////////////////////////////////////////////////////////////////////
    //分析周期
    enum DATA_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, //月线
    MULTI_DATA //多日线
    };

    ///////////////////////////////////////////////////////////////////////////
    //基本数据

    typedef struct tagSTKDATA
    {
    time_t 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;


    ////////////////////////////////////////////////////////////////////////////
    //扩展数据,用于描述分笔成交数据的买卖盘

    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量
    };
    float m_fDataEx[12]; //保留
    } STKDATAEx;

    /////////////////////////////////////////////////////////////////////////////
    /*财务数据顺序(m_pfFinData内容)

    序号 内容

    0 总股本(万股),
    1 国家股,
    2 发起人法人股,
    3 法人股,
    4 B股,
    5 H股,
    6 流通A股,
    7 职工股,
    8 A2转配股,
    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 净资收益率
    */

    /////////////////////////////////////////////////////////////////////////////
    //函数数据结构

    typedef struct tagCALCINFO
    {
    const DWORD m_dwSize; //结构大小
    const DWORD m_dwVersion; //调用软件版本(V2.10 : 0x210)
    const DWORD m_dwSerial; //调用软件序列号
    const char* m_strStkLabel; //股票代码
    const BOOL m_bIndex; //大盘

    const int m_nNumData; //数据数量(pData,pDataEx,pResultBuf数据数量)
    const STKDATA* m_pData; //常规数据,注意:当m_nNumData==0时可能为 NULL
    const STKDATAEx* m_pDataEx; //扩展数据,分笔成交买卖盘,注意:可能为 NULL

    const int m_nParam1Start; //参数1有效位置
    const float* m_pfParam1; //调用参数1
    const float* m_pfParam2; //调用参数2
    const float* m_pfParam3; //调用参数3
    const float* m_pfParam4; //调用参数3

    float* m_pResultBuf; //结果缓冲区
    const DATA_TYPE m_dataType; //数据类型
    const float* m_pfFinData; //财务数据
    } CALCINFO;

    /*
    注:
    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.
    在时间上m_pData[x] 与 m_pfParam1[x]是一致的
    */


    ///////////////////////////////////////////////////////////////////////////////////
    /* 函数输出

    __declspec(dllexport) int xxxxxxxx(CALCINFO* pData); ---------- A
    __declspec(dllexport) int xxxxxxxxVAR(CALCINDO* pData); ---------- B

    1.函数名称需全部大写.
    2.函数必须以上述A,B两种形式之一声明,请用实际函数名称替代xxxxxxxx;
    对于C++程序还需包括在 extern "C" { } 括号中.
    3.上述形式A用于声明不带参数或全部参数为常数的函数;
    形式B用于声明参数1为序列数的函数;两种函数的区别在于后者以VAR结尾.
    4.函数计算结果用pData->m_pResultBuf带回.
    5.函数返回-1表示错误或全部数据无效,否则返回第一个有效值位置,即:
    m_pResultBuf[返回值] -- m_pResultBuf[m_nNumData-1]间为有效值.
    6.函数名称长度不能超过15字节,动态连接库文件名不能超过9字节(不包括扩展名),动态库名称不能叫SYSTEM,EXPLORER
    7.编译时请请选择1字节对齐

    */

    //示例函数,使用时用实际名称替换
    __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData);
    __declspec(dllexport) int WINAPI MYMAVAR(CALCINFO* pData);

    __declspec(dllexport) int WINAPI MYMACLOSE_CALC_PREV(CALCINFO* pData);
    __declspec(dllexport) int WINAPI MYMAVAR_CALC_PREV(CALCINFO* pData);

    #ifdef __cplusplus
    }
    #endif //__cplusplus


    #endif //__DZHFUNC_H_INCLUDE
     
  3. // FxjFunc.cpp : Defines the entry point for the DLL application.
    //

    #include "stdafx.h"
    #include "FxjFunc.h"

    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;
    }

    //计算收盘价的均价,一个常数参数,表示计算周期
    //调用方法:
    // MYMACLOSE(5)

    __declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData)
    {
    float f,fTotal;
    int nPeriod,i,j;
    if(pData->m_pfParam1 && //参数1有效
    pData->m_nParam1Start<0 && //参数1为常数
    pData->m_pfParam2==NULL) //仅有一个参数
    {
    f = *pData->m_pfParam1;
    nPeriod = (int)f; //参数1
    if(nPeriod>0)
    {
    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 = fTotal/nPeriod; //平均
    }
    return nPeriod-1;
    }
    }
    return -1;
    }

    __declspec(dllexport) int WINAPI MYMACLOSE_CALC_PREV(CALCINFO* pData)
    {
    if(pData->m_pfParam1 && pData->m_nParam1Start<0)
    {
    float f = *pData->m_pfParam1;
    return ((int)f) - 1;
    }
    return 0;
    }

    //计算均价,2个参数,参数1为待求均线的数据,参数2表示计算周期
    //调用方法:
    // MYMAVAR(CLOSE-OPEN,5)

    __declspec(dllexport) int WINAPI MYMAVAR(CALCINFO* pData)
    {
    float f,fTotal;
    const float* pValue;
    int nPeriod,nFirst,i,j;
    if(pData->m_pfParam1 && pData->m_pfParam2 && //参数1,2有效
    pData->m_nParam1Start>=0 && //参数1为序列数
    pData->m_pfParam3==NULL) //有2个参数
    {
    pValue = pData->m_pfParam1; //参数1
    nFirst = pData->m_nParam1Start; //有效值
    f = *pData->m_pfParam2;
    nPeriod = (int)f; //参数2
    if(nFirst>=0 && nPeriod>0)
    {
    for(i=nFirst+nPeriod-1;i<pData->m_nNumData;i++)
    {
    fTotal = 0.0f;
    for(j=0;j<nPeriod;j++) //累加
    fTotal += pData->m_pData[i-j].m_fClose;
    pData->m_pResultBuf = fTotal/nPeriod; //平均
    }
    return nFirst+nPeriod-1;
    }
    }
    return -1;
    }

    __declspec(dllexport) int WINAPI MYMAVAR_CALC_PREV(CALCINFO* pData)
    {
    if(pData->m_pfParam2)
    {
    float f = *pData->m_pfParam2;
    return ((int)f) - 1;
    }
    return 0;
    }
     
  4. 是大智慧的新一代还是经典版?
    谢谢!
     
  5. 应该是新一代,经典版不支持dll的。
     
  6. 大智慧新一代,分析家,和飞狐的公式dll

    飞狐的dll语言规范是分析家的扩展,主要体现在输入参数可以有四个可变参数(类似于参数1).
     
    Last edited by a moderator: Sep 20, 2009
  7. 我又加了个支持四个可变参数的函数,所以飞狐的也支持
     
  8. 楼主观念在改变了,开放些了
     
  9. 请问您是指“大智慧扩展函数规范”吗?这几天我也在研究DLL公式,如果能同大智慧传递多个可变参数就太好了。还请指点一下如何能够传递多个可变参数。谢谢!
     
  10. 参数一般不超过四个.少于四个是可以的.本软件只是调入公式dll.他原来有几个参数就是几个参数.

    公式dll的配置和使用,可以根据实际需要来.假如你多于四个参数,就应当分拆,通过生成中间指标来转接.

    再复杂的系统也不难.
     
  11. 谢谢分享