追涨杀跌 发表于 2011-6-8 16:55:08

跨周期数据转换函数以及跨周期技术指标调用的实现

本帖最后由 追涨杀跌 于 2011-12-26 14:17 编辑

TB的跨周期调用,以前已经有一些解决方案。但总体来说,使用还不够方便。以前的帖子中Nopain曾提出过一个算法,非常精巧。最近在这个算法的基础上, 把整个实现方法完善了一下。下面把总体思路和函数代码贴出来,请大家试用,也欢迎大家提出修改意见。

总体思路:
1、小周期调用大周期的数据;
2、具体方法是新编一个函数,用来根据小周期下的数据推算出大周期的BAR数据,为了省事,计算时,会将大周期下的开高低收以及成交量和持仓量等数据都算出来,然后将这些数据通过引用参数返回。当然有的朋友可能只需要一个收盘价就可以了,那样的话,可以自行修改这个函数,把多余的数据去掉;
3、返回的大周期数据将以序列变量的形式保留在对应的小周期K线上,以便以后调用;
4、另外为了便于大周期的数据计算出来后的回溯使用,函数会将小周期下当前BAR到大周期下的前一个BAR的最后一个小周期BAR需要回溯的BAR数目,作为函数的结果返回。这句话,不容易描述清楚,估计大家听起来也费力,但没关系,后面用例子来解释,知道这回事就行了。
5、另外还增加了一个返回值(也是通过引用参数返回),表示的是当前小周期K线对应的大周期K线在整个大周期中的索引值。举例来说,5分钟图,样本数300,那转换成30分钟周期图,总共应该是50根K线,那最新一根5分钟图对应的30分钟K线在整个30分钟图中的索引值就应该是49(类似CurrentBar 0-49);

好,其他先不废话,把代码贴出来,再举几个例子。

新建用户函数MtBar, 返回值为数值类型,代码如下:
Params
        Numeric TimeFrame(1440);   
        // 目标时间周期:月线=40320,周线=10080,日线=1440,4小时线=240
        // 其他1小时内的周期等于相应的分钟数,如:1小时=60, 30分钟=30。。。
        // 支持不规则分钟数,如3分钟,8分钟,之类都行
        
        Numeric BarsBack(1);
        // 目标时间周期BAR偏移:
        // 1--表示将目标时间周期下的前1根K线数据作为与当前Bar对应的目标时间周期下的K线数据
        // 0--表示将目标时间周期下的截止到目前为止的数据转换为与当前BAR对应的目标时间周期下K线数据
        
        NumericRef oCurBar;                 // 目标时间周期下的Bar索引
        NumericRef oOPenHT;         // 目标时间周期下的开盘价
        NumericRef oHighHT;         // 目标时间周期下的最高价
        NumericRef oLowHT;          // 目标时间周期下的最低价
        NumericRef oCloseHT;        // 目标时间周期下的收盘价
        NumericRef oVolHT;          // 目标时间周期下的成交量
        NumericRef oOpenIntHT;      // 目标时间周期下的持仓量

Vars
        NumericSeries barCnt;
        NumericSeries CurBar;
        NumericSeries barCntSum;
        NumericSeries OpenHT;
        NumericSeries HighHT;
        NumericSeries LowHT;
        NumericSeries CloseHT;
        NumericSeries VolHT;
        NumericSeries OpenIntHT;
        Numeric CurTime;
        Numeric PreTime;
        bool condition(false);
        Numeric i;
