经常在处理指标数据时,我们会碰到要采集一批数据,然后新数据来了之后,要在第0个数据更新,原来第0个到第N-1个数据ArrayCopy到第1到N个。这意味着总有内存读写操作,尽管CPU很快。
之前曾想如果形成环形数组,首尾相连,新来的数据不再存放在第0个位置,而是最后一个位置,同时用一个指针指向这个位置,下次新数据来时,转移到最老的N-1的位置。
后来发现这个想法在各个算法书里早有了,今天尝试把FX Pro Bot进行改写成功了,积累的经验如下。
首先,FX Pro Bot需要2个环形数组,一个是5元素的fast,一个是250元素的slow,我定义一个结构体,
struct LPA//环形数组
{
int id;
double data[];
double sum;
};
LPA fa,sa;
其中,id当做指针,总是指向环形数组的尾巴,data[]用来存储数据,是个动态的,sum是我们要根据这个环形数组后续处理的计算值,这里是计算累加值。
ArrayResize(fa.data,Favg); ArrayResize(sa.data,Savg);
通过ArrayResize限定结构体内部data成不同的元素个数,这种搞法居然也有效。
经过研究发现,在OnTick()主体里面不能搞太复杂,所以有必要在OnInit()里进行一次5元素和250元素的全面计算,这样只需要一次运算就ok了,避免在OnTick()主体里反复运算。
fa.id=Favg;sa.id=Savg;
fa.sum=0.0;sa.sum=0.0;
int i;
for(i = 0; i <Favg; i++)
{
fa.data[i]= Close[1+i] - Open[1+i];
fa.sum += fa.data[i];
}
for(i = 0; i <Savg; i++)
{
sa.data[i]= MathAbs(Close[1+i+Offs] - Open[1+i+Offs]);
sa.sum += sa.data[i];
}
bt=Time[1];
其中,fa.id和sa.id要赋值大数而不是0,这是因为,在初始化中,是按0,1,2...N这样顺序赋值的(符合MT4的时间序列),在后面的EA主体里面,则是按倒序方式。
另外通过bt=Time[1];完成与后面主体的隔离,避免衔接错误。
下面在主体OnTick()里面就相当简单了,全是加减法操作,不涉及乘除法了,所以算法效率提升可不是一点点儿。
if(Time[1] != bt)
{
bt = Time[1];
fa.id--;//新值要赋值给环形数组的尾巴
if(fa.id<0)fa.id += Favg;//如果减过头了,重新开始
fa.sum -= fa.data[fa.id];//先减
fa.data[fa.id] = Close[1] - Open[1];//更新新值
fa.sum += fa.data[fa.id];//后加,至此新值计算完毕
//---慢速计算同理
sa.id--;
if(sa.id<0)sa.id += Savg;
sa.sum -= sa.data[sa.id];
sa.data[sa.id] = MathAbs(Close[1+ Offs] - Open[1+ Offs]);
sa.sum += sa.data[sa.id];
//---最后获取最终结果
cA = (fa.sum/Favg)/(sa.sum/Savg);
Print("cA=",DoubleToStr(cA,2));
}
微信公众号:天泓评测

发表评论