最近在开始用AM做回测和编写指标,说明书和视频什么的大约浏览了一遍。有些问题比较困惑,请前辈指点迷津。 1.作为INDICATOR的AFL的调用时机的问题,我把实时的执行频率在tools->preference->intraday 里的realtime chart refresh interval 设为5秒,然后用简单的afl来作为INDICATOR来运行跟踪,发现每个AFL在5秒内被执行了2次,里面我跟踪了BARCOUT这个数,居然这2次的值都不同,下面是log 00004687 10:30:09.875 [3896] 00004688 10:30:09.875 [3896] 00004689 10:30:14.796 [3896] Barcount1= 6045 Time interVal:60 00004690 10:30:14.796 [3896] Filename= myTrend 00004691 10:30:14.796 [3896] VarPfx =myTrendVer1_0 00004692 10:30:14.796 [3896] Barcount2= 6045 Time interVal:300 00004693 10:30:14.796 [3896] myTrend =DOWN 00004694 10:30:14.812 [3896] Bid=257.2,Ask=257.25,Last=257.25,Vol=6 00004695 10:30:14.812 [3896] Bid=96.54,Ask=96.56,Last=96.56,Vol=1 00004696 10:30:14.812 [3896] 00004697 10:30:14.812 [3896] 00004698 10:30:14.875 [3896] Barcount1= 5814 Time interVal:60 00004699 10:30:14.875 [3896] Filename= myTrend 00004700 10:30:14.875 [3896] VarPfx =myTrendVer1_0 00004701 10:30:14.875 [3896] Barcount2= 5814 Time interVal:300 00004702 10:30:14.875 [3896] myTrend =DOWN 00004703 10:30:14.875 [3896] Bid=257.2,Ask=257.25,Last=257.25,Vol=6 00004704 10:30:14.875 [3896] Bid=96.54,Ask=96.56,Last=96.56,Vol=1 00004705 10:30:14.875 [3896] 00004706 10:30:14.875 [3896] 00004707 10:30:19.796 [3896] Barcount1= 6045 Time interVal:60 00004708 10:30:19.796 [3896] Filename= myTrend 00004709 10:30:19.796 [3896] VarPfx =myTrendVer1_0 00004710 10:30:19.796 [3896] Barcount2= 6045 Time interVal:300 00004711 10:30:19.812 [3896] myTrend =DOWN 00004712 10:30:19.812 [3896] Bid=257.2,Ask=257.25,Last=257.25,Vol=2 00004713 10:30:19.812 [3896] Bid=96.54,Ask=96.56,Last=96.56,Vol=1 00004714 10:30:19.812 [3896] 00004715 10:30:19.812 [3896] 00004716 10:30:19.875 [3896] Barcount1= 5814 Time interVal:60 00004717 10:30:19.875 [3896] Filename= myTrend 00004718 10:30:19.875 [3896] VarPfx =myTrendVer1_0 00004719 10:30:19.875 [3896] Barcount2= 5814 Time interVal:300 00004720 10:30:19.875 [3896] myTrend =DOWN 00004721 10:30:19.875 [3896] Bid=257.2,Ask=257.25,Last=257.25,Vol=2 00004722 10:30:19.875 [3896] Bid=96.54,Ask=96.56,Last=96.56,Vol=1 00004723 10:30:19.875 [3896] 00004724 10:30:19.875 [3896] 谁能解释下为什么barCOUNT会不同吗? 2.关于AFL做为indicator,作为scan和作为explore的不同,有前辈总结下吗? 3.关于数组实在很困惑,就是在实时的行情里,如果取当前值是否一定要用条件判断是否最后一个BAR,如果切换时间周期,一定用TimeFrameSet函数,而且要TimeFramerestore 吗,那在explore的回测中呢,是否也是这样?要知道在回测时,各个框架的数据应该是可以随便用的呀?是不是我还有什么资料没有看到?
自己顶一下。 1.关于第一个问题,就是5秒钟内执行2边的问题,可能是设定了5秒后,在设定框里只选了“APPLY”,没选“OK”的问题,BARCOUNT有变问题还是不知道。 2. 还是一头雾水,我的理解:AFL的关于数组的操作只是定义了数组之间的逻辑运算关系,就像SQL语句里那样的。至于数组内的值,只是AFL的解释引擎在该数组被引用时才根据逻辑关系计算,这个计算是在整个BARCOUNT范围内进行的,不知道这么理解对不对? 3.关于时间框架,还是不清楚,比如在SCAN和EXPLORE内就不是很方便用TimeFrame这族函数? 前辈们出来指导下吧?ESPRESSO大哥?
“作为INDICATOR的AFL的调用时机的问题,我把实时的执行频率在tools->preference->intraday 里的realtime chart refresh interval 设为5秒” 我从来没有改过这个设置,这似乎只是控制AB刷新显示的频率,而不是执行AFL的频率。 不太清楚你的AFL里面写的代码做什么,是指标呢,还是回测? indicator和 scan/exploration 的触发方式完全不一样,indicator是每次收到一个tick时被触发,而scan/exploration则是手动去触发(当然也可以设置为最快每1分钟扫描一次) 实时模式下,如果你的指标同时放在5min和1HR图上,这个时候进来一个tick,AB会自动把这两个图上的指标AFL代码都执行一遍 回测模式下呢,就不存在有tick更新的问题,AB只是根据你指定的周期去运行。(菜单: Analysis -> Automatic Analysis ,按"Setting..."按钮, 有个叫做Periodicity的下拉列表)。例如,你选择在1 hour周期上面测试,那么你的AFL代码就会使用1 hour的数据。 这就涉及到你的另外一个问题,在scan/exploration时,你的基本时间周期在periodicity里面设置,但是也可以用TimeFrame函数去获得其他周期的数据。 比如,你的AFL基本时间周期是1 hour,需要使用到4hr, daily的数据,这个时候可以TimeFrameSet去获得相应数据,然后TimeFrameRestore恢复回来(好像是这样子,你可以去看一下文档)。
用于indicator和scan的一些代码其实是可以重用的,比如我的系统有3个AFL,一个是indicator,用于在AB里面实时显示信号,一个是exploration用于生成交易信号(可以设定每n分钟运行一次),另一个也是exploration,用于做回测。 这3个AFL里面生成信号方面的代码是一样的。 AB里面有个函数用于判断其运行的模式是indicator,scan/exploration等 if (Status("action") == actionPortfolio) { } else { } STATUS - get run-time AFL status information http://www.amibroker.com/guide/afl/status.html
谢谢espresso大哥的指点,我觉得有点理解了,函数还是要全部看完的。嘿嘿。 还有一些问题想请大哥指点,比如无论在indicator和scan和explore中经常要需要先前的bar的信号,而又不确切的知道这个信号在多长时间以前,这种信号在实时运行的时候可以用STATIC变量保存,以后取,但在scan和explore中似乎脚本只运行一次,这个问题如何解决?怎么回测这样的策略呢?
其实只要理解了AFL基于数组工作的原理就比较容易了,不管是实时扫描还是回测,都是在一个for循环里面,实时扫描的时候可能只关心最近10个或20个bar,回测则在过去1个月,1年的bar上面运行你的策略。 给你我自己使用的代码模板。 其他的任何信号或变量都可以放在一个相应的数组里面,比如我下面的代码里面就用数组DatetimeArr和FirstBarFlag保存每个bar对应的时间和一个标记。 Code: DatetimeArr = DateTime(); // array FirstBarFlag = Status("firstbarinrange"); // array LastBarFlag = Status("lastbarinrange"); // array DebugOn = 1; // flag bStart = False; // flag //for(i = BarCount - 50; i < BarCount; i++) { // for real-time scan/explore //for(i = BarCount - nBackRange; i < BarCount; i++) { // for real-time scan/explore for(i = 1; i < BarCount; i++) { //if(DebugOn) _TRACE("FirstBarFlag[" + i + "]=" + FirstBarFlag[i]); if (FirstBarFlag[i] == 1) { if(DebugOn) _TRACE("SIGNAL: first bar in range found"); bStart = True; //if(ExecTrace) _TRACE("ExecTrace=[Main file loop started processing]"); } // start calculation only within specified range if (bStart == False) continue; ///////////////////////////////////////////////////////////////////// // Your real-time scan/exploration or backtesting code here ///////////////////////////////////////////////////////////////////// //if(DebugOn) _TRACE("LastBarFlag[" + i + "]=" + LastBarFlag[i]); if (LastBarFlag[i] == 1) { if(DebugOn) _TRACE("SIGNAL: last bar in range found"); bStart = False; //if(ExecTrace) _TRACE("ExecTrace=[Main file loop stopped processing]"); break; // break the for loop } } // End of for loop on each bar
大哥又贡献了一个思路,我用比较笨的办法就是FOR循环遍历了整个BAR序列后,还是用赋值的方法解决了我上个帖子提得问题,后来我又看到了一个函数叫FLIP(array1,array2),其作用就是保持第一个信号,直到第2个信号,和exrem作用相反,可能是我想要的。 觉得思路转向数组的话,经常会把数据的横向序列和纵向序列(切面)搞混,希望早点适应。 谢谢大哥的再次指点,有时前辈的一句话,真的是要节约很多黑暗中的行程。
espresso老师,你好! 看了你这里的回帖,感觉你在amibroker方面修行精深、高山仰止! 我近来在学习amibroker,总是只见树木,不见森林。请老师诠释一下:scan, exploration 和 backtest之间的关系和区别,使用的先后顺序,以及各自使用的scenario。先谢了!!
多谢espresso兄的回复!确实,我上面提的问题非一两句话能讲清楚的,看来espresso兄的功力果然不浅,我希望看到的就是你对使用Amibroker/AFL使用的领悟,特别是在backtest, scan 和 explore的应用上,可以不拘形式!期待你的新贴。谢谢了
终于写完,放在下面单独帖子里面: 指标(indicator),回测(backtesting),和扫描(scan/exploration)的简介及入门链接 http://www.hylt.net/vb/showthread.php?t=32133