用DLL来编写TII指标
关于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=(rates.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<fSMA[i-j]) sdm += fSMA[i-j] - rates[i-j].close; } ar_TII = 100*sdp/(sdp+sdm); } } else { for ( i = rates_count-1; i < rates_total; i++ ) { fSMA=(rates.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<fSMA[i-j]) sdm += fSMA[i-j] - rates[i-j].close; } ar_TII = 100*sdp/(sdp+sdm); } } return(rates_total); } 附注:DLL函数TII元素的赋值,使用了2个循环体,这个代码的目的--是为了更直观的说明2种情况:初次调用指标,和在新tick到来时,指标赋值的不同处理。实际上,完全可以用一个循环体完成上述代码,只需对循环的起点做相应的判断即可...... |
打赏
最新创建圈子
- 新闻EA运行效果图圈 2019-05-05
圈主:admin 帖子:1