繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

技术指标研报复现—CCI的顺势而为

作者/fjsdjfs 2019-07-19 16:00 0 来源: FX168财经网人物频道

CCI的顺势而为¶

研究思路¶

顺势指标CCI由唐纳德拉姆伯特所创,是通过测量股价的波动是否已超出其正常范围,来预测股价变化趋势的技术分析指标。由于选用的计算周期不同,顺势指标CCI也包括日CCI指标、周CCI指标、年CCI 指标以及分钟CCI指标等很多种类型。经常被用于股市研判的是日CCI指标和。虽然它们计算时取值有所不同,但基本方法一样。
计算方法:
第一步:

$TP_i = \frac{H_i+L_i+C_i}{3}$
第二步,计算最近n日TP的移动平均:
$MATP(n)_t = \frac{1}{n}\sum_{i=1}^nTP_{t-i+1}$
第三步,计算最近n日TP的一阶均差:
$meanDev(n)_t = \frac{1}{n}\sum_{i=1}^n|TP_{t-i+1}-MATP(n)_t|$
第四步:
$CCI(n)_t = \frac{TP_t-MATP(n)_t}{α*meanDev(n)_t}$
其中α一般取0.015,而n取20。 CCI指标没有运行区域的限制,在正无穷和负无穷之间变化。但是,和所有其 它没有运行区域限制的指标不一样的是,它有一个相对的技术参照区域:+100 和-100。按照指标分析的常用思路,CCI指标的运行区间也分为三类:+100以上为超买区,-100以下为超卖区,+100到-100之间为震荡区。

#计算CCI
from jqdata import *
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

start = '2005-09-01'
end = '2019-7-12'
n = 20
a= 0.015
index = '000300.XSHG'

def cal_meandev(tp,matp):
    mean_dev = (n-1)*[np.nan]
    for i in range(len(tp)-n+1):
        mean_dev.append(np.mean(abs(tp[i:i+n]-matp[i+n-1])))
    return np.array(mean_dev)

extended_days = get_trade_days(end_date = start,count=n-1)
start=extended_days[0]

def get_data(start,end,n,a,index):
    df = get_price(index,start_date=start,end_date=end,fields = ['close','high','low'] )
    df['tp'] = (df['close']+df['high']+df['low'])/3
    df['matp'] = df['tp'].rolling(n).mean()
    mean_dev = cal_meandev(df['tp'],df['matp'])
    df['mean_dev'] = mean_dev
    df['cci'] = (df['tp']-df['matp'])/(a*df['mean_dev'])
    return df
df = get_data(start,end,n,a,index)
df.tail(10)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
close high low tp matp mean_dev cci
2019-07-01 3935.81 3936.67 3886.91 3919.796667 3722.628833 86.435050 152.073982
2019-07-02 3937.17 3942.43 3918.94 3932.846667 3737.305333 93.096867 140.027150
2019-07-03 3893.53 3927.44 3878.84 3899.936667 3751.984500 94.680833 104.176077
2019-07-04 3873.10 3906.89 3854.69 3878.226667 3765.470667 92.470267 81.291716
2019-07-05 3893.20 3900.31 3857.93 3883.813333 3780.949000 85.730533 79.990430
2019-07-08 3802.79 3875.75 3775.03 3817.856667 3791.796000 75.320200 23.066558
2019-07-09 3793.13 3811.10 3774.76 3792.996667 3797.113500 68.925133 -3.981937
2019-07-10 3786.74 3810.40 3774.23 3790.456667 3801.854333 64.077667 -11.858179
2019-07-11 3785.22 3830.74 3774.41 3796.790000 3807.739667 58.192333 -12.544226
2019-07-12 3808.73 3820.24 3774.52 3801.163333 3814.207167 51.724833 -16.811826

策略构造¶

标的为沪深300指数日频数据(2005-09-01至2019-07-12)
当CCI上穿100,买入,信号为1;当CCI下穿-100,卖出,信号为-1。参数n为20。策略表现如下。

策略表现¶

双边交易策略¶

我们可以看出,双边交易策略的收益主要来自于几次牛市行情,在震荡行情中的表现普通,而这也是一般趋势类择时策略的特点。策略总收益7.68,夏普比率0.70,表现可以说不错。但是最大回撤达到了47%,这是我们不希望看到的。

#CCI策略双边交易表现
threshold = 100
def gen_signal(cci,threshold):
    signal = n*[0]
    for i in range(n,len(cci)):
        if cci[i]>threshold and cci[i-1]<threshold:
            signal.append(1)
        elif cci[i]<-threshold and cci[i-1]>-threshold:
            signal.append(-1)
        else:
            signal.append(0)
    return np.array(signal)
            

