开拓者期货期权程序化系统交易论坛

标题: 一个容易犯得编程错误 [打印本页]

作者: efrog    时间: 2010-5-19 20:28:40     标题: 一个容易犯得编程错误

下面程序是我从程序中摘取的片段,它编译正确,但执行不是我要的结果。
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:17

我甚至怀疑FileAppend函数是否在使用变量的情况下有问题,我把MyLogFile变量替换成"C:\\Test4.Log",竟然问题解决了,似乎我证实了FileAppend函数在使用变量时有问题。
我高兴了好一会,我对着程序有看了一遍。或然我感到我犯了一个非常简单的错误,就是以一般编程的思维来理解TB程序执行步骤,也就是在一般编程中,变量一旦初始化,在程序执行中一直有效,直到程序改变它。因此在我的头脑中,MyLogFile的内容始终是"c:\\MyAutoExiter.Log",但实际上它的值在第一个Bar以后都为N/A,自然不可能输出任何内容。
我忽略了我脑海中深深印记的TB执行流程,也就是TB始终是每个Bar执行一遍,然后在实时行情时每个Tick执行一遍程序,因此所有的变量都要重新计算。只有用公共变量能保留数值,或者利用SetTBProfileString和GetTBProfileString对数据库操作能保存字符串值。

用二种办法修改这段程序可解决问题。
作者: efrog    时间: 2010-5-19 20:57:35

方法一:

Vars
   String MyLogFile; //日志文件名
   Numeric MyTicks(7); //计数值
Begin
   If (BarStatus==0)
   {        
       //MyLogFile ="c:\\MyAutoExiter.Log"; //把这条语句移到IF语句之外
       SetGlobalVar(0,0); //Ticks计数器归0
       FileAppend(MyLogFile,"启动交易程序 for "+SymbolName+" at "+TimeToString(CurrentTime));
   }
   MyLogFile ="c:\\MyAutoExiter.Log"; //移过来的语句
   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:25 编辑 ]
作者: efrog    时间: 2010-5-19 21:01:47

方法二(更简单):
Vars
   String MyLogFile("c:\\MyAutoExiter.Log"); //日志文件名。作为变量初始值,每次Tick执行时恢复该值。
   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
作者: efrog    时间: 2010-5-19 21:21:26

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

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

Begin
   //循环执行区
End

[ 本帖最后由 efrog 于 2010-5-19 21:22 编辑 ]
作者: leevolvo    时间: 2010-7-27 15:02:30

怎么没人回复?
好贴
彻底让我明白TB的执行流程,谢谢efrog了
作者: bjcifco    时间: 2010-9-15 15:21:02

请问有人看的懂上面这个程序是用来干嘛的吗?
作者: efrog    时间: 2010-9-15 20:29:32

本帖最后由 efrog 于 2011-10-11 11:10 编辑

谢谢有人欣赏我的帖子,这是我学习TB的点滴心得,奉献给大家。
这段程序是告诉你:
如果一个变量要所有周期都要使用(如程序中的MyLogFile ="c:\\MyAutoExiter.Log";),那么你要么放在变量的初始化里(如Var String MyLogFile ("c:\\MyAutoExiter.Log");),要么放在程序的If 框架之外。否则的话如放在If (BarSatuts==0) 之内,那么在其他的周期MyLogFile的值实际上就等于N/A,所以发生1楼所看到的现象。明白了吗?
TB的每一个Bar(和Tick)来临后,所有的变量都从头赋值或计算,并不继承上一个Bar的值!!除非使用公共变量。

2011-10-11增加
这个问题也容易错:

If (con1 && Con2 && ......);
{
   语句1;
  .............;
}
错在If条件后习惯性加了语句分割符分号,结果导致条件内的语句总是被执行,还以为是条件计算错误。
作者: efrog    时间: 2010-9-15 20:40:33

本帖最后由 efrog 于 2010-9-15 20:41 编辑

另外使用:
  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:14

你瞒会自娱自乐的,不过 加一个初始化模块是个好建议啊,但是那些闭门造车的人不会理你的
作者: zhudaqun    时间: 2010-9-16 09:21:42

不过给你提个建议啊,千万不要用等多长时间然后处理 这种方法。网络延迟,服务器连不上这种异常经常发生
作者: herbert_tan    时间: 2010-12-14 21:09:13

好贴啊!!!
作者: bluefire999    时间: 2011-3-9 10:27:03

好贴!确实的小心变量放到if条件语句外的情况,否则N/A不小心因为tb机制原因误导操作
作者: yishengu    时间: 2011-4-3 22:02:36

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

好贴啊,对楼主很欣赏
作者: 读书山林    时间: 2011-8-10 12:10:09

好贴,如果一个变量要所有周期都要使用,那么你要么放在变量的初始化里,要么放在程序的If 框架之外。
作者: 读书山林    时间: 2011-8-10 12:11:53

我原想使用MyLogFile=”C:\\My”+SymbolName+“.Log”; 来针对不同的交易品种来记录交易日志,发生了上述错 ...
efrog 发表于 2010-5-19 21:21



    建议tb增加这个功能
作者: lzl563    时间: 2011-8-11 00:33:16

没太看懂。。
作者: alex647l    时间: 2011-8-11 09:11:17

TB没有全局变量,LZ说的初始化的部分。。。。。。。可以用代码解决的问题,又不是写大程序,不需要怎么苛求把
作者: lhmindson    时间: 2011-9-4 20:55:33

学习中。。。
作者: skyfis    时间: 2011-10-4 15:34:54

非常欣赏efrog天天向上的精神,要写出专业的交易系统,出了对技术面的总结提炼,还要包括对开发平台的深入了解。
工欲善其事必先利其器。

作者: Amymylove    时间: 2011-10-10 09:57:12

马克留名学习之
作者: xiaoshansanzhi    时间: 2011-11-2 09:37:05

好贴,对于我们这些初学者来说这样的讨论太有意义了,谢谢LZ
作者: slarkmonk    时间: 2011-11-2 09:38:43

这个帖子必须顶啊...
作者: goolybody    时间: 2011-11-2 10:58:55

简单的方法: Stringseries MyLogFile;
作者: 蔡宛宏    时间: 2011-12-16 17:50:18

谢谢LZ分享




欢迎光临 开拓者期货期权程序化系统交易论坛 (http://bbs.tb18.net/) Powered by Discuz! X2