龙哥量化:国外著名交易策略:R-Breaker日内交易策略

龙哥微信:Long622889  
代写技术指标_选股公式: 通达信,同花顺,东方财富,大智慧,文华,博易,KT交易师
代写期货量化策略:TB交易开拓者,文华8,金字塔量化

 

本篇是我研究策略的时候, 找到的一篇写的高质量文章,策略思路说的非常清晰明了,值得学习,R-Breaker策略也很经典, 转载收藏学习 ,

本篇,我用TBquant3,交易开拓者软件

我计划研究三个版本,原版, 国内期货版,etf版T+1

 

原文地址:https://www.vnpy.com/forum/topic/1597?page=1

原文,及策略思路:

R-Breaker是一种中高频的日内交易策略,这个策略也长期被Future Truth杂志评为最赚钱的策略之一。R-Breaker策略结合了趋势和反转两种交易方式,所以交易机会相对较多,比较适合日内1分钟K线或者5分钟K线级别的数据。

R-Breaker的策略逻辑由以下4部分构成:

 

1)计算6个目标价位

根据昨日的开高低收价位计算出今日的6个目标价位,按照价格高低依次是:

  • 突破买入价(Bbreak)
  • 观察卖出价(Ssetup)
  • 反转卖出价(Senter)
  • 反转买入价(Benter)
  • 观察买入价(Bsetup)
  • 突破卖出价(Sbreak)

他们的计算方法如下:(其中a、b、c、d为策略参数)

  • 观察卖出价(Ssetup)= High + a * (Close – Low)
  • 观察买入价(Bsetup)= Low – a * (High – Close)
  • 反转卖出价(Senter) = (High + Low)/ 2 *b  – c * Low
  • 反转买入价(Benter)=  (High + Low)/ 2 *b – c * High
  • 突破卖出价(Sbreak)= Ssetup - d * (Ssetup – Bsetup)
  • 突破买入价(Bbreak)= Bsetup + d * (Ssetup – Bsetup)

其中a、b、c、d为参数,满足 b - c =1,并且b越大,Senter越大,Benter越小;d越大,Bbreak越大,Sbreak越小。可以通过调整参数改变价位,从而调整交易频率,但注意不能改变6个价格的相对大小。

 

2)策略逻辑
趋势策略
该策略主要在没有持仓情况下,判断是否有上涨(下跌)的趋势,从而实现多头(空头)开仓。

  • 当前价格>突破买入价(Bbreak),开仓做多;
  • 当前价格<突破卖出家(Sbreak),开仓做空。

image


反转策略
  反转策略包括在持仓与没有持仓的情况下的交易,根据走势进行反转。

  • 若当日最高价>观察卖出价(Ssetup),然后下跌导致当前价格<反转卖出价(Senter),没有持仓时则开仓做空,有多头持仓时则先平仓再反向开仓做空;
  • 若当日最低价<观察买入价(Bsetup),然后上涨导致当前价格>反转买入价(Senter),没有持仓时则开仓做多,有空头持仓时则先平仓再反向开仓做多。

image

 

3)设定相应的止盈止损。

4)日内策略要求收盘前平仓。

上面是原版R-Breaker策略逻辑,但是使用RQData从2010年至今(即2019年10月)的1分钟沪深300股指期货主力连续合约(IF88)测试,效果并不理想。

大概回测几个指数合约,效果不好

image

 

原版的R-Breaker策略

TBquant3,完整代码,运行在5分钟K线,完全交易时段,应用结束时间

imageimage

image

Params
    Numeric qty(1); 
    Numeric aa(0.01);  
    Numeric bb(1.3); 
    Numeric cc(0.3);  
    Numeric dd(0.4);  
    Numeric StopLossSet(50); // 固定止损跳数
    //其中a、b、c、d为参数,满足 b - c =1,并且b越大,Senter越大,Benter越小;d越大,Bbreak越大,Sbreak越小。
    //可以通过调整参数改变价位,从而调整交易频率,但注意不能改变6个价格的相对大小。
Vars

    Series<Numeric> guancha_buy;
    Series<Numeric> guancha_sell;
    Series<Numeric> fanzhuan_buy;
    Series<Numeric> fanzhuan_sell;
    Series<Numeric> tupo_buy;
    Series<Numeric> tupo_sell;
    Series<Numeric> timecha;
    natural numeric tiao;
    Series<Bool> time2;
    Series<Numeric> hh;
    Series<Numeric> ll;
    Series<Numeric> zhouqi;
    Series<Numeric> shu;
    Natural Numeric dianshu;

