用DLL来编写TII指标

楼主  收藏   举报   帖子创建时间:  2019-05-05 05:45 回复:0 关注量:252
关于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到来时,指标赋值的不同处理。实际上,完全可以用一个循环体完成上述代码,只需对循环的起点做相应的判断即可......
打赏