Begin
        If (TimeFrame == 40320)                 // 月线
        {
                CurTime = Month;
                PreTime = Month;
        }
        Else If (TimeFrame == 10080)                        // 周线
        {
                CurTime = IntPart(DateDiff(19700105,Date)/7);
                PreTime = IntPart(DateDiff(19700105,Date)/7);
        }
        Else                                                                        // 其他时间周期
        {
                CurTime = IntPart((DateDiff(19700105,date)*1440 + Hour*60 + Minute)/TimeFrame);
                PreTime = IntPart((DateDiff(19700105,date)*1440 + Hour*60 + Minute)/TimeFrame);
        }
        condition = CurTime != PreTime;

        If (CurrentBar==0)                // 如果是第一根Bar, CurBar=0
        {
                barCnt = 0;
                CurBar = 0;
                OpenHT = Open;
                HighHT = High;
                LowHT = Low;
                CloseHT = Close;
                VolHT = Vol;
                OpenIntHT = OpenInt;
        }
        Else
        {
                If(Condition)               
                // 如果在目标周期下,属于另一根K线,则CurBar加1
                {
                        barCnt = 1;
                        CurBar = CurBar + 1;
                        OpenHT = Open;
                        HighHT = High;
                        LowHT = Low;
                        VolHT = Vol;
                }Else
                // 如果在目标周期下,属于同一根K线,则CurBar不变,但最高价和最低价要记录价格的变化,成交量要累加
                {
                        barCnt = barCnt + 1;
                        CurBar = CurBar;
                        OpenHT = OpenHT;
                        HighHT = Max(HighHT,High);
                        LowHT = Min(LowHT,Low);
                        VolHT = VolHT + Vol;
                }
                // 收盘价和持仓量总是取最新值
                CloseHT = Close;
                OpenIntHT = OpenInt;
        }
        
        // 上面的程序,在每根小周期的K线上,记录了它所属的大时间周期下的开高低收等值的变化。
        // 接下来,要把在大的时间周期级别上,属于同一根K线的开高低收这些数据,记录在这一组小周期K线的最后一根上。
        barCntSum = barCnt ;
        If(BarsBack == 0)
        // 如果Bar偏移参数为0,则取每根小周期K线上保留的大时间周期截止到这根小周期K线为止的BAR数据
        {
                barCntSum = 0 ;
        }Else If(BarsBack == 1)
        // 如果Bar偏移参数为1,则取大时间周期的上一根K线的BAr数据
        {
                barCntSum = barCnt ;
        }Else
        // 如果BAR偏移参数为其他,则取大时间周期的指定偏移后的那根K线的BAR数据
        {
                For i = 2 To BarsBack
                {
                        barCntSum = barCntSum + barCnt;
                }
        }

        // 最后将相应的K线数据作为引用参数返回
        oCurBar = CurBar;
        oOpenHT = OpenHT;
        oHighHT = HighHT;
        oLowHT = LowHT;
        oCloseHT = CloseHT;
        oVolHT = VolHT;
        oOpenIntHT = OpenIntHT;
        Return barCnt;
End

追涨杀跌 发表于 2011-6-8 17:16:25

忘了说一句,以上代码是在TB V4中编写与调试的。

接下来,我们来实现跨周期的求和函数MtSummation,上面的函数中特地返回了一个值oCurBar,就是我上面提到的大周期下的BAR索引值,就是想为实现MtSummationFC留下的伏笔,等以后有时间再解决。现在先还是用最笨的循环累加的算法。
Params
        NumericSeries Price(1);
        NumericSeries BarCnt(0);
        Numeric Length(10);
Vars
        NumericSeries SumValue(0);
        Numeric i;
        Numeric j(0);
Begin
        SumValue = 0;
        For i = 1 to Length
        {
                If (Price <> InvalidNumeric)
                {
                        SumValue = SumValue + Price;
                        j = j + BarCnt;
                }
                else Break;
        }
        Return SumValue;
End

追涨杀跌 发表于 2011-6-8 17:22:36

接下来,就可以实现计算跨周期简单移动平均的函数MtMa。
Params
        Numeric TimeFrame(1440);        // 目标时间周期参数,参数说明参见MtBar
        Numeric BarsBack(1);                // 目标时间周期BAR偏移参数,说明见MtBar函数
        Numeric Length(10);                        // 均线周期
        NumericRef oMA;             // 以目标时间周期下的K线数据计算出的移动平均线
Vars
        NumericSeries mtBarCnt;
        NumericSeries mtClose;
        Numeric refCurBar;
        Numeric refOpen;
        Numeric refHigh;
        Numeric refLow;
        Numeric refClose;
        Numeric refVol;
        Numeric refOpenInt;
       
        Numeric SumValue(0);
        Numeric i;
        Numeric j(0);