def gen_position(signal,short):
    position = [0]
    if short:
        short_pos =-1
    else:
        short_pos = 0
    for i in range(1,len(signal)):
        if signal[i] == 1:
            position.append(1)
        elif signal[i] == 0:
            position.append(position[-1])
        else:
            position.append(short_pos)
    return np.array(position)

def cal_ret(df):
    ret =n*[0]
    for i in range(n,len(df)):
        ret.append(df['position'][i-1]*df['index_ret'][i])
    ret = np.array(ret)
    return ret

def cal_cum_ret(ret):
    cum_ret = [1]
    for i in range(len(ret)-1):
        cum_ret.append(cum_ret[-1]*(1+ret[i]))
    cum_ret = np.array(cum_ret)
    return cum_ret

def back_test(df,threshold,short,plot=True):
    df['index_ret'] = np.concatenate(([np.nan],np.array(df['close'][1:])/np.array(df['close'][:-1])))-1
    df['signal'] = gen_signal(df['cci'],threshold)
    df['position'] = gen_position(df['signal'],short)
    ret = cal_ret(df)
    df['ret'] = ret
    cum_ret = cal_cum_ret(ret)
    
    #计算指标
    sum_dict={}
    sum_dict['总收益']=cum_ret[-1]-1
    sum_dict['日胜率'] = len(ret[ret>0])/(len(ret[ret>0])+len(ret[ret<0]))
    max_nv = np.maximum.accumulate(cum_ret)
    mdd = -np.min(cum_ret/max_nv-1)
    sum_dict['最大回撤']=mdd
    sum_dict['夏普比率']=ret.mean()/ret.std()*np.sqrt(240)
    sum_df = pd.DataFrame(sum_dict,index=[0])
    
    if plot:
    #作图
        plt.figure(1,figsize=(20,10))
        plt.title('策略表现',fontsize=18)
        plt.plot(df.index,cum_ret)
        plt.plot(df.index,df['close']/df['close'][0])
        plt.legend(['CCI策略','HS300'],fontsize=14)
        plt.show()
    return sum_df

back_test(df,threshold,True)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
总收益 日胜率 最大回撤 夏普比率
0 7.610018 0.533868 0.471381 0.701032

双边交易策略敏感性分析¶

我们通过寻找夏普比率最大的参数n来优化参数,最优参数为22。

#敏感性分析
ns = list(range(15,31))
sharpe_list =[]
for n in ns:
    df2 = get_data(start,end,n,a,index)
    summary = back_test(df2,threshold,True,False)
    sharpe_list.append(summary['夏普比率'][0])
plt.figure(figsize=(15,8))
plt.plot(ns,sharpe_list)
[<matplotlib.lines.Line2D at 0x7f3600696358>]

优化后的策略成功避开了2009-2010年这一段时间的回撤,但仍未避开2018年底和2019年初的大回撤。但总的来说,相对于未优化的策略还是有所改善,总收益达到11.55,夏普比率0.80。

#双边交易最优参数回测
df2 = get_data(start,end,22,a,index)
back_test(df2,threshold,True,True)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
总收益 日胜率 最大回撤 夏普比率
0 11.548231 0.538507 0.444329 0.800002

单边交易策略表现¶

通过类似的参数优化方法,我们得到单边交易策略的最优参数22。 单边交易策略的总收益低于双边交易,为8.37,但收益更稳定:最大回撤仅为29%,夏普比率达到0.96。

#单边交易最优参数回测
df3 = get_data(start,end,22,a,index)
back_test(df2,threshold,False,True)
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
总收益 日胜率 最大回撤 夏普比率
0 8.368407 0.570156 0.298012 0.966564
#单边交易敏感性分析
ns = list(range(15,31))
sharpe_list =[]
for n in ns:
    df3 = get_data(start,end,n,a,index)
    summary = back_test(df3,threshold,False,False)
    sharpe_list.append(summary['夏普比率'][0])
plt.figure(figsize=(15,8))
plt.title('单边交易敏感性分析')
plt.plot(ns,sharpe_list)
[<matplotlib.lines.Line2D at 0x7f3600272080>]

优化的CCI策略¶

从该指标的设计来看,在一般常态行情下,CCI指标不会发生作用。当CCI扫描到异常股价波动时,也就是当CCI突破+/-100时,可以抓住市场趋势。但是在上涨/下跌行情中出现短暂反方向运动时,该策略会出现误判,又因为策略的信号频率不高,也因此带来比较大的回撤。
以下从这一点出发来构建的策略二:CCI指标上穿100买入,信号为1;当CCI指标回到100,并距离前次上穿100在m天之内,我们卖出,信号为-1。否则信号不变,直到下穿-100才卖出。(这里我们认为如果是短暂的上穿下穿,上涨的趋势并不明显,所以就卖出。如果是之前长期在100以上,说明是个长期的趋势,这时下穿100,并不马上卖出,要等到下穿-100才确认卖出)
下穿-100情况同上。测得最优参数为n=20,m=7

