中海新能源:MT4编程:用DLL来编写TII指标

来源:百度文库 编辑:偶看新闻 时间:2024/03/29 01:35:27
MT4编程:用DLL来编写TII指标2011-01-28 11:47

关于TII指标--趋势强度指数,Overview:

The trend intensity index (TII), developed by M.H. Pee, is used to indicate the strength of a current trend in the market. It was introduced in the June 2002 issue of TASC.TII determines the current strength of a price trend based on deviations of previous prices from a current moving average.The stronger the current trend, the more likely the market will continue moving in its current direction instead of changing course.According to M.H. Pee, values >80 and <20 indicate strong trends.

俺现在定义的TII(n)的算法是:

MA1:= SMA(CLOSE,2*n,1);
SDP1:= SUM(IF(CLOSE-MA1>0, CLOSE-MA1,0),n);
SDM1:= SUM(IF(MA1-CLOSE>0, MA1-CLOSE,0),n);

TII:  (SDP1/(SDP1 + SDM1))* 100;

如何在MT4上编写指标,需要了解MT4编程的一些概念:
●    第一个概念就是start(),它是一切程序的入口。
      对于custom indicator–每次start()的调用(程序的进入)发生在:客户端打开的时候;当指标加载到图表的时候;每一个新tick形成的时候。也就是说,你的电脑并没有存储任何与指标相关的数据,你每次开机或重新加载该指标(即调用该程序)的时候,它就会初始化:把已有的历史上所有的柱子(数据)重新算一遍。
      而每次调用start(),系统变量Bars和系统函数IndicatorCounted()就会被赋予新的值。
●    Bars就是图表里柱子的总数,新tick到来时,只要不形成新的柱子,Bars的值维持不变。
●    IndicatorCounted(),则返回自上次start()调用后到目前的那些没有变化的柱子的数量,也就是说:第一次调用start() 时,IndicatorCounted()的值为0;经过一次或多次调用后,IndicatorCounted()的值应该为Bars-1,因为最后一根柱子还在变化中;
      新ticks的到来,分两种情况:一是跨周期而又形成新的柱子,此时IndicatorCounted()的值应该为Bars-2,因为起变化的只有最后2根柱子;另一种情况是服务器传递数据不及时,比如断线重连等等,新增加的可能不只一根的柱子。
一般指标的编程思路:
●    首先考虑:初次调用指标--也就是IndicatorCounted()为0的时候,一次性对指标Buffer赋值;
●    然后考虑:在新tick到来时,都会判断哪些柱子发生了变化,并据此重算和更新指标Buffer的赋值。指标Buffer其实可看成是系列变量或数组,通常情况下--数组前面的元素的值不变--无需重算,新tick到来时--只需赋值给数组后面增加的元素,对应于新增加的柱子。
●    在程序开始部分,我们需要定义指标的属性,以及一些全局变量,包括系列变量的数组和外部参数。

●    mt4用于绘制的数组有数量限制:最多只能8个数组变量,在初始化init()中--通过IndicatorBuffers(n)和SetIndexBuffer来分配;不用来绘制的数组没什么限制(当然你内存要够), 只是需要通过ArrayResize分配内存后--才能使用。而由几个单值所组成的数组,通常作为中间变量,用于储存和交换--来自子程序或DLL的计算数据,如int inter[3]={0, 0, 0},则不需要再分配内存。

DLL相关事项:

