系统交易论坛 - 开拓者期货自动交易平台's Archiver

efrog 发表于 2010-5-19 20:28

一个容易犯得编程错误

下面程序是我从程序中摘取的片段,它编译正确,但执行不是我要的结果。
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”呢?
我百思不得其解!

efrog 发表于 2010-5-19 20:54

我甚至怀疑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对数据库操作能保存字符串值。

用二种办法修改这段程序可解决问题。

efrog 发表于 2010-5-19 20:57

方法一:

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]]

efrog 发表于 2010-5-19 21:01

方法二(更简单):
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

efrog 发表于 2010-5-19 21:21

我原想使用MyLogFile=”C:\\My”+SymbolName+“.Log”; 来针对不同的交易品种来记录交易日志,发生了上述错误后放弃了,但现在想来还是可行的!

有一点建议给TB公司的开发人员,能否像MT4系统一样有一段初始化程序段:
Params
   //参数区
Vars
   //变量区
[color=Red]Initialize
   //初始化程序区,在程序中只执行一遍[/color]
Begin
   //循环执行区
End

[[i] 本帖最后由 efrog 于 2010-5-19 21:22 编辑 [/i]]

leevolvo 发表于 2010-7-27 15:02

怎么没人回复?
好贴
彻底让我明白TB的执行流程,谢谢efrog了

bjcifco 发表于 2010-9-15 15:21

请问有人看的懂上面这个程序是用来干嘛的吗?

efrog 发表于 2010-9-15 20:29

[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],结果导致条件内的语句总是被执行,还以为是条件计算错误。

efrog 发表于 2010-9-15 20:40

[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后处理出现的信号。

zhudaqun 发表于 2010-9-16 09:15

你瞒会自娱自乐的,不过 加一个初始化模块是个好建议啊,但是那些闭门造车的人不会理你的

zhudaqun 发表于 2010-9-16 09:21

不过给你提个建议啊,千万不要用等多长时间然后处理 这种方法。网络延迟,服务器连不上这种异常经常发生

herbert_tan 发表于 2010-12-14 21:09

好贴啊!!!

bluefire999 发表于 2011-3-9 10:27

好贴!确实的小心变量放到if条件语句外的情况,否则N/A不小心因为tb机制原因误导操作

yishengu 发表于 2011-4-3 22:02

确实新接触TB的人是会忽视这个问题,尽管TB的帮助文档中提到了TB程序的执行过程,但是惯有的编程思维定势还是会导致犯这种错误。谢谢efrog分享!

allin 发表于 2011-4-7 23:13

好贴啊,对楼主很欣赏

读书山林 发表于 2011-8-10 12:10

好贴,如果一个变量要所有周期都要使用,那么你要么放在变量的初始化里,要么放在程序的If 框架之外。

读书山林 发表于 2011-8-10 12:11

[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增加这个功能

lzl563 发表于 2011-8-11 00:33

没太看懂。。

alex647l 发表于 2011-8-11 09:11

TB没有全局变量,LZ说的初始化的部分。。。。。。。可以用代码解决的问题,又不是写大程序,不需要怎么苛求把

lhmindson 发表于 2011-9-4 20:55

学习中。。。

页: [1] 2

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.