双边交易策略表现¶

优化后的双边交易策略总收益大幅提升,达到25.49,夏普比率也达到0.99。策略成功避开了几次熊市的回撤。但是在2012-2014这一段震荡行情中,策略遭遇了52%的大幅回撤,这是优化策略更高的换手率造成的:高换手率可以避开熊市的回撤,但在震荡市中,过高的换手同样会造成回撤。

#优化的CCI择时策略(双边交易)
def gen_signal_2(cci,threshold,m):
    signal = n*[0]
    up_list=[]
    down_list=[]
    flag=0
    for i in range(n,len(cci)):
        if cci[i]>threshold and cci[i-1]<threshold:
            signal.append(1)
            up_list.append(i)
        elif cci[i]<-threshold and cci[i-1]>-threshold:
            signal.append(-1)
            down_list.append(i)
        elif cci[i]<threshold and cci[i-1]>threshold:
            try:
                if up_list[-1]<i-m:
                    signal.append(0)            
                else:
                    signal.append(-1)
            except:
                signal.append(0)
        elif cci[i]>-threshold and cci[i-1]<-threshold:
            try:
                if down_list[-1]<i-m:
                    signal.append(0)            
                else:
                    signal.append(1)
            except:
                signal.append(0)
        else:
            signal.append(0)
    print(len(signal))
    return np.array(signal)

def back_test_2(df,threshold,m,short,plot=True):
    df['index_ret'] = np.concatenate(([np.nan],np.array(df['close'][1:])/np.array(df['close'][:-1])))-1
    df['signal'] = gen_signal_2(df['cci'],threshold,m)
    df['position'] = gen_position(df['signal'],short)
    ret = cal_ret(df)
    df['ret'] = ret
    cum_ret = cal_cum_ret(ret)
    
    #计算指标
    sum_dict={}
    sum_dict['总收益']=cum_ret[-1]-1
    sum_dict['日胜率'] = len(ret[ret>0])/(len(ret[ret>0])+len(ret[ret<0]))
    max_nv = np.maximum.accumulate(cum_ret)
    mdd = -np.min(cum_ret/max_nv-1)
    sum_dict['最大回撤']=mdd
    sum_dict['夏普比率']=ret.mean()/ret.std()*np.sqrt(240)
    sum_df = pd.DataFrame(sum_dict,index=[0])
    
    if plot:
    #作图
        plt.figure(1,figsize=(20,10))
        plt.plot(df.index,cum_ret)
        plt.plot(df.index,df['close']/df['close'][0])
        plt.show()
    return sum_df

df4 = get_data(start,end,20,a,index)
back_test_2(df4,threshold,7,True)
3388
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
总收益 日胜率 最大回撤 夏普比率
0 25.489206 0.528818 0.521558 0.992611

单边交易策略表现¶

我们进一步考察优化后的单边交易策略。一般来说,单边交易策略的收益回比双边交易策略低,但它的收益会更稳定。优化的单边交易策略总收益同样大幅提升,达到12.65,夏普比率达到1.12。但其同样没能避开2012-1014年的这一段回撤,最大回撤达到40%。

#优化的CCI择时策略(单边交易)
df4 = get_data(start,end,20,a,index)
back_test_2(df4,threshold,False)
3388
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
总收益 日胜率 最大回撤 夏普比率
0 12.659258 0.559588 0.403086 1.115412

研究结论¶

总的来说,CCI可以捕捉到趋势行情。普通的CCI择时策略能捕捉到长期趋势,但对于突然的趋势反转反应不足,会在熊市遭受回撤。而优化后的CCI策略捕捉短期趋势的能力更强,但会在横盘震荡行情由于频繁换仓而遭遇较大的回撤。。但是不管哪种策略,指标的钝化,以及脉冲式的行情两点造成的错判都是不可避免的。那么按照这个思路,对于指标钝化未来我们将加入与之互补的指标加以配合,而对于脉冲式行情,我们考虑运用高频数据去捕捉“瞬间”的机会。

分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2192文章4145粉丝45

    暂无个人简介信息

  • 梁孟梵

    人气2176文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 指导老师

    人气1864文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2320文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 王启蒙现货黄金

    人气296文章3164粉丝8

    本人做分析师以来,并专注于贵金属投资市场,尤其是在现货黄金...

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2328文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4760文章8329粉丝119

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...

FX168财经

FX168财经学院

FX168财经

FX168北美