TradeBlazer公式入门教程

Discussion in '开拓者期货自动交易平台' started by tradeblazer, Aug 26, 2007.

  1. [font=楷体_GB2312]请大家不要在此贴回复,关于该贴的问题请到这里回复,谢谢![/font]


    TradeBlazer公式入门教程(1)

    Step 1、在开始写公式之前,我们先了解以下基本概念

    Bar数据:
    公式在进行计算时,都是建立在基本数据源(Bar数据)之上,我们这里所谓的Bar数据,是指商品在不同周期下形成的序列数据,在单独的每个Bar上面包含开盘价、收盘价、最高价、最低价、成交量及时间。期货等品种还有持仓量等数据。所有的Bar按照不同周期组合,并按照时间从先到后进行排列,由此形成为序列数据,整个序列称之为Bar数据。
    公式如何执行:
    TradeBlazer公式在计算时按照Bar数据的Bar数目,从第一个Bar到最后一个Bar,依次进行计算,如果公式中出现了调用Bar数据函数的,则取出当前Bar的相应值,进行运算。公式执行从上至下,Bar从左到右执行。

    Step 2、接下来,我们从TradeBlazer公式的HelloWorld开始
    该贴前期已经发过,因此在此只给出链接:
    TradeBlazer公式的HelloWorld!

    Step 3、建立一个简单的指标:成交量
    对于交易开拓者界面不熟悉的朋友可以参看以下帖子:
    如何在交易开拓者中编写技术指标?

    新建指标简称: MyVol
    Code:
    Begin 
    	PlotNumeric("Vol",Vol);	
    End
    
    BeginEnd宣告公式正文的开始和结束,公式语句应该放到Begin 和End之间。
    并且总是以";"作为语句结束的标志。
    PlotNumeric表示输出一个数值型组成的数组;公式中“”内所引用的是字符串的常量,内容文字即在图表中所输出的技术指标的名称

    关于PlotNumeric的使用
    函数原形:
    Numeric PlotNumeric(String Name,Numeric Number,Integer Color=-1,Integer BarsBack=0)
    参数:
    Name 输出值的名称,不区分大小写;
    Number 输出的数值;
    Color 输出值的显示颜色,默认表示使用属性设置框中的颜色;
    BarsBack 从当前Bar向前回溯的Bar数,默认值为当前Bar。

    技术指标属性的设置
    在属性里的常规下填写公式的简称、名称、分类以及注释。也可更改参数等设置:
     
  2. 在“线型”里选择更改技术指标的输出形态,如线条、柱状图、十字图等,并且选择自己爱好的颜色,
    以更加个性化的表现形式来迎合您的看盘习惯。
     
  3. TradeBlazer公式入门教程(2)
    Step 4:
    前面我们所建的技术指标MyVol,可以输出成交量,但成交量只能设置为属性所选的一种颜色。如下图:
     
  4. 很多朋友习惯于看红绿色表示涨跌的成交量。
    下面我们来实现带红绿颜色的成交量指标,代码如下:
    Code:
    Begin
        PlotNumeric(“Vol”,Vol,IIf(Close>=Open,Red,Green));
    End
    
    使用的情形如下:
     
  5. 关于IIF
    函数原形:
    Numeric IIF(Bool Conditon,Numeric TrueValue,Numeric FalseValue)
    参数:
    Conditon 条件表达式;
    TrueValue 条件为True时的返回值;
    FalseValue 条件为False时的返回值。

    针对上面的使用IIF进行成交量颜色指定的脚本, 我们还有另外一种写法:
    Code:
    Begin
        If(Close>=Open)
            PlotNumeric(“Vol”,Vol,Red);
        Else
            PlotNumeric(“Vol”,Vol,Green);
    End
    
    PlotNumeric由输出的名字来区分是否为同一条线!

    关于IF语句
    If语句是一个条件语句,当特定的条件满足后执行一部分操作。
    语法如下:
    If (Condition)
    {
      TradeBlazer公式语句;
    }
    TradeBlazer公式语句是一些语句的组合,如果TradeBlazer公式语句是单条,您可以省略{},二条或者二条以上的语句必须使用{}。
     
  6. TradeBlazer公式入门教程(3)
    Step5

    关于条件表达式

    逻辑操作符
    逻辑运算符常常用于比较两个True/False的表达式,共有三个逻辑操作符:AND(&&),OR(||),NOT(!)。

     表达式1 AND 表达式2
     表达式1 OR 表达式2
     NOT表达式1

    如下图表所示可以让大家更清晰地理解逻辑操作符在表达式中的运算结果
     
  7. TradeBlazer公式入门教程(4)
    Step6

    前面第一贴已经讲过了IF语句,接下来要讲解条件语句的另外三种表达方式:
    If-Else
    If-Else-If
    If-Else的嵌套


    关于If-Else语句
    If-Else语句是对指定条件进行判断,如果条件满足执行If后的语句。否则执行Else后面的语句。

    语法如下:
    Code:
    If (Condition)
    {
        TradeBlazer公式语句1;
    }Else
    {
        TradeBlazer公式语句2;
    }
    Condition是一个逻辑表达式,当Condition为True的时候,TradeBlazer公式语句1将会被执行;Condition为False时,TradeBlazer公式语句2将会被执行。Condition可以是多个条件表达式的逻辑组合,Condition必须用()括起来。

    TradeBlazer公式语句是一些语句的组合,如果TradeBlazer公式语句是单条,您可以省略{},二条或者二条以上的语句必须使用{}。


    例如,比较当前Bar和上一个Bar的收盘价,如果Close > Close[1],Value1 = Value1 + Vol;否则Value1 = Value1 - Vol,脚本如下:
    Code:
    If (Colse > Close[1])
        Value1 = Value1 + Vol;
    Else
        Value1 = Value1 - Vol;


    关于If-Else-If的语句
    If-Else-If是在If-Else的基础上进行扩展,支持条件的多重分支。

    语法如下:

    Code:
    If (Condition1)
    {
        TradeBlazer公式语句1;
    }Else If(Condition2)
    {
        TradeBlazer公式语句2;
    }Else
    { 
        TradeBlazer公式语句3;
    }
    
    
    Condition1是一个逻辑表达式,当Condition1为True的时候,TradeBlazer公式语句1将会被执行,Condition1为False时,将会继续判断Condition2的值,当Condition2为True时,TradeBlazer公式语句2将会被执行。Condition2为False时,TradeBlazer公式语句3将会被执行。Condition1,Condition2可以是多个条件表达式的逻辑组合,条件表达式必须用()括起来。

    TradeBlazer公式语句是一些语句的组合,如果TradeBlazer公式语句是单条,您可以省略{},二条或者二条以上的语句必须使用{}。

    If-Else-If的语句可以根据需要一直扩展,在最后的Else之后再加If(Condition)和新的执行代码即可。当然您也可以省略最后的Else分支,语法如下:

    Code:
    If (Condition1)
    {
        TradeBlazer公式语句1;
    }Else If(Condition2)
    {
        TradeBlazer公式语句2;
    }
    
    


    If-Else的嵌套

    If-Else的嵌套是在If-Else的执行语句中包含新的条件语句,即一个条件被包含在另一个条件中。

    语法如下:

    Code:
    If (Condition1)
    {
        If (Condition2)
        {
            TradeBlazer公式语句1;
        }Else
        {
            TradeBlazer公式语句2;
        }
    }Else
    {
        If (Condition3)
        {
            TradeBlazer公式语句3;
        }Else
        {
            TradeBlazer公式语句4;
        }
    }
    
    

    Condition1是一个逻辑表达式,当Condition1为True的时候,将会继续判断Condition2的值,当Condition2为True时,TradeBlazer公式语句1将会被执行。Condition2为False时,TradeBlazer公式语句2将会被执行。当Condition1为False的时候,将会继续判断Condition3的值,当Condition3为True时,TradeBlazer公式语句3将会被执行。Condition3为False时,TradeBlazer公式语句4将会被执行。Condition1,Condition2,Condition3可以是多个条件表达式的逻辑组合,条件表达式必须用()括起来。

    TradeBlazer公式语句是一些语句的组合,如果TradeBlazer公式语句是单条,您可以省略{},二条或者二条以上的语句必须使用{}。

    例如,在一个交易指令中,条件设置如下:当前行情上涨的时候,如果收盘价高于开盘价时,则产生一个以收盘价买入1张合约;否则产生一个以开盘价买入1张合约。当前行情没有上涨的时候,如果收盘价高于开盘价,则产生一个以收盘价卖出1张合约;否则产生一个以开盘价卖出1张合约。脚本如下:

    Code:
    If (Open > High[1])
    {
        If (Close>Open)
        {
            Buy(1,Open);
        }Else
        {
            Buy(1,Close);
        }
    }Else
    {
        If (Close > Open)
        {   
            Sell(1,Open);
        }Else
        {
            Sell (1,Close);
        }
    }
    
    
     
  8. TradeBlazer公式入门教程(5)

    Step7


    现在再回到成交量指标
    有人喜欢在成交量指标上加均线,我们来看如何实现这样的功能。
    Code:
    Begin
        PlotNumeric(“Vol”,Vol);
        PlotNumeric(“AvgVol5”,AverageFC(Vol,5));
    End
    如下图中所示便是加了均线的成交量
     
  9. Step8

    关于Average和 AverageFC
    Average和AverageFC都是内建的用户函数,目的都是用来求N个Bar以来的平均值,您可以直接看到实现的代码。
    如下:
    Average
    Code:
    Params
            NumericSeries Price(1);
            Numeric Length(10);
    Vars
            Numeric AvgValue; 
    Begin
            AvgValue = Summation(Price, Length) / Length;        
            Return AvgValue;
    End
    AverageFC
    Code:
    Params
            NumericSeries Price(1);
            Numeric Length(10);
    Vars
            Numeric AvgValue; 
    Begin
            AvgValue = SummationFC(Price, Length) / Length;        
            Return AvgValue;
    End
    Average和AverageFC有什么不同呢?AverageFC是指FastCalculate,即快速计算。当这两个函数的第二个变量,即N个Bar是常量时,使用AverageFC,提高计算效率。当N是不确定的变量时,则必须使用Average,否则会出现计算问题。
    单看Average和AverageFC似乎是一样的,唯一不同的是AvgValue的计算方式用到的是Summation和SumamtionFC。



    Summation和SumamtionFC
    现在再来看看Summation与SumamtionFC的不同之处。公式表达如下:

    Summation

    Code:
    Params
    	NumericSeries Price(1);
    	Numeric Length(10);
    Vars
    	Numeric SumValue(0);
    	Numeric i;
    Begin
    	If (CurrentBar >= Length-1)
    	{
    		for i = 0 to Length - 1
    		{
    			SumValue = SumValue + Price[i];
    		}
    	}Else
    	{
    		SumValue = InvalidNumeric;
    	}
    	Return SumValue;
    End

    SummationFC

    Code:
    Params
    	NumericSeries Price(1);
    	Numeric Length(10);
    Vars
    	NumericSeries SumValue(0);
    	Numeric i;
    Begin
    	If ( CurrentBar < Length || Price[Length] == InvalidNumeric || SumValue[1] == InvalidNumeric )
    	{
    		for i = 0 to Length - 1
    		{
    			SumValue = SumValue + Price[i];
    		}
    	}Else
    	{
    		SumValue = SumValue[1] + Price - Price[Length] ;
    	}
    	Return SumValue;
    End

    关于Average函数的参数

    Numeric Average(NumericSeries Price, Numeric Length);
    Price 需要进行平均的序列变量
    Length 平均时回溯的Bar数量
     
  10. TradeBlazer公式入门教程(6)


    Step9

    接下来我们再说一下常量与变量的定义

    常量
    是用来代替一个数或字符串的名称,在公式整个执行过程中不发生改变。

    变量
    是一个存储值的地址,当变量被声明之后,就可以在脚本中使用变量,可以对其赋值,也可以在其他地方引用变量的值进行计算,要对变量进行操作,直接使用变量名称即可。

    变量的主要用处在于它可以存放计算或比较的结果,以方便在之后的脚本中直接引用运算的值,而无需重现计算过程。

    例如,我们定义一个变量Y,我们把一个收盘价(Close)乘上8%的所得的值存储在Y中,即Y = Close *8%。那么一旦计算出Close * 8%的值,便赋给变量Y。而无需在公式中输入计算过程,只需调用变量名称即可引用变量的值。

    变量有助于程序的优化,这是TradeBlazer公式必须重复调用一些数据,这些数据可能是某些函数(如:Bar数据),或通过表达式执行计算和比较的值。因此,在表达式频繁使用的地方使用变量可提高程序的运行速度和节约内存空间。

    使用变量也可以避免输入错误,使程序的可读性提高,示例如下:

    未使用变量的公式代码:

    Code:
    If(Close > High[1] + Average(Close,10)*0.5) 
    {
        Buy(100, High[1] + Average(Close,10)*0.5);
    }
    如果使用变量,则整个代码变得简洁:

    Code:
    Value1 = High[1] + Average(Close,10)*0.5;
    If (Close > Value1)
    {
        Buy(100,Value1);
    }
    
    如果一些表达式的组合经常在不同的公式中被调用,这个时候变量就不能实现功能,变量只能在单个公式的内部使用,这个时候我们需要建立用户函数来完成这些功能,详细说明参见用户函数(在TB软件里按F1便会出现联机帮助--公式系统--公式应用--用户函数)

    变量类型

    TradeBlazer公式支持有三种基本数据类型:数值型(Numeric)、字符串(String)、布尔型(Bool)。为了通过用户函数返回多个值,我们对三种数据类型进行了扩展,增加了引用数据类型。另外,为了对变量,参数进行回溯,我们增加了序列数据类型。因此,我们的数据类型共有九种。但对于变量定义,引用类型是无效的,剩余六种数据类型中分为简单和序列两大类,简单类型变量是单个的值,不能对其进行回溯,序列类型变量是和Bar长度一致的数据排列,我们可以通过回溯来获取当前Bar以前的任意值。

    9种数据类型

    Bool 布尔型。
    BoolRef 布尔型引用。
    BoolSeries 和周期长度一致的Bool型序列值。
    Numeric 数值型。
    NumericRef 数值型引用。
    NumericSeries 和周期长度一致的Numeric型序列值。
    String 字符串。
    StringRef 字符串引用。
    StringSeries 和周期长度一致的String型序列值。


    变量声明

    在使用变量之前,必须对变量进行声明,TradeBlazer公式使用关键字"Vars"来进行变量宣告,并指定变量类型。可以选择赋默认值,也可以不赋默认值。

    变量定义的语法如下:

    Code:
    Vars
        变量类型 变量名1(初值);
        变量类型 变量名2(初值);
        变量类型 变量名3(初值);
    
    下面是一些变量定义的例子:

    Code:
    Vars
        NumericSeries   MyVal1(0);              //定义数值型序列变量MyVal1,默认值为0;
        Numeric         MyVal2(0);              //定义数值型变量MyVal2,默认值为0;
        Bool            MyVal3(False);          //定义布尔型变量MyVal3,默认值为False;
        String          MyVal4("Test");         //定义字符串变量MyVal4,默认值为Test。
    
    变量定义的个数没有限制,变量名称的命名规范详细说明参见命名规则

    整个公式中只能出现一个Vars宣告,并且要放到公式的开始部分,在参数定义之后,正文之前

    变量的默认值

    在声明变量时,通常会赋给变量一个默认值。例如上例中的0,False,"Test"等就是变量的默认值。如果某个变量没有赋予默认值,系统将会自动给该变量赋予默认值。数值型变量的默认值为0,布尔型变量的默认值为False,字符串的默认值为空串。

    变量的默认值是在当公式在执行时,给该变量赋予的初值,使该变量在引用时存在着有效的值。在该公式每个Bar的执行过程中,改变量的默认值都会被重新赋值。


    变量赋值

    变量声明完成之后,您可以在脚本正文中给变量指定一个值。

    语法如下:
    Code:
    Name = Expression;
    

    "Name"是变量的名称,表达式的类型可以是数值型、布尔型、字符串中的任何一种。不过表达式的类型一定要和变量的数据类型相匹配。如果变量被指定为是数值型的,那么表达式一定要是数值型的表达式。

    例如:下面的语句将Close的10周期平均值赋值给变量Value1:

    Code:
    Value1 = Average(Close , 10);
    在下面这个语句中,声明了一个名为"KeyReversal"的逻辑型变量,然后又把计算的值赋给它。

    Code:
    Vars
        Bool        KeyReversal(False);
    Begin
        KeyReversal = Low < Low[1] AND Close > High[1];
        ...
    End
    
    变量使用

    变量定义、赋值之后,在表达式中直接使用变量名就可以引用变量的值。例如在下面的语句中计算了买入价格后,把值赋给数值型变量EntryPrc,在买入指令中便可直接应用变量名,通过变量名便可引用变量的值:

    Code:
    Vars
        Numeric EntryPrc(0);
    Begin
        EntryPrc = Highest(High,10);
        If (MarkerPosition <> 1)
        {
            Buy(1,EntryPrc);
        }
    End
    接下来的例子,我们计算最近10个Bar最高价中的最大值(不包括当前Bar),对比当前High,然后通过If语句,产生报警信息。

    Code:
    Vars
        Bool    Con1(False);
    Begin
        Con1 = High > Highest(High,10)[1];
        If(Con1)
        {
            Alert("New 10-bar high");
        }
    End

    其实我们并不一定都要应用条件为True的情况,有时候我们需要判断条件为False的时候执行某些代码,如下的例子:

    Code:
    Vars
        Bool    Con1(False);
    Begin
        Con1 = High < Highest(High,10)[1] AND Low > Lowest(Low,10)[1];
        If(Con1==False)
        {
            Alert("New high or low");
        }
    End
    

    序列变量

    Code:
    Vars
        NumericSeries  MyNumSVal(0);
        BoolSeries	  MyBoolVal(False);
        StringSeries	  MyStrVal("");
    
    序列变量和简单变量一样,可以对其赋予默认值。

    序列变量定义之后,您可以象简单变量一样的对其使用,不会有任何的不同。除了支持全部简单变量的功能之外,序列变量还可以通过"[nOffset]"来回溯以前的变量值,详细说明参见变量回溯

    对于序列变量,TradeBlazer公式在内部针对其回溯的特性作了很多的特殊处理,也需要为序列变量保存相应的历史数据,因此,和简单变量相比,执行的速度和占用内存空间方面都作了一些牺牲。因此,尽管您可以定义一个序列变量,把它当作简单变量来使用,但是,我们强烈建议您只将需要进行回溯的变量定义为序列变量。