关于作为INDICATOR的AFL的调用时机和几个值

Discussion in 'AmiBroker' started by wangjuny, Feb 25, 2011.

  1. 最近在开始用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的回测中呢,是否也是这样?要知道在回测时,各个框架的数据应该是可以随便用的呀?是不是我还有什么资料没有看到?
     
  2. 自己顶一下。
    1.关于第一个问题,就是5秒钟内执行2边的问题,可能是设定了5秒后,在设定框里只选了“APPLY”,没选“OK”的问题,BARCOUNT有变问题还是不知道。
    2. 还是一头雾水,我的理解:AFL的关于数组的操作只是定义了数组之间的逻辑运算关系,就像SQL语句里那样的。至于数组内的值,只是AFL的解释引擎在该数组被引用时才根据逻辑关系计算,这个计算是在整个BARCOUNT范围内进行的,不知道这么理解对不对?
    3.关于时间框架,还是不清楚,比如在SCAN和EXPLORE内就不是很方便用TimeFrame这族函数?
    前辈们出来指导下吧?ESPRESSO大哥?
     
  3. “作为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恢复回来(好像是这样子,你可以去看一下文档)。
     
  4. 用于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
     
  5. 谢谢espresso大哥的指点,我觉得有点理解了,函数还是要全部看完的。嘿嘿。
    还有一些问题想请大哥指点,比如无论在indicator和scan和explore中经常要需要先前的bar的信号,而又不确切的知道这个信号在多长时间以前,这种信号在实时运行的时候可以用STATIC变量保存,以后取,但在scan和explore中似乎脚本只运行一次,这个问题如何解决?怎么回测这样的策略呢?
     
  6. 其实只要理解了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
    
    
     
  7. 大哥又贡献了一个思路,我用比较笨的办法就是FOR循环遍历了整个BAR序列后,还是用赋值的方法解决了我上个帖子提得问题,后来我又看到了一个函数叫FLIP(array1,array2),其作用就是保持第一个信号,直到第2个信号,和exrem作用相反,可能是我想要的。
    觉得思路转向数组的话,经常会把数据的横向序列和纵向序列(切面)搞混,希望早点适应。
    谢谢大哥的再次指点,有时前辈的一句话,真的是要节约很多黑暗中的行程。
     
  8. 呵呵,不用客气。其实我对AFL的编程就是能够满足自己的需求即可,比较倾向于使用一些简单明了的东西,太复杂的东西不是学不会,而是有时候觉得太复杂的东西可靠性似乎不够,哈哈
     
  9. espresso老师,你好!

    看了你这里的回帖,感觉你在amibroker方面修行精深、高山仰止!

    我近来在学习amibroker,总是只见树木,不见森林。请老师诠释一下:scan, exploration 和 backtest之间的关系和区别,使用的先后顺序,以及各自使用的scenario。先谢了!!
     
  10. 楼上这位兄弟过奖了,我其实对AB/AFL的东西也是现学现用。你上面问的问题一两句讲不清楚,我另开个帖子说这个吧。这几天有点忙,抽空就写点。
     
  11. 多谢espresso兄的回复!确实,我上面提的问题非一两句话能讲清楚的,看来espresso兄的功力果然不浅,我希望看到的就是你对使用Amibroker/AFL使用的领悟,特别是在backtest, scan 和 explore的应用上,可以不拘形式!期待你的新贴。谢谢了