一个容易犯得编程错误
下面程序是我从程序中摘取的片段,它编译正确,但执行不是我要的结果。Vars
String MyLogFile; //日志文件名
Numeric MyTicks(7); //计数值
Begin
If (BarStatus==0)
{
MyLogFile ="c:\\MyAutoExiter.Log";
SetGlobalVar(0,0); //Ticks计数器归0
FileAppend(MyLogFile,"启动交易程序 for "+SymbolName+" at "+TimeToString(CurrentTime));
}
SetGlobalVar(0,GetGlobalVar(0)+1);//计数器增1
If (GetGlobalVar(0)>=MyTicks)
{
FileAppend(MyLogFile,"计数值==7"); //这句没有做出任何记录
// CommentaryCommentary
SetGlobalVar(0,0); //Ticks计数器归0
}
End
程序中只有第一个FileAppend语句执行了,其后每一次执行FileAppend语句都没有结果。
我百思不得其解,我把大段程序注释掉,化简为上面的程序段,甚至在FileAppend语句后加了Commentary验证,发现FileAppend语句肯定是执行的,但为什么没有记录“计数器==7”呢?
我百思不得其解! 我甚至怀疑FileAppend函数是否在使用变量的情况下有问题,我把MyLogFile变量替换成"C:\\Test4.Log",竟然问题解决了,似乎我证实了FileAppend函数在使用变量时有问题。
我高兴了好一会,我对着程序有看了一遍。或然我感到我犯了一个非常简单的错误,就是以一般编程的思维来理解TB程序执行步骤,也就是在一般编程中,变量一旦初始化,在程序执行中一直有效,直到程序改变它。[color=Red]因此在我的头脑中,MyLogFile的内容始终是"c:\\MyAutoExiter.Log",但实际上它的值在第一个Bar以后都为N/A[/color],自然不可能输出任何内容。
我忽略了我脑海中深深印记的TB执行流程,也就是[color=Red]TB始终是每个Bar执行一遍,然后在实时行情时每个Tick执行一遍程序[/color],因此所有的变量都要重新计算。只有用公共变量能保留数值,或者利用SetTBProfileString和GetTBProfileString对数据库操作能保存字符串值。
用二种办法修改这段程序可解决问题。 方法一:
Vars
String MyLogFile; //日志文件名
Numeric MyTicks(7); //计数值
Begin
If (BarStatus==0)
{
//MyLogFile ="c:\\MyAutoExiter.Log"; //[color=Red]把这条语句移到IF语句之外[/color]
SetGlobalVar(0,0); //Ticks计数器归0
FileAppend(MyLogFile,"启动交易程序 for "+SymbolName+" at "+TimeToString(CurrentTime));
}
MyLogFile ="c:\\MyAutoExiter.Log"; //[color=Red]移过来的语句[/color]
SetGlobalVar(0,GetGlobalVar(0)+1);//计数器增1
If (GetGlobalVar(0)>=MyTicks)
{
FileAppend(MyLogFile,"计数值==7"); //这句没有做出任何记录
// CommentaryCommentary
SetGlobalVar(0,0); //Ticks计数器归0
}
End
[[i] 本帖最后由 efrog 于 2010-5-19 21:25 编辑 [/i]] 方法二(更简单):
Vars
String MyLogFile([color=Red]"c:\\MyAutoExiter.Log"[/color]); //日志文件名。[color=Red]作为变量初始值,每次Tick执行时恢复该值。[/color]
Numeric MyTicks(7); //计数值
Begin
If (BarStatus==0)
{
//MyLogFile ="c:\\MyAutoExiter.Log"; //[color=Red]去掉该语句[/color]
SetGlobalVar(0,0); //Ticks计数器归0
FileAppend(MyLogFile,"启动交易程序 for "+SymbolName+" at "+TimeToString(CurrentTime));
}
SetGlobalVar(0,GetGlobalVar(0)+1);//计数器增1
If (GetGlobalVar(0)>=MyTicks)
{
FileAppend(MyLogFile,"计数值==7"); //这句没有做出任何记录
// CommentaryCommentary
SetGlobalVar(0,0); //Ticks计数器归0
}
End 我原想使用MyLogFile=”C:\\My”+SymbolName+“.Log”; 来针对不同的交易品种来记录交易日志,发生了上述错误后放弃了,但现在想来还是可行的!
有一点建议给TB公司的开发人员,能否像MT4系统一样有一段初始化程序段:
Params
//参数区
Vars
//变量区
[color=Red]Initialize
//初始化程序区,在程序中只执行一遍[/color]
Begin
//循环执行区
End
[[i] 本帖最后由 efrog 于 2010-5-19 21:22 编辑 [/i]] 怎么没人回复?
好贴
彻底让我明白TB的执行流程,谢谢efrog了 请问有人看的懂上面这个程序是用来干嘛的吗? [i=s] 本帖最后由 efrog 于 2011-10-11 11:10 编辑 [/i]
谢谢有人欣赏我的帖子,这是我学习TB的点滴心得,奉献给大家。
这段程序是告诉你:
如果一个变量要所有周期都要使用(如程序中的MyLogFile ="c:\\MyAutoExiter.Log";),那么你要么放在变量的初始化里(如Var String MyLogFile ("c:\\MyAutoExiter.Log");),要么放在程序的If 框架之外。否则的话如放在If (BarSatuts==0) 之内,那么在其他的周期MyLogFile的值实际上就等于N/A,所以发生1楼所看到的现象。明白了吗?
TB的每一个Bar(和Tick)来临后,所有的变量都从头赋值或计算,并不继承上一个Bar的值!!除非使用公共变量。
[color=Red][size=4]2011-10-11增加
这个问题也容易错:[/size][/color]
If (con1 && Con2 && ......)[color=Red];[/color]
{
语句1;
.............;
}
错在If条件后习惯性加了[color=Red]语句分割符分号[/color],结果导致条件内的语句总是被执行,还以为是条件计算错误。 [i=s] 本帖最后由 efrog 于 2010-9-15 20:41 编辑 [/i]
另外使用:
SetGlobalVar(0,GetGlobalVar(0)+1);//计数器增1
If (GetGlobalVar(0)>=MyTicks)
{
SetGlobalVar(0,0); //Ticks计数器归0
}
是为了防止重复发单,信号出现后,如果GV0的值大于7,则发出交易指令,否则等7个Tick。一般5个Tick以后,上一个发出的交易指令结果就返回了,你的账户函数的值已发生了变化,所以要用公共变量控制等7个Tick后处理出现的信号。 你瞒会自娱自乐的,不过 加一个初始化模块是个好建议啊,但是那些闭门造车的人不会理你的 不过给你提个建议啊,千万不要用等多长时间然后处理 这种方法。网络延迟,服务器连不上这种异常经常发生 好贴啊!!! 好贴!确实的小心变量放到if条件语句外的情况,否则N/A不小心因为tb机制原因误导操作 确实新接触TB的人是会忽视这个问题,尽管TB的帮助文档中提到了TB程序的执行过程,但是惯有的编程思维定势还是会导致犯这种错误。谢谢efrog分享! 好贴啊,对楼主很欣赏 好贴,如果一个变量要所有周期都要使用,那么你要么放在变量的初始化里,要么放在程序的If 框架之外。 [quote]我原想使用MyLogFile=”C:\\My”+SymbolName+“.Log”; 来针对不同的交易品种来记录交易日志,发生了上述错 ...
[size=2][color=#999999]efrog 发表于 2010-5-19 21:21[/color] [url=http://www.tradeblazer.net/forum/redirect.php?goto=findpost&pid=49150&ptid=8448][img]http://www.tradeblazer.net/forum/images/common/back.gif[/img][/url][/size][/quote]
建议tb增加这个功能 没太看懂。。 TB没有全局变量,LZ说的初始化的部分。。。。。。。可以用代码解决的问题,又不是写大程序,不需要怎么苛求把 学习中。。。
页:
[1]
2
