逐行和逐根

来自tradeStar帮助系统
跳转到: 导航, 搜索

目录

序列

要理解什么是逐行和逐根,首先要理解什么是“序列”。

在多数股软里,对于每个品种,K线是分析的基础对象,而很多根K线就组成了所谓的“序列”。 一根K线实际上是由开高低收量额组成的,所以也就有对应的close,open,high,low,vol,amount等五个内置序列。

序列是很特别的一类数据。它跟数组很相像:每个序列都由多个元素组成,可以通过下标访问。

序列跟数组的区别: 数组在声明时已经定义好元素数量,之后不会改变;而序列在声明时并不指明元素数量。它的数量由K线数量决定,随着行情进行,K线不断增加,序列也相应的自动增加,并且是一一对应。

序列的下标:在星语言中,序列下标0代表最近的一根K线所对应的序列数据;下标1代表前一根K线所对应的数据。。下标2代表倒数第三根K线。。。。。[DataCount-1]代表了第一根K线(也是倒数第DataCount根)

序列计算引擎

那么,在看过系统中的一些公式指标实例之后,稍有传统语言编程经验的人都会立刻产生一个疑问。

那就是,在这些指标公式里,序列并不通过下标直接使用。

例如这样的一句:

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等。

交易策略指标比较适合逐根模式

逐根模式注意事项

1.凡是未来函数均不能用于逐根模式 未来函数包括zig,paek,refx,backset,

2.所有的序列计算不要包含在if then 语句内。由于每个元素只能计算一次,如果某个序列刚好依赖之前的计算结果,而之前的元素又因为if 条件不满足没有被计算,那么计算结果可能有误。 例如: 不建议这样写

if( marketpostion = 0 ) then 
  aa:= ma( c, 5);

建议的写法是:

ma5 := ma( c, 5); 
if( marketpostion = 0 ) then 
   aa := ma5;

仅适用于逐根的函数

1.Text_开头的文本系列函数

2.TL_开头的画线系列函数

3.所有跟交易相关的函数(交易函数、交易绩效函数、交易账户函数、交易状态函数、组合测评函数)

4.应用程序接口函数(AddMenu、OpenChartView)

5.Plot、PlotLine

常见问题

逐根指标可以引用逐行指标吗

答:可以。此时,被引用的逐行指标强行以逐根模式运行

主图是逐根指标,那么副图也是逐根吗

答:不是。主图和副图的运行模式是相互独立的

个人工具
名字空间

变换
操作
导航
工具箱