Begin
        mtBarCnt = MtBar(TimeFrame,BarsBack,refCurBar,refOpen,refHigh,refLow,refClose,refVol,refOpenInt);
        mtClose = refClose;

        SumValue = MtSummation(mtClose,mtBarCnt,Length);
        oMA = SumValue/Length;
        Return mtBarCnt;
End

追涨杀跌 发表于 2011-6-8 17:51:14

现在可以举个例子来说明,怎么用上面的几个函数来做交易策略了。假如我们的策略如下:
1、我们以日线的均线交叉来判断大趋势,然后在5分钟图上来做交易;
2、日线的短期均线上穿长期均线,则只做多,不做空;反之只做空,不做多;
3、确定了大趋势后,我们再根据5分钟图来判断小趋势,以决定进场时机。我们仍然用均线来判断,在多头大趋势下,如果5分钟的短期均线上穿长期均线,则进场做多,反穿出场,但不反手做空;在空头大趋势下,类似;
我们在5分钟图上调用刚才的函数的来实现。新建公式应用TestMtMa,代码如下:
Params
        Numeric TimeFrame(1440);        // 目标时间周期参数,参数说明参见MtBar
        Numeric BarsBack(1);                // 目标时间周期BAR偏移参数,说明见MtBar函数

        Numeric Length1(10);                // 大周期的短期均线周期               
        Numeric Length2(20);                // 大周期的长期均线周期
        Numeric Length3(10);                // 小周期的短期均线周期
        Numeric Length4(20);                // 小周期的长期均线周期
        Numeric Lots(1);
Vars
        NumericSeries MA1;
        NumericSeries MA2;
        Numeric oMA1;
        Numeric oMA2;

        NumericSeries MA3;
        NumericSeries MA4;
Begin
        MtMa(TimeFrame,BarsBack,Length1,oMA1);
        MA1 = oMA1;
        PlotNumeric("MA1",MA1);
        MtMa(TimeFrame,BarsBack,Length2,oMA2);
        MA2 = oMA2;
        PlotNumeric("MA2",MA2);
        MA3 = AverageFC(Close,Length3);
        MA4 = AverageFC(Close,Length4);
        PlotNumeric("MA3",MA3);
        PlotNumeric("MA4",MA4);
       
       
        If (MA1>MA2)                // 大周期均线金叉,多头趋势
        {
                if (MarketPosition!=1 and MA3>MA4)
                {
                        Buy(Lots,Open);
                }
                if (MarketPosition==1 and MA3<MA4)
                {
                        Sell(Lots,Open);
                }
        }
        If (MA1<MA2)                // 大周期均线死叉,空头趋势
        {
                if (MarketPosition!=-1 and MA3<MA4)
                {
                        SellShort(Lots,Open);
                }
                if (MarketPosition==-1 and MA3>MA4)
                {
                        BuyToCover(Lots,Open);
                }
        }
End

追涨杀跌 发表于 2011-6-8 17:53:29

如果上面的策略,我们不想用日线均线来判断大趋势,而改用小时线来判断,则只要将参数TimeFrame改为60, 就可以了。

道勤 发表于 2011-6-12 20:25:09

本帖最后由 道勤 于 2011-6-12 20:58 编辑

很好很强大,慢慢学习。:D   使用起来非常方便啊,只要修改时间参数就行了,十分感谢!!

haomai01 发表于 2011-6-13 01:23:20

请问怎么在小时K线调用DMI的指标

haomai01 发表于 2011-6-13 01:23:53

请问怎么在小时K线调用日线DMI的指标

追涨杀跌 发表于 2011-6-13 01:40:52

谢谢道勤的鼓励! 继续把其他几个常用指标的跨周期函数贴出来。
新建MtMacd函数,代码如下:
Params
        Numeric TimeFrame(1440);        // 目标时间周期参数,参数说明参见MtBar
        Numeric BarsBack(1);         // 目标时间周期BAR偏移参数,说明见MtBar函数
        Numeric FastLength(12);
        Numeric SlowLength(26);
        Numeric MACDLength(9);
       
        NumericRef oMACDValue;      // 以目标时间周期下的K线数据计算出的MACDValue
        NumericRef oAvgMACD;        // 以目标时间周期下的K线数据计算出的AvgMACD

