执行模式

来自tradeStar帮助系统
(版本间的差异)
跳转到: 导航, 搜索
(以“ #Run_By_Bar #Run_By_Series #Run_Every_Tick #Run_Every_Bar”为内容创建页面)
 
 
(未显示2个用户的19个中间版本)
第1行: 第1行:
 +
=逐根和逐行=
 +
 +
星语言中,公式有两种执行模式,一种叫逐行模式,一种叫逐根模式。
 +
 +
'''逐行运行''' 就是说根据代码,从上到下,第一行运行到最后一行:
 +
 +
[[Image:RunBySeries.png]]
 +
 +
'''逐根运行''' 就是说根据K线,从左边第一根K线,运行到右面最后一根K线:
 +
 +
[[Image:RunByBar.png]]
 +
 +
逐根运行在运行每一根K线时,也是把代码从第一行运行到最后一行的。逐根运行与逐行运行的区别是:
 +
 +
每行代码只运行当前的一个值,而逐行模式是整条序列。
 +
 +
 +
例如如果代码是 Close+1,那么在逐行模式下,Close 代表图上所有的收盘价,加一后,得到所有收盘价+1的一条序列;
 +
 +
而在逐根运行时,Close 只代表当前一根k线的收盘价,加一后,得到当前收盘价+1的一个单值,从第一根运行到最后一根,
 +
 +
每一根都得到1个单值,等所有K线运行完毕后,才得到完整的序列。
 +
 +
 +
由此可见,逐根模式比逐行模式多运行了许多遍:如果图上有1000根K线,公式代码将会被执行1000遍,
 +
 +
只不过每次运算只算1个值,而不像逐行模式那样每次运算一整条序列。总的来说逐根运行要比逐行耗时,
 +
 +
但是逐根运算能表达逐行运算所不能完成的条件分支逻辑,这是交易脚本所必须的逻辑。
 +
 +
另外,逐根模式在第一次运行完毕后,后续行情到来时,只需要运算最后一根的变化,这要比逐行的开销少多了。
 +
 +
关于这两种模式的运行机制更多讨论:[[逐行和逐根]]。
 +
 +
 +
公式是怎样选择运行模式的呢?通过编译开关来控制:
 
  #Run_By_Bar
 
  #Run_By_Bar
 
  #Run_By_Series
 
  #Run_By_Series
 +
 +
其中,#Run_By_Bar表示使用逐根模式,#Run_By_Series表示使用逐行模式。
 +
 +
这两个开关也可以不写,在不同的指标类型中,分别有不同的默认值。
 +
 +
在“技术指标”、“条件选股”、“交易系统”、“五彩K线”这四种指标中,默认是逐行模式。
 +
 +
在“智能策略”、“公共函数”、“优化评价”这三种指标中,默认是逐根模式(而且只能是逐根,指定逐行开关无效)。
 +
 +
=计算频率开关=
 +
 +
对于逐根模式,我们知道,每次都是只计算一根。
 +
 +
现在问题来了,K线的最后一根,并非是一次成型的,是在一段时间内不断变化的。
 +
 +
那么,是在每次变化时,都计算,还是最后成型时才计算呢?为此,准备了开关来控制这个行为。
  
 
  #Run_Every_Tick
 
  #Run_Every_Tick
 
  #Run_Every_Bar
 
  #Run_Every_Bar
 +
 +
*Run_Every_Tick 表示,最后一根K线每次变化的时候,都重新计算。
 +
 +
*Run_Every_Bar,则在下一根K线产生的一瞬间,才计算当前的K线。
 +
 +
[[Image:RunEveryTick.png]]
 +
 +
在 Buy Next Bar Open 这种类型的公式里,为了避免信号抖动,需要在K线完全走完时才发出信号,在下根K线中成交。
 +
 +
对于这种类型的公式,可以使用#Run_Every_Bar模式,减少不必要的运算。
 +
 +
 +
在 Buy This Bar Market 这种类型的公式里,需要根据最新行情来计算是否交易。此时公式运行需要 #Run_Every_Tick模式
 +
 +
对于SetStopLoss(止损)、SetProfitTarget(止盈)、SetDollarTrailing/SetPercentTrailing(跟踪止损)、SetBreakeven(保本平仓)等等Set给后台去做的工作,不受run_every_bar指令的影响,是永远每tick计算的。
 +
 +
=事件触发=
 +
 +
在公式中,可以编写一小段代码,这段代码是在某些事件发生的时候才执行。
 +
 +
这类事件包括'''初始化'''和'''执行完毕'''
 +
 +
===初始化===
 +
只要编写一个内置函数,并且命名为OnInit,那么它就会在初始化时执行。
 +
 +
fucntion OnInit
 +
Begin
 +
  //做一些只需要做一次,没有必要每次行情来时都做的工作。例如,设置画线的颜色,设置账号。等等。
 +
End
 +
 +
 +
那么,OnInit究竟具体在什么时候会发生呢。
 +
包括并且不限于以下情况,例如:
 +
 +
1.切换成其他品种;
 +
 +
2.切换成其他周期;
 +
 +
3.服务器推送来一些旧的历史数据(某种情况下,可能客户端会先请求最新一段数据,再请求旧的数据)
 +
 +
初始化事件会让公式清除所有状态重新运行计算1次,后续行情到来不再计算。
 +
 +
===执行完毕===
 +
只要编写一个内置函数,并且命名为OnExit,那么它就会在公式执行到末尾时执行。
 +
 +
  function OnExit
 +
  Begin
 +
    //做一些收尾工作
 +
  End
 +
 +
为什么需要OnExit呢,是因为目前公式引擎支持“中断”。所谓中断,就是如果某些公式计算一次时间特别长,有时公式运行到一半,还没计算完,用户切换到其他品种了,那之前的计算就没有必要继续下去,这时候,系统就会强行中断计算。
 +
 +
但是,用户可能希望某些计算是必须要执行的,例如,这个公式可能是调用DLL的,DLL可能在开始分配了一些资源,而且必须在运算完毕后释放,这部分计算就可以写在OnExit中,正常情况下它们会在公式主体运行结束之后被执行。如果公式主体被中断,它们会在中断后执行。
 +
 +
===公式主体===
 +
公式的主体是名为OnStart的函数,象这样:
 +
 
 +
  Function OnStart
 +
  Begin
 +
    mm:ma(c, close );
 +
  End
 +
 +
但是,为了方便编写,上述的“Function OnStart”可以省略。
 +
也就是可以只写
 +
  mm: ma( c, Close );
 +
 +
凡是没有包在其它函数体里面的代码都被认为是 OnStart 函数的内容。除非显式声明了 OnStart 函数。如果既声明了OnStart函数,又写了一段没有被任何函数包裹的代码,那么没有被包裹的代码被直接忽略,认为是空白。
 +
 +
=逐行和逐根的转化=
 +
有时我们需要把一个逐行公式转成逐根公式。例如,可能在策略里需要引用某个指标,那么最好让这个指标也运行在逐根下,这就需要写一个新指标,把老指标代码拷贝到新指标,然后加上#RUN_BY_BAR标志。
 +
 +
但有时这还不够。如果逐行指标里有for循环,那么最好把for循环去掉。
 +
 +
例如。以下逐行公式
 +
for i=100 to dataCount do
 +
begin
 +
  x[dataCount-i] = open[dataCount-i] + close[dataCount-i];
 +
end
 +
可以看到,这段代码的逻辑是从第100根K线开始,对每一根K线,相加其开盘和收盘价赋值给x。<br>
 +
在逐根逻辑中,公式引擎本身已经对K线做了逐根循环,所以可以消解掉这个for,把上面的代码直接用以下代码代替
 +
#RUN_BY_BAR
 +
if( barpos>=100 )then
 +
  x[dataCount-barpos] = Open[dataCount-barpos] + Close[dataCount-barpos]

2013年9月28日 (六) 15:19的最后版本

目录

[编辑] 逐根和逐行

星语言中,公式有两种执行模式,一种叫逐行模式,一种叫逐根模式。

逐行运行 就是说根据代码,从上到下,第一行运行到最后一行:

RunBySeries.png

逐根运行 就是说根据K线,从左边第一根K线,运行到右面最后一根K线:

RunByBar.png

逐根运行在运行每一根K线时,也是把代码从第一行运行到最后一行的。逐根运行与逐行运行的区别是:

每行代码只运行当前的一个值,而逐行模式是整条序列。


例如如果代码是 Close+1,那么在逐行模式下,Close 代表图上所有的收盘价,加一后,得到所有收盘价+1的一条序列;

而在逐根运行时,Close 只代表当前一根k线的收盘价,加一后,得到当前收盘价+1的一个单值,从第一根运行到最后一根,

每一根都得到1个单值,等所有K线运行完毕后,才得到完整的序列。


由此可见,逐根模式比逐行模式多运行了许多遍:如果图上有1000根K线,公式代码将会被执行1000遍,

只不过每次运算只算1个值,而不像逐行模式那样每次运算一整条序列。总的来说逐根运行要比逐行耗时,

但是逐根运算能表达逐行运算所不能完成的条件分支逻辑,这是交易脚本所必须的逻辑。

另外,逐根模式在第一次运行完毕后,后续行情到来时,只需要运算最后一根的变化,这要比逐行的开销少多了。

关于这两种模式的运行机制更多讨论:逐行和逐根


公式是怎样选择运行模式的呢?通过编译开关来控制:

#Run_By_Bar
#Run_By_Series

其中,#Run_By_Bar表示使用逐根模式,#Run_By_Series表示使用逐行模式。

这两个开关也可以不写,在不同的指标类型中,分别有不同的默认值。

在“技术指标”、“条件选股”、“交易系统”、“五彩K线”这四种指标中,默认是逐行模式。

在“智能策略”、“公共函数”、“优化评价”这三种指标中,默认是逐根模式(而且只能是逐根,指定逐行开关无效)。

[编辑] 计算频率开关

对于逐根模式,我们知道,每次都是只计算一根。

现在问题来了,K线的最后一根,并非是一次成型的,是在一段时间内不断变化的。

那么,是在每次变化时,都计算,还是最后成型时才计算呢?为此,准备了开关来控制这个行为。

#Run_Every_Tick
#Run_Every_Bar
  • Run_Every_Tick 表示,最后一根K线每次变化的时候,都重新计算。
  • Run_Every_Bar,则在下一根K线产生的一瞬间,才计算当前的K线。

RunEveryTick.png

在 Buy Next Bar Open 这种类型的公式里,为了避免信号抖动,需要在K线完全走完时才发出信号,在下根K线中成交。

对于这种类型的公式,可以使用#Run_Every_Bar模式,减少不必要的运算。


在 Buy This Bar Market 这种类型的公式里,需要根据最新行情来计算是否交易。此时公式运行需要 #Run_Every_Tick模式

对于SetStopLoss(止损)、SetProfitTarget(止盈)、SetDollarTrailing/SetPercentTrailing(跟踪止损)、SetBreakeven(保本平仓)等等Set给后台去做的工作,不受run_every_bar指令的影响,是永远每tick计算的。

[编辑] 事件触发

在公式中,可以编写一小段代码,这段代码是在某些事件发生的时候才执行。

这类事件包括初始化执行完毕

[编辑] 初始化

只要编写一个内置函数,并且命名为OnInit,那么它就会在初始化时执行。

fucntion OnInit
Begin
  //做一些只需要做一次,没有必要每次行情来时都做的工作。例如,设置画线的颜色,设置账号。等等。
End


那么,OnInit究竟具体在什么时候会发生呢。 包括并且不限于以下情况,例如:

1.切换成其他品种;

2.切换成其他周期;

3.服务器推送来一些旧的历史数据(某种情况下,可能客户端会先请求最新一段数据,再请求旧的数据)

初始化事件会让公式清除所有状态重新运行计算1次,后续行情到来不再计算。

[编辑] 执行完毕

只要编写一个内置函数,并且命名为OnExit,那么它就会在公式执行到末尾时执行。

 function OnExit
 Begin
   //做一些收尾工作
 End

为什么需要OnExit呢,是因为目前公式引擎支持“中断”。所谓中断,就是如果某些公式计算一次时间特别长,有时公式运行到一半,还没计算完,用户切换到其他品种了,那之前的计算就没有必要继续下去,这时候,系统就会强行中断计算。

但是,用户可能希望某些计算是必须要执行的,例如,这个公式可能是调用DLL的,DLL可能在开始分配了一些资源,而且必须在运算完毕后释放,这部分计算就可以写在OnExit中,正常情况下它们会在公式主体运行结束之后被执行。如果公式主体被中断,它们会在中断后执行。

[编辑] 公式主体

公式的主体是名为OnStart的函数,象这样:

 Function OnStart
 Begin
   mm:ma(c, close );
 End

但是,为了方便编写,上述的“Function OnStart”可以省略。 也就是可以只写

 mm: ma( c, Close );

凡是没有包在其它函数体里面的代码都被认为是 OnStart 函数的内容。除非显式声明了 OnStart 函数。如果既声明了OnStart函数,又写了一段没有被任何函数包裹的代码,那么没有被包裹的代码被直接忽略,认为是空白。

[编辑] 逐行和逐根的转化

有时我们需要把一个逐行公式转成逐根公式。例如,可能在策略里需要引用某个指标,那么最好让这个指标也运行在逐根下,这就需要写一个新指标,把老指标代码拷贝到新指标,然后加上#RUN_BY_BAR标志。

但有时这还不够。如果逐行指标里有for循环,那么最好把for循环去掉。

例如。以下逐行公式

for i=100 to dataCount do 
begin
  x[dataCount-i] = open[dataCount-i] + close[dataCount-i];
end

可以看到,这段代码的逻辑是从第100根K线开始,对每一根K线,相加其开盘和收盘价赋值给x。
在逐根逻辑中,公式引擎本身已经对K线做了逐根循环,所以可以消解掉这个for,把上面的代码直接用以下代码代替

#RUN_BY_BAR
if( barpos>=100 )then 
  x[dataCount-barpos] = Open[dataCount-barpos] + Close[dataCount-barpos]
个人工具
名字空间

变换
操作
导航
工具箱