●    调用DLL里面的函数,和调用普通子程序的用法差不多,只是程序的开头,必须引入该DLL(如#import "XXXXXXX.dll")并对被引用的函数做一个声明......

●    与DLL相关的指标公式,我编写的习惯:一般都会把需要求值的指标变量(数组)-- 作为参数(函数形参,实际上传递的是一个数组指针)传递给DLL,声明的时候:变量类型后面带有标识符“&”,代码如double&TiiBuffer[];当然,传递给DLL的--通常还有系统提供的Bars和IndicatorCounted(),和行情数据double rates[][6]等等,都作为参数。这样的话,mt4本身的代码很简单,就等DLL函数更新相应的指标变量(数组)就可以了,而有关的算法都在DLL编程里实现。
●    需要注意的是:mq4行情数据传递到DLL后,数组顺序完全相反。mq4行情数组原来的顺序是:从Bars-1到0;而传递到DLL后,数组顺序变为0到Bars-1。

图例:

我喜欢把不同周期参数(5,7,17,31)的四根TII线放在一起,构成一个附图指标

 

附:mt4编程源码

#property copyright "Copyright 2010, Spark.Ho"
#property link      "http://hi.baidu.com/sparkho"
//----
#import "sparkhomt4.dll"
int GetTII(double rates[][6],int ,int ,int ,double& SmaBuffer[],double& TiiBuffer[]);
#import
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Lime
#property indicator_color2 DarkViolet
#property indicator_color3 DarkGoldenrod
#property indicator_color4 Red
//---- input parameters
//---- buffers
double Tii5[];
double Tii7[];
double Tii17[];
double Tii31[];
//---- 自定义数组,
double S5[];
double S7[];
double S17[];
double S31[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   string short_name;  
//---- indicators
   IndicatorBuffers(4);
   SetIndexStyle(0, DRAW_LINE);   
   SetIndexBuffer(0, Tii5);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexBuffer(1, Tii7);
   SetIndexStyle(2, DRAW_LINE,STYLE_SOLID,1);
   SetIndexBuffer(2, Tii17);
   SetIndexStyle(3, DRAW_LINE,STYLE_SOLID,2);
   SetIndexBuffer(3, Tii31);
//---- name for DataWindow and indicator subwindow label
   short_name="SpTii";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"Tii5");
   SetIndexLabel(1,"Tii7");
   SetIndexLabel(2,"Tii17");
   SetIndexLabel(3,"Tii31");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| SPTII indicator system with DLL code                                      |
//+------------------------------------------------------------------+
int start()
  {
   int counted_bars = IndicatorCounted();
   double rates[][6];
   ArrayResize(S5,Bars);
   ArrayResize(S7,Bars);
   ArrayResize(S17,Bars);
   ArrayResize(S31,Bars);   
//----
   if(Bars < 31)
       return(0);
   ArrayCopyRates(rates);
   GetTII(rates,Bars,counted_bars,5,S5,Tii5);
   GetTII(rates,Bars,counted_bars,7,S7,Tii7);
   GetTII(rates,Bars,counted_bars,17,S17,Tii17);
   GetTII(rates,Bars,counted_bars,31,S31,Tii31);
//----
   return(0);
  }
//+------------------------------------------------------------------+

附:DLL源码

MT4_EXPFUNC int __stdcall GetTII(const RateInfo* rates,const int rates_total,const int rates_count,const int nPeriod,double *fSMA,double *ar_TII)
{
    int nP2 = 1;
    double sdp,sdm;
    int i,j;    
    if(rates_count == 0)   // just the first time to enter the pro
    {
        fSMA[0]=rates[0].close;
        for ( i = 1; i < rates_total; i++ )    
        {
            fSMA[i]=(rates[i].close*nP2 + fSMA[i-1]*(nPeriod*2-nP2))/(nPeriod*2);
        }
        for ( i = nPeriod-1; i < rates_total; i++ )    
        {
            sdp = 0.0;
            sdm = 0.0;
            for ( j = 0; j < nPeriod; j++ )         //累加
            {
                if(rates[i-j].close>fSMA[i-j])
                    sdp += rates[i-j].close - fSMA[i-j];
                if(rates[i-j].close                    sdm += fSMA[i-j] - rates[i-j].close;
            }
            ar_TII[i] = 100*sdp/(sdp+sdm);               
        }
    }
    else
    {
        for ( i = rates_count-1; i < rates_total; i++ )    
        {
            fSMA[i]=(rates[i].close*nP2 + fSMA[i-1]*(nPeriod*2-nP2))/(nPeriod*2);
        }
        for ( i = rates_count-1; i < rates_total; i++ )    
        {
            sdp = 0.0;
            sdm = 0.0;
            for ( j = 0; j < nPeriod; j++ )         //累加
            {
                if(rates[i-j].close>fSMA[i-j])
                    sdp += rates[i-j].close - fSMA[i-j];
                if(rates[i-j].close                    sdm += fSMA[i-j] - rates[i-j].close;
            }
            ar_TII[i] = 100*sdp/(sdp+sdm);               
        }
    }
    return(rates_total);
}

附注:DLL函数TII元素的赋值,使用了2个循环体,这个代码的目的--是为了更直观的说明2种情况:初次调用指标,和在新tick到来时,指标赋值的不同处理。实际上,完全可以用一个循环体完成上述代码,只需对循环的起点做相应的判断即可......
类别:编程日志 | 浏览(1209) | 评论 (17)  上一篇:通达信、同花顺看外汇历史分时图    下一篇:编程日志:系统时间与行情时间同... /**/最近读者:xienaizhong你是天使wo是谁ufo_08lggzghuijinshu5212小二来壶竹叶青meteorkong又古又豆 网友评论:1
0perator2011-01-28 23:51 | 回复 3Q有空讲讲SP操盘线 嘿嘿 顺势而为!!!



 2
wangyu2042011-03-19 13:32 | 回复 老大, 你dll是什么软件写的,写好之后放在那个文件下,就可以直接调用了。mt4 可以自己写dll文件么 3
sparkho2011-03-20 17:20 | 回复 回复wangyu204:
DLL是用VC6.0平台写的,编译后放到"MT4\experts\libraries”目录下。 4
wangyu2042011-03-23 16:08 | 回复 我刚刚 用你的代码 调试了 下   没有出现指标图标 ,已经 把 dll 放到MT4\experts\libraries”目录下。   代码没改  我用def 配置的。 cpp里 已经#define MT4_EXPFUNC __declspec(dllexport)     不知道哪里出错了 没有指标数据 5
fxamy2011-04-08 13:52 | 回复 学习了,路过!!跑跑!! 6
sparkho2011-04-09 17:20 | 回复 回复fxamy:THKS 7
sparkho2011-04-09 17:34 | 回复 回复wangyu204:#import "sparkhomt4.dll" 改成相应的文件名? 8
fxamy2011-04-20 11:55 | 回复 MT4调用的DLL里必须用MT4_EXPFUNC定义吗,能不能用其它自定义名呢? 9
fxamy2011-04-20 12:01 | 回复 MT4调用的DLL必须用MT4_EXPFUNC 定义吗,能不能用其它自定义名呢?例如:MT4_EXPFUNC int __stdcall GetTII(const RateInfo* rates,const int rates_total,const int rates_count,const int nPeriod,double *fSMA,double *ar_TII)
是否可以这样写呢?extern "C" __EXPFUNC int __stdcall GetTII(const RateInfo* rates,const int rates_total,const int rates_count,const int nPeriod,double *fSMA,double *ar_TII) 10
sparkho2011-04-21 17:51 | 回复 CPP文件开始部分,有个定义:
#define MT4_EXPFUNC __declspec(dllexport)

你说的方式,我没试过,我的DLL编程:只是在mt4范例中,编辑相应的代码--来获得相应的功能......

 11
fxamy2011-04-25 18:47 | 回复 有一个错误提示D:\C++\sparkhomt4\sparkhomt4.cpp(15) : error C2143: syntax error : missing ',' before '*'
 12
sparkho2011-04-29 22:13 | 回复 回复fxamy:你的sparkhomt4.cpp来自何方?在加入本文代码前,能编译通过吗? 13
sparkho2011-04-29 22:16 | 回复 提示:请先学习mt4的范例,然后在那个代码的基础上,添加自己编写的函数....
祝君顺利...

 14
fxamy2011-05-16 13:22 | 回复 回复sparkho:复制的你的呀,我用的6.0的版本. 15
sparkho2011-06-10 01:36 | 回复 回复fxamy:我的意思是,先编译mt4自带的那个范例,0K后再加插本文代码。 16
caoyukun32011-09-02 18:40 | 回复 为啥我写的dll,一旦带参数,平台就会自动关闭?
 17
sparkho2011-10-25 16:47 | 回复 回复caoyukun3:什么编译平台?