Vars
        NumericSeries mtBarCnt;
        NumericSeries mtCurBar;
        NumericSeries mtClose;
        Numeric refCurBar;
        Numeric refOpen;
        Numeric refHigh;
        Numeric refLow;
        Numeric refClose;
        Numeric refVol;
        Numeric refOpenInt;
       
        NumericSeries MACDValue;
        NumericSeries AvgMACD;
        Numeric sFcactor;
        NumericSeries XAvgValue1;
        NumericSeries XAvgValue2;
       
Begin

        mtBarCnt = MtBar(TimeFrame,BarsBack,refCurBar,refOpen,refHigh,refLow,refClose,refVol,refOpenInt);
        mtCurBar = refCurBar;
        mtClose = refClose;
       
        sFcactor = 2 / ( FastLength + 1 );
        if (MtCurBar == 0 || XAvgValue1 == InvalidNumeric) XAvgValue1 = mtClose;
        else XAvgValue1 = XAvgValue1 + sFcactor * ( mtClose - XAvgValue1 ) ;

        sFcactor = 2 / ( SlowLength + 1 );
        if (MtCurBar == 0 || XAvgValue2 == InvalidNumeric) XAvgValue2 = mtClose;
        else XAvgValue2 = XAvgValue2 + sFcactor * ( mtClose - XAvgValue2 ) ;

        MACDValue = XAvgValue1 - XAvgValue2;

        sFcactor = 2 / ( MACDLength + 1 );
        if (MtCurBar == 0 || AvgMACD == InvalidNumeric) AvgMACD = MACDValue;
        else AvgMACD = AvgMACD + sFcactor * ( MACDValue - AvgMACD ) ;

        oMACDValue = MACDValue;
        oAvgMACD = AvgMACD;
        return mtBarCnt;
End

追涨杀跌 发表于 2011-6-13 01:57:13

编译好上面的MtMacd函数后,以后就可以随时通过调用这个函数来显示跨周期的MACD指标,以及在小周期上根据大周期的MACD指标进行交易,下面继续举个例子,也是在V4中实现,把指标和交易指令放在一个公式应用中,注意要在“属性设置”中,设置成“子图显示”。这次简单点,没有做成多周期共振,只是简单地在5分钟图表上,根据30分钟的MACD指标交叉来进行交易,代码如下:
Params
        Numeric TimeFrame(30);                // 目标时间周期参数,参数说明参见MtBar
        Numeric BarsBack(1);                 // 目标时间周期BAR偏移参数,说明见MtBar函数
        Numeric FastLength(12);
        Numeric SlowLength(26);
        Numeric MACDLength(9);
    Numeric Lots(1);
Vars
        NumericSeries MACDValue;
        NumericSeries AvgMACD;
        NumericSeries MACDDiff;
        Numeric ooMACDValue;
        Numeric ooAvgMACD;
        Numeric PreBar;
Begin
        PreBar = MtMACD(TimeFrame,BarsBack,FastLength,SlowLength,MACDLength,ooMACDValue,ooAvgMACD);
        MACDVAlue = ooMACDValue;
        AvgMACD = ooAvgMACD;
        MACDDiff = MACDValue - AvgMACD;

        PlotNumeric("MACD",MACDValue);
        PlotNumeric("MACDAvg",AvgMACD);
        If (MACDDiff >= 0)       
                PlotNumeric("MACDDiff",MACDDiff,0,Red);
        Else
                PlotNumeric("MACDDiff",MACDDiff,0,Green);
        PlotNumeric("零线",0);

        If (MacdDiff<0 and MacdDiff>0)
        {
                Buy(Lots,Open);
        }
        If (MacdDiff>0 and MacdDiff<0)
        {
                SellShort(Lots,Open);
        }
End
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 跨周期数据转换函数以及跨周期技术指标调用的实现