逐行和逐根
目录 |
序列
要理解什么是逐行和逐根,首先要理解什么是“序列”。
在多数股软里,对于每个品种,K线是分析的基础对象,而很多根K线就组成了所谓的“序列”。 一根K线实际上是由开高低收量额组成的,所以也就有对应的close,open,high,low,vol,amount等五个内置序列。
序列是很特别的一类数据。它跟数组很相像:每个序列都由多个元素组成,可以通过下标访问。
序列跟数组的区别: 数组在声明时已经定义好元素数量,之后不会改变;而序列在声明时并不指明元素数量。它的数量由K线数量决定,随着行情进行,K线不断增加,序列也相应的自动增加,并且是一一对应。
序列的下标:在星语言中,序列下标0代表最近的一根K线所对应的序列数据;下标1代表前一根K线所对应的数据。
序列计算引擎
那么,在看过系统中的一些公式指标实例之后,稍有传统语言编程经验的人都会立刻产生一个疑问。
那就是,在这些指标公式里,序列并不通过下标直接使用。
例如这样的一句:
a1: close - open;
这句话所起的作用是,计算开盘价减去收盘价的值。并且是对于每根K线,a1都会得到一个对应的值。a1也是序列。
既然序列是数组,为什么可以不通过下标就直接使用? 根据传统编程经验,要得到数组中每一个元素的值,必须写一个循环,计算每个元素,产生新的结果。
例如这样:
for i=1 to sizeof( close ) do begin a1[i] := close[i] - open[i]; end;
为什么在指标中,可以不写这个循环呢?
答案是:指标引擎在背后默默的帮我们做了这份工作。
在股票类数据运算中,序列用得太多,太频繁,如果指标引擎不替用户做这份循环计算工作的话,那么用户编写程序的时候,将会非常的麻烦。 任何一个简单的操作,都要写上一大堆的循环。 有心人可以去观摩一个股软metaTrader的指标。metaTrader的内置语言是不替用户做序列循环计算的。 实现相同功能,它的源码要比其他的股软长的多 举个简单例子,macd,在metaTrader里面要写这么多代码:
//+------------------------------------------------------------------+ //| Custom MACD.mq4 | //| Copyright ?2004, MetaQuotes Software Corp. | //| http://www.metaquotes.net/ | //+------------------------------------------------------------------+ #property copyright "Copyright ?2004, MetaQuotes Software Corp." #property link "http://www.metaquotes.net/" //---- indicator settings #property indicator_separate_window #property indicator_buffers 3 #property indicator_color1 Silver #property indicator_color2 Red #property indicator_color3 Green #property indicator_width1 2 //---- indicator parameters extern int FastEMA=12; extern int SlowEMA=26; extern int SignalSMA=9; //---- indicator buffers double DiffBuffer[]; double MacdBuffer[]; double SignalBuffer[]; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { //---- drawing settings //SetIndexStyle(0,DRAW_HISTOGRAM); SetIndexStyle( 0, DRAW_LINE ); SetIndexStyle(1,DRAW_LINE); SetIndexStyle( 2, DRAW_HISTOGRAM); SetIndexDrawBegin(1,SignalSMA); IndicatorDigits(Digits+1); //---- indicator buffers mapping //SetIndexBuffer(0,MacdBuffer); SetIndexBuffer(0,DiffBuffer); SetIndexBuffer(1,SignalBuffer); SetIndexBuffer(2,MacdBuffer); //---- name for DataWindow and indicator subwindow label IndicatorShortName("MACD("+FastEMA+","+SlowEMA+","+SignalSMA+")@@#"); //SetIndexLabel(0,"MACD"); //SetIndexLabel(1,"Signal"); SetIndexLabel(0,"Diff"); SetIndexLabel(1,"Dea"); SetIndexLabel(2,"MACD"); //---- initialization done return(0); } //+------------------------------------------------------------------+ //| *****Moving Averages Convergence/Divergence ***** | //| DIFF : EMA(CLOSE,S) - EMA(CLOSE,P); | //| DEA : EMA(DIFF,M); | //| MACD : 2*(DIFF-DEA), COLORSTICK | //+------------------------------------------------------------------+ int start() { int limit; int counted_bars=IndicatorCounted(); //---- last counted bar will be recounted if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; //---- macd counted in the 1-st buffer for(int i=0; i<limit; i++) DiffBuffer[i]=iMA(NULL,0,FastEMA,0,MODE_EMA,PRICE_CLOSE,i)-iMA(NULL,0,SlowEMA,0,MODE_EMA,PRICE_CLOSE,i); //---- signal line counted in the 2-nd buffer for(i=0; i<limit; i++) SignalBuffer[i]=iMAOnArray(DiffBuffer,Bars,SignalSMA,0,MODE_SMA,i); for ( i=0; i<limit; i++ ) MacdBuffer[i] = 2*(DiffBuffer[i]-SignalBuffer[i]); //---- done return(0); } //+------------------------------------------------------------------+
而在支持序列计算的股软里,只需要这几行:
DIFF : EMA(CLOSE,S) - EMA(CLOSE,P); DEA : EMA(DIFF,M); MACD : 2*(DIFF-DEA), COLORSTICK;
逐行和逐根
所谓“逐行模式”和“逐根模式”,就是支持序列的指标引擎在背后帮用户进行循环工作时的两种不同的工作模式。
考察macd指标中的两行语句:
DIFF : EMA(CLOSE,S) - EMA(CLOSE,P); DEA : EMA(DIFF,M);
在逐行模式和逐根模式中,它们有着不同的循环方式。
逐行模式
假设当前有N根K线。
计算过程: 计算diff的第1个元素,计算diff的第2个元素,............计算diff的第N个元素。 计算dea的第1个元素,计算dea的第2个元素,..........计算dea的第N个元素。 当新行情到来
计算diff的第1个元素,计算diff的第2个元素,.....计算diff的第N个元素,计算diff的第N+1个元素。 计算dea的第1个元素,计算dea的第2个元素,.....计算dea的第N个元素,计算dea的第N+1个元素。
逐根模式
计算过程:
计算diff的第1个元素, 计算dea的第1个元素, 计算diff的第2个元素, 计算dea的第2个元素, ............计算diff的第N个元素。 ..........计算dea的第N个元素。
当新行情到来 ............计算diff的第N+1个元素。 ..........计算dea的第N+1个元素。
逐行和逐根的区别
根据上面的解释,我们可以看到其中的区别:
行模式下,每次新行情的到来,指标引擎都要把需要计算的序列从头到尾全部计算一遍。
逐根模式下,每次新行情到来,指标引擎只计算最新一根的值。
逐根和逐行的更多差异
差异一:计算结果 逐行和逐根可能产生不一样的计算结果。 逐行模式,每次计算都对序列中所有元素重新计算,所以,有些情况下,某些以前计算过的值可能被修改。 也就是调用了俗称所谓“未来函数”一族函数的时候。 在这种情况下,不但调用未来函数的该行语句的序列结果会发生改变,后续语句如果用到被影响的变量,那么它们之前的值也都可能因此发生改变。
而对于逐根模式,每次计算都只计算最新一根,所以即使调用了未来函数,那么它也只改变到该函数直接影响的序列,而很可能不会将改变带给下面的计算。
差异二:计算速度 一般来说,逐行计算在K线图第一次打开时,速度要略快于逐根模式。 因为,对于很多指标,一次整行算完的话,作一些算法上的优化会比较方便。 但是,在新行情到来时,逐根计算就非常有优势了;此模式下,只计算最后一根的数值。
在测评模式下,逐根模式的速度优势可以完全的体现出来。
测评相当于一次性渐次灌入成千上万的行情。逐行的话,要对整行重复计算成千上万次,而逐根模式只需要对单根计算这么多次。
整体时间消耗的差别是几十倍上千倍的。
逐行和逐根的适用范围
一般技术指标比较适用逐行模式。尤其是用到一些传统的未来函数时。例如,backset,zig,refx 交易策略指标比较适合逐根模式