TB交易开拓者公式平台的语言编码原则
TB交易开拓者公式平台的语言编码原则
TBQuant版
2021年3月20日 14:38
浏览量:360
끄收藏
语言元素
交易开拓者公式平台的语言是TradeBlazer Language,简称“TB语言”。 它是一种高级语言,语法简洁易懂,介于C++与Pascal之间,其语言元素包括保留字、函数、表达式和语句。
保留字:TB公式中保留字有自己独特的意义或用途,主要是指一些功能关键字、系统函数以及数据类型等,例如:Params,Vars , For……
函数:函数实现一定的功能,分为系统函数和用户函数,例如:sqr,abs……
表达式:由变量和操作符组成的运算式,例如:x=a+b;
语句:赋值语句,分支语句,控制语句等等,例如:if…else语句
命名规则
1. 公式名称规则
不区分大小写;
不能超过64个英文字符;
公式之间不得重名;
公式名称不能出现字母、数字、下划线以外的其他字符,且不能以数字开头;
不能使用C++关键字;
公式名称不能和系统保留字,系统函数等重名。
2. 变量,参数规则
不区分大小写;
不能超过64个英文字符;
每一个公式内部不能重复命名;
名称不能出现字母、数字、下划线以外的其他字符,且不能以数字开头;
名称不能和系统保留字,系统函数等重名;
不能使用C++关键字;
不能使用已定义的用户函数名。
公式正文规则
公式中不区分字符的大小写,例如Ab与ab等效;
公式语句以“;”结束;
公式中代码正文不允许出现中文字符,使用英文双引号 “” 引用起来的字符串除外;
公式正文字符因含义不同,以不同的颜色区分:
黑色 --- 用户自己声明的变量名或者参数名;
红色 --- 数字;
蓝色 --- 系统函数;
暗红色--- 已有的用户函数;
紫红色--- 运算符号;
果绿色--- 字符串(可以为中文字符);
翠绿色--- 注释语句(注释符号后可为中文字符)。
注释方式
对单行语句进行注释,可以在句首使用“//”将该行文字注释,也可直接在公式语句之后使用 “// ”对语句的意思或者想要标记的内容注释;
对多行语句进行注释,则可使用“/* ...*/”将整段文字进行注释;
也可以使用快捷键Ctrl + B进行块注释;
使用快捷键Ctrl+U对选中行取消行注释,Ctrl+L对选中行添加行注释;
注释语句不参与公式主体的计算,允许出现中文字符。
保留字
TB公式中保留字主要指功能关键字、系统函数以及数据类型等。命名公式简称以及参数、变量时,要避免使用保留字。
下面分类列举出系统主要的保留字。
运算符
类型保留字
算术运算符+ - * / % ^
关系运算符> >= < <= == != <>
逻辑运算符AND/&& OR/|| NOT/!
功能关键字
保留字说明
Params用该关键字宣告参数定义的起始,参数必须填写默认值。
Vars用该关键字宣告变量定义的起始(可以赋初值), 变量不填写初值时,系统将自动为其填充初值。
If条件语句。
Else条件语句。
Begin用该关键字宣告程序主体的起始。
End用该关键字宣告程序主体的结束。
For循环语句。
To循环语句。
DownTo循环语句。
While循环语句。
Break循环语句。
Continue循环语句。
True真。
False假。
Return返回函数结果
数据源
保留字说明
Data0-Data99**支持多个数据源(具体数目及支持效率与本地电脑配置相关)。
Data数据源数组(格式为:Data[i],i为整数,用法同上)。
函数:数据输出和交易指令
保留字说明
PlotBool输出布尔型值。
PlotNumeric输出数值型值。
PlotString输出字符串值。
UnPlot取消指定位置的输出。
PlotDic在当前Bar的输出信息中添加基础数据信息。
Alert报警输出。
Buy多头建仓操作。
Sell多头平仓操作。
SellShort空头建仓操作。
BuyToCover空头平仓操作。
...其他系统函数。
标点符号
TB公式的语句支持使用标点符号,例如,";"标注一个语句结束;()创建规则的优先权等等。标点符号也是系统保留字,下表中列出了TB公式中所用到的标点符号及其含义:
符号名称说明
;分号语句结束的标志。
,逗号当函数带有多个参数时,用于分隔多个参数。
()小括号括号之内的表达式有计算的优先权。
""双引号字符串常量。
[]中括号回溯数据,引用以前的数据,或者数组中的元素。
{}大括号控制语句的起始。
.点扩展数据源的数据调用。
操作符
操作符是象征具体操作运算行为的符号,根据其作用的不同,分为三类:
数学操作符
操作符说明
+加
-减
*乘
/除
%求模
()括号
这些数学操作符按其特定的优先级来进行计算,“* ”(乘法)最先,其次是“/”(除法)和“%”(求模),“+”(加法)和“-”(减法)最后,如果有多个乘法/除法(或者是加法/减法),那么计算顺序是从左至右。
例:High+2* Range/2;
它首先计算的是Range(此处Range是指High-Low)与2的积,接着计算与2的商(除法),最后求2*Range/2与最高价(High)的和。
例: (High+Low)/2;
先计算()中High与Low的和,然后将计算得到的和值除以2,找到一个Bar的中间位置
关系操作符
操作符说明
<小于
>大于
<=小于等于
>=大于等于
<>或!=不等于
==等于
应用关系操作符,可以对两个数值或字符串表达式进行比较。
如果两个操作数都是数值型,则按其大小比较
如果两个操作数都是字符型,则按字符的ASCII码值从左到右一一比较
汉字字符大于西文字符
关系操作符的优先级相同
例:Close>High[1];
判断当前Bar收盘价是否比前一个Bar最高价高
例:"abcd" < "zyxw";
字符串的比较运算中,按照顺序依次比较的每个字符的ASCII码值,直至计算出结果即可。 在这个例子中,首先比较“a”和“z”,字母"a"的ASCII值是小于"z",所以该表达式的值为True。
逻辑操作符
TB语言支持三类逻辑操作符:与AND(&&),或OR(||),非NOT(!)。
AND逻辑操作符运算规则:
表达式1表达式2表达式1 AND 表达式2
TrueTrueTrue
TrueFalseFalse
FalseTrueFalse
FalseFalseFalse
简单记忆法则:AND运算只有两个条件都为True时,结果才为True。
OR逻辑操作符运算规则:
表达式1表达式2表达式1 OR 表达式2
TrueTrueTrue
TrueFalseTrue
FalseTrueTrue
FalseFalseFalse
简单记忆法则:OR运算只要有一个条件为True,结果即为True。
NOT逻辑操作符运算规则:
表达式1NOT表达式1
TrueFalse
FalseTrue
例:Low < Low[1] AND Close > High[1];
当前Bar的最低价小于前一个Bar的最低价,并且当前Bar的收盘价高于前一个Bar的最高价时,这个表达式的计算结果才为Ture。
例:High > 10 OR Vol > 5000;
当前Bar的最高价大于10,或者成交量大于5000,表达式的值都为True。
逻辑操作符的优先级低于数学操作符和关系操作符。逻辑操作符也遵循括号优先的原则,如果没有括号,那么其运算顺序是从左至右。因此逻辑表达式中不同条件的前后顺序,可能会产生不同的运算逻辑,执行的效率也会有所不同。
以Con1 AND Con2为例,系统从左到右进行逻辑判断,当Con1为True时,需要继续判断Con2是否为True,只有当Con1,Con2都为True时,整个表达式才为True。但是只要当Con1为False时,就不再需要判断Con2的值,而是直接返回False。
因此,以下两个表达式在执行效率方面是有差异的:
5 < 4 AND Close > Open;
Close > Open AND 5 < 4;
第一条语句的执行速度大部分情况下都比第二条要快。
对于Con1 OR Con2表达式,情况也比较类似,当Con1为False时,需要继续判断Con2是否为False,只有当Con1,Con2都为False时,整个表达式才为False。但是只要当Con1为True时,就不再需要判断Con2的值,而是直接返回True。
以下两条语句的执行效率也是不一样的:
5 > 4 OR Close > Open;
Close > Open OR 5 > 4;
因此,逻辑表达式的组合应该尽可能的把容易判别整个表达式逻辑的条件放在前面,以减少整个表达式的计算时间。
表达式
表达式的组成
TB表达式由常量、变量、操作符、函数和圆括号按一定的规则组成,通过运算能得到结果,运算结果的类型由数据和操作符共同决定。
表达式的书写规则
乘号不能省略。
括号必须成对出现,均使用圆括号,可以嵌套,但必须配对。
表达式从左到右在同一基准上书写,无高低、大小之分。
例:sqr((3* x+y)-z)/(x*y)^4
不同数据类型的转换
操作数的数据类型应该符合要求,不同的数据应该转换成同一类型。
例:Commentary("Close = "+Text(Close));
Commentary函数只能显示字符串类型的注释信息,因此,使用Text()函数将Close的数值转换成字符再显示
优先级
同一表达式中,不同运算符的优先级是:
算术运算符 > 字符运算符 > 关系运算符 > 逻辑运算符
【注意】对于存在多种运算符的表达式,可增加圆括号改变优先级或使表达式更清晰。
例:MarketPosition == 1 And BarsSinceEntry >= 1
先进行关系运算MarketPosition是否等于1,BarsSinceEntry是否大于等于1;然后再根据逻辑运算符AND计算两个表达式的的结果(此条件的含义为是否持有多仓且不是开仓bar)
例:Low <= MyEntryPrice - StopLossSet* MinPoint
先计算StopLossSet* MinPoint,然后计算MyEntryPrice - StopLossSet* MinPoint,最后比较Low是否小于MyEntryPrice - StopLossSet*MinPoint(此条件的含义为判断止损条件是否满足)
赋值语句
一个语句代表一个完全的指示或描述,语句中包含有保留字、操作符、符号。并且语句总是以";"作为语句结束的标志。
赋值语句用于给公式变量指定一个具体的值的语句,赋值语句使用赋值操作符(=)进行处理。
以下为赋值语句的一些例子:
Vars
Bool b;
Events
OnBar(ArrayRef<Integer> indexs)
{
B = true;
...
}
Vars
Numeric Value1;
Events
OnBar(ArrayRef<Integer> indexs)
{
Value1 = (Close + Open)/2;
...
}
Vars
String str;
Events
OnBar(ArrayRef<Integer> indexs)
{
str ="It Is A Test!";
...
}
变量在赋值的时候忽略其扩展数据类型,只考虑其基本数据类型,即Series,NumericRef,Numeric之间可以相互赋值。此时序列数据类型只是对当前Bar的值进行操作。
以下的写法是错误的:
Vars
Series<Numeric> Value2;
Events
OnBar(ArrayRef<Integer> indexs)
{
Value2[1] = (Close + Open)/2;
}
控制语句
计算机语言一般都有有三个基本的控制语句,顺序、选择和循环。
顺序类型直接以代码的顺序决定。选择类型和循环类型则需要有关键字来进行操作。
1. 选择类型
选择类型的关键字有if和else。
1.1 一个分支
If(逻辑条件)
{
执行语句组;
}
注意:如果执行语句组只有一条语句时,{}可以省略。
举例:
Vars
Numeric a;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
if(a>0 and a<=1)
b=1;
}
1.2 两个互斥分支
If(逻辑条件)
{
执行语句组A;
}
Else
{
执行语句组B;
}
举例:
Vars
Numeric a;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
if(a>0 and a<=1)
b=1;
Else
b=2;
}
1.3 多个互斥分支
If(逻辑条件1)
{
执行语句组A;
}
Else if(逻辑条件2)
{
执行语句组B;
}
Else if(逻辑条件3)
{
执行语句组C;
}
...
Else {
}
举例:
Vars
Numeric a;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
if(a>0 and a<=1)
b=1;
else if(a>1 and a<=2)
b=2;
else if(a>2 and a<=3)
b=3;
Else
b=4;
}
1.4 条件语句的嵌套
If(逻辑条件1)
{
If(逻辑条件2)
{
执行语句组;
}
}
举例:
Vars
Numeric a;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
if(a>0)
{
if(a<1)
b=1;
}
}
2. 循环类型
循环类型的关键字有while和for。配合的还有to downto break continue。
2.1 while类型
While(逻辑条件)
{
执行语句组;
}
举例:
Vars
Numeric a;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
While(b<3)
{
b=b+1;
}
}
2.2 for 增序类型
for i=min to max
{
执行语句组;
}
举例:
Vars
Integer i;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
for i=0 to 3
{
b=b+1;
}
}
2.3 for 降序类型
for i=max downto min
{
执行语句组;
}
举例:
Vars
Integer i;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
for i=3 DownTo 0
{
b=b+1;
}
}
2.4 break
Break是触发语句所在的最内层循环的终止。
举例:
Vars
Integer i;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
for i=3 DownTo 0
{
b=b+1;
if(b>=2)
break;
}
}
注释:当b>=2时,这个循环就提前终止了。
2.5 continue
Continue是跳过语句所在循环剩下的执行语句,进入下一轮的执行。
举例:
Vars
Integer i;
Numeric b;
Events
OnBar(ArrayRef<Integer> indexs)
{
for i=3 DownTo 0
{
if(b>=2)
Continue;
b=b+1;
}
}
注释:当b>=2时,b=b+1始终得不到执行,所以b最终=2。
2.6 循环的嵌套
For i=min to max
{
For j=min to max
{
执行语句组;
}
}
举例:
Vars
Integer i;
Integer j;
Array<Array<Numeric>> a;
Events
OnBar(ArrayRef<Integer> indexs)
{
for i=3 DownTo 0
{
for j=0 to 3
{
a[i][j]=i+j;
}
}
}
RANGE对代码段的控制
Range[i:j]
{
代码段codes1;
}
如果使用range[i:j]把代码段codes1括起来,则代表这一段代码只在数据源datai到dataj的数据源运行。I要小于j,比如range[1:2],则代表代码段codes1只在数据源data1和data2上运行。
具体例子如下:
Range[0:1]
{
AvgValue1 = AverageFC(Close,FastLength);
AvgValue2 = AverageFC(Close,SlowLength);
PlotNumeric("MA1",AvgValue1);
PlotNumeric("MA2",AvgValue2);
}
上面代码会在Data[0]和Data[1]上都运行,分别画出Data[0]和Data[1]的双均线。
注意:Range[i:j]内的代码运行说明如下:
没有指定数据源的代码,依次在Data [i]到Data [j]的bar上运行。
有指定数据源的代码,则在指定的数据源的bar上运行。
同一个公式内,可有多个并列的Range代码块,Range内不支持Range嵌套。
Range[m:n]中,数据源起始位置m及结束位置n可以指定,也可以为变量和参数声明,类型为简单变量。
如果想要得到数据源的编号,则可以这样使用
Range[i=0:1]
{
Commentary(“i=”+text(i));
}