Events
    onBar(ArrayRef<Integer> indexs)
    {    
        tiao = minmove * pricescale;
        Commentary("High  "+Text(HighD(1)));
        Commentary("lowd  "+Text(lowd(1)));
        Commentary("closed  "+Text(closed(1)));

        guancha_sell=HighD(1)+aa*(closed(1)-lowd(1));
        guancha_buy=lowd(1)-aa*(HighD(1)-closed(1));
        fanzhuan_sell= bb/2*(HighD(1)+lowd(1))-cc*lowd(1);
        fanzhuan_buy=bb/2*(HighD(1)+lowd(1))-cc*highd(1);
        tupo_sell= guancha_buy-dd*(guancha_sell-guancha_buy);
        tupo_buy=guancha_sell+dd*(guancha_sell-guancha_buy);
        PlotAuto("突破买入价",tupo_buy,tupo_buy);  
        PlotAuto("观察卖出价",guancha_sell,guancha_sell); 
        PlotAuto("反转卖出价",fanzhuan_sell,fanzhuan_sell);
        
        PlotAuto("反转买入价",fanzhuan_buy,fanzhuan_buy);
        PlotAuto("观察买入价",guancha_buy,guancha_buy);
        PlotAuto("突破卖出价",tupo_sell,tupo_sell);
        
        
        zhouqi=nthcon(time2,1)+1;
        hh=highest(high,zhouqi);
        ll=lowest(low,zhouqi);

        //趋势策略,  开仓  
        if (longCurrentContracts==0 and shortCurrentContracts==0 and high>tupo_buy) 
        {
            Buy(qty, max(open,tupo_buy+tiao*1));
            PlotAuto("开多1", "趋势突破买入价,开多", high + tiao*5, yellow);
        } 
        if (longCurrentContracts==0 and shortCurrentContracts==0 and low<tupo_sell)  
        {
            SellShort(qty, min(open,tupo_sell-tiao*1));
            PlotAuto("开空1", "趋势突破卖出价,开空", high + tiao*5, yellow);
        } 
        
        
        //反转策略, 平仓
        if (longCurrentContracts==0 and shortCurrentContracts>0 and ll<guancha_buy and high>fanzhuan_buy and shu[1]==0) 
        {
            buytocover(qty, max(open,fanzhuan_buy+tiao*1));
            PlotAuto("平多2", "反转买入价平空", high + tiao*10, yellow);
            shu=1;
        } 
        if (longCurrentContracts>0 and shortCurrentContracts==0 and hh>guancha_sell and low<fanzhuan_sell and shu[1]==0)  
        {
            sell(qty, min(open,fanzhuan_sell-tiao*1));
            PlotAuto("平空2", "反转卖出价平多", high + tiao*10, yellow);
            shu=1;
        }
        //反转策略, 开仓
        if (longCurrentContracts==0 and shortCurrentContracts==0 and ll<guancha_buy and high>fanzhuan_buy and shu[1]<=1)  
        {
            Buy(qty, max(open,fanzhuan_buy+tiao*1));
            PlotAuto("开多2", "反转买入价,开多", high + tiao*5, yellow);
            shu=2;
        } 
        if (longCurrentContracts==0 and shortCurrentContracts==0 and hh>guancha_sell and low<fanzhuan_sell and shu[1]<=1)   
        {
            SellShort(qty, min(open,fanzhuan_sell-tiao*1));
            PlotAuto("开空2", "反转卖出价,开空", high + tiao*5, yellow);
            shu=2;
        } 

        //固定止损
        dianshu=StopLossSet *MinMove * PriceScale;
        if(longCurrentContracts > 0 and BarsSinceEntry > 0 and Low < longAvgEntryPrice - dianshu  )
        {
            Sell(qty, min(open, longAvgEntryPrice - dianshu ));
            PlotAuto("固定止损", "固定止损", close, green);
        }
        if(shortCurrentContracts > 0 and BarsSinceEntry > 0 and High > shortAvgEntryPrice + dianshu)
        {
            BuyToCover(qty, max(open, shortAvgEntryPrice + dianshu));
            PlotAuto("固定止损", "固定止损", close, green);
        }
        
    }
OnBarClose(ArrayRef<Integer> indexes)
    {
        //日内策略要求收盘前平仓。
        time2 = time == 0.1500;
        Commentary("时间: " + text(Time));
        if(time2)
        {
            shu=0;
            
            if (longCurrentContracts > 0 )
            {
                Sell(qty, close);
                PlotAuto("清仓", "清仓1", high + tiao * 5, yellow);
            }
            if (shortCurrentContracts > 0)
            {
                buytocover(qty, close);
                PlotAuto("清仓", "清仓1", high + tiao * 5, yellow);
            }
        } 
    }
    

 

 

实际上R-Breaker策略可以拆分成趋势策略和反转策略。下面分别对这对2种策略逻辑进行优化:

1)趋势策略:

  • 若当前x分钟的最高价>观察卖出价,认为它具有上升趋势,在突破买入价挂上买入开仓的停止单;
  • 若当前x分钟的最低价<观察买入价,认为它具有下跌趋势,在突破卖出价挂上买入开仓的停止单;
  • 开仓后,使用固定百分比移动止损离场;
  • 增加过滤条件:为防止横盘行情导致不断的开平仓,日内每次开仓买入开仓(卖出开仓)委托的价位都比上一次更高(更低);
  • 收盘前,必须平调所持有的仓位。

2)反转策略:

  • 若当前x分钟的最高价>观察卖出价,认为它已经到了当日阻力位,可能发生行情反转,在反转卖出价挂上卖出开仓的停止单;
  • 若当前x分钟的最低价>观察买入价,认为它已经到了当日支撑位,可能发生行情反转,在反转买入价挂上买入开仓的停止单;
  • 开仓后,使用固定百分比移动止损离场;
  • 收盘前,必须平调所持有的仓位

其代码实现逻辑如下:

代码---

明天继续研究

 

以下文字是

策略效果

同样使用10年的1分钟IF88数据进行回测。不过,在展示强化版R-Breaker策略效果前,先分别展示一下拆分后的趋势策略和反转策略。

1)趋势策略:

  • 趋势策略夏普比率1.96,日均成交2.6笔,资金曲线是整体上扬的;
  • 但是在2017~2018年的盘整阶段,具有较大并且持续时间较长的回撤;
  • 这凸显出趋势类策略自身无法规避的缺点:在趋势行情中盈利,意味着震荡行情必然亏损。

 

 

2)反转策略

  • 反转策略夏普比率0.75,日均成交0.4笔,资金曲线缓慢上扬;
  • 但是在2017~2018年的盘整阶段,资金曲线上扬最快,而且这个阶段是最平滑的;
  • 这凸显出反转类策略优点:尽管在趋势行情亏损,在震荡行情必然能盈利。

 

 

综合对比2种策略的日均成交笔数和资金曲线,我们可以知道:

  • 由于趋势策略日均交易笔数较多(2.6笔),它主要负责贡献R-Breaker策略的alpha;
  • 趋势策略的亏损也是主要导致R-Breaker策略亏损的原因,但这时候的亏损由反转策略的盈利来填补。

由于趋势策略和反转策略是互斥的,在某些方面呈现出此消彼长的特点。那么,根据投资组合理论,可以把反转策略看作是看跌期权,买入一定规模的看跌期权来对消非系统性风险,那么组合的收益会更加稳健,即夏普比率更高。

由于趋势策略和反转策略日均成交手数比是2.6:0.4,若它们都只委托1手的话,反转策略的对冲效果微乎其微。

为了方便演示,我们设置趋势策略每次交易1手;反转策略则是3手。然后合成R-Breaker策略。发现夏普比率提高到2,资金曲线整体上扬,而且没有较大且持续时间较长的回撤。

 

 

结论

 

R-Breaker策略成功之处在于它并不是纯粹的趋势类策略,它属于复合型策略,它的alpha由2部分构成:趋势策略alpha;反转策略alpha。

这类复合型策略可以看作是轻量级的投资组合,因为它的交易标的只有一个:沪深300股指期货的主力合约。

更复杂的话,可以交易多个标的,如在商品期货做虚拟钢厂套利(同时交易螺纹钢、铁矿石、焦炭),在IF股指期货上做日内CTA策略。考虑到市场容量不同,价差套利能分配更多的资金。这样在价差套利提供稳定收益率基础上,CTA策略能在行情好的时候贡献更多alpha(高盈亏比特征导致的)。

从上面例子可以看出,一个合理的投资组合,往往比单个策略具有更高的夏普比率。因为夏普比率=超额收益/风险。夏普比率高意味着资金曲线非常平滑;这也意味着我们可以有效控制使用杠杆的风险。

当某个投资组合策略夏普足够高,而且策略资金容量允许,交易成本能有效控制等情况下,就可以通过杠杆来提升组合收益了。例如向银行贷款或者发放债券,这时候交易团队是债务人角色,即在承担更大风险同时,追求更到收益。债权人享受利息收益(类无风险收益)。

向公众发产品是另一种增加杠杆的方式,但此时投资组合风险已经转移到了客户这方,交易团队可以享受着管理费收益(类无风险收益)。根据目标客户的不同:

  • 私募基金面向高净值客户,这些客户群体风险承受能力较高;并且私募监管比较放松,能使用的衍生品较多,有提升业绩的自由度。故私募基金除了管理费,更追求业绩提成。
  • 公募基金面向普通群众,他们风险承受能力较低;并且公募监管非常严格,投资约束非常多,提升业绩难度较大。但是公募牌照的稀缺性必然导致该行业是盈利的。如万亿级别的管理规模,其管理费的收益,也不是一般的自营交易公司或者私募基金比得上的。

 
 

附录

最后附上策略源代码:

posted @ 2023-11-14 22:06  龙哥量化  阅读(783)  评论(0)    收藏  举报