拒绝踏空和卖飞,魔改CCI指标主升浪战法!

〇、写在前边

其实最应该学习量化的,就是散户。

作为散户,我们能获取的只有公开信息,这使得我们天然就落后于机构、大户和内幕狗。

那么我们可以利用公开信息来提升投资表现吗?当然可以。

网上有大量免费或者低成本就能获取的数据,比如历史行情、基本面数据等,这些数据中隐藏着大量的规律,哪怕我们能从中找出一条有效的策略,可能就足以保证我们长期跑赢大盘了。

想要长期赚钱,仅靠运气是万万不行的,你的运气要是够好,你早就买彩票中大奖了不是吗?

机构、大户们在有那么多优势的情况下,还会投入大量的精力和成本在研究上,我们如果不认真提升自己的投资能力和操作水平,那么市场凭什么让你赚钱,凭你的追涨杀跌?凭你是“长期股东”?凭你有着发财梦?凭你……穷?

散户最应该抛掉的想法,就是想挣所有的钱。因为这样大概率所有的钱都挣不到。

很多人,既想做好高频、又想做好长线,最后往往是想买超短做个T,结果最后又成了长线股东。

很多人,既想做趋势投资者,又想做好均值回归型投资,最好往往是散户三连:高位接盘、山腰加仓、低位割肉。

以散户的水平和精力,想要掌握非常丰富的、多元的投资策略几乎是不可能的。我的建议是大家根据自己的性格和交易习惯,找到最适合自己的风格,然后把这个风格做深,不断挖掘这个风格下好用的指标和交易策略。

基础差也可以做量化,量化远没你想的那么复杂。

数学、编程,可能会让你在这条路上起步得更加顺利,但是哪怕这两个你都不会,也不代表你做不了量化。

量化可以很复杂,也可以很简单。其实很多量化策略的背后只不过是一些简单的规则,比如一个均线金叉死叉的策略,能有什么复杂的呢?如果你通过研究甚至是一个个试探的方式找到了合适的参数,那你完全可以认为这就是一条量化策略。

量化的本质,就是通过数据来验证一个个假设,得到更加可靠的结论,这和大家通过经验来判断涨跌或者根据玄学来猜涨跌有着本质的不同。我们在使用量化武器时,就是要通过不断执行大概率正确或平均期望收益更高的动作,以此来追求长期正向回报。一次两次的胜利只能是运气,只有持续胜利,那才是真正的能力。

工具方面大家也不用担心,现在有很多工具可以帮助大家低成本地启动量化研究。比如掘金、聚宽、QMT、PTrade等量化平台或交易软件,很多都带有策略编写、选股、回测之类的能力。后续我也会针对常用的工具出一些教程,大家按喜好进行选择就好。

而我们的核心关注点,是策略本身。

言归正传。

一、CCI:顺势指标的本质

今天要介绍的,是一个已经四十多岁的指标。这个指标由唐纳德·兰伯特在上世纪80年代初创造、原本用于商品市场。我强烈建议大家看到最后,可能很多人都没意识到,这个指标最流行的用法其实是错误的!

CCI的全称是Commodity Channel Index,通常翻译成顺势指标。一般来说,该指标下穿+100时有走弱迹象,上穿-100时有走强迹象,这是最常规的逃顶、抄底的信号。当然,在A股,这种所有人都知道的规律大概率已经是个反向指标了。

我们了解它的最终目的就是为了改造它,从而使得它更好用。我们来看下它的计算公式,其相对于RSI、BOLL等略显复杂,但整体来说利用的还是很粗浅的统计知识。我们先看下具体的步骤:

T P = h i g h + l o w + c l o s e 3 A T P = S M A ( T P , N ) M D = M A D N ( T P ) C C I = T P − A T P 0.015 ∗ M D \begin{align} TP = &\frac{high + low + close}{3}\\ \nonumber\\ ATP &= SMA(TP, N) \\ \nonumber\\ MD &= MAD_N(TP)\\ \nonumber\\ CCI &= \frac{TP - ATP}{0.015 * MD} \end{align} TP=ATPMDCCI3high+low+close=SMA(TP,N)=MADN(TP)=0.015MDTPATP

我来详细解释下每一个细节,我尽量使用相对白话的描述,尽可能让没基础的朋友也能看懂。

1. TP和ATP

TP是指Typical Price,是指当天最高价、最低价、收盘价三者的算术平均值,相当于在价格信息中综合考虑了这三个因素。

ATP则是TP的N日简单移动平均,A是Average的开头。一般来说,N采用14,但是我们还是应该从个人风格和实际效果出发,结合自己关注的资产来寻找最恰当的参数。

2. MD

AD对应的是Absolute Deviation,绝对偏差的意思。在这里AD就是指每天的TP减去过去N天的ATP的绝对值,前边再加一个M,对应的是Mean,即对AD再求一个均值,也就是统计学中常见的MAD(平均绝对偏差),这样就得到了我们的MD。

3. CCI

我们用TP减去ATP,再除以MD就得到了CCI。CCI的计算中,0.015是一个常量缩放系数,用于控制值域,可以忽略。

TP-ATP在这里起到的作用是平移,它的目标是将数据中枢移到0的位置,这样我们可以很方便地根据正负值判断当前处于上涨趋势还是下降趋势。

MD起到的作用是缩放,类似于归一化或者标准化,它的目标是为了让不同资产之间具有可比性。举个简单的例子,A资产价格100,B资产价格也是100,那么它们两个谁在超买区、谁在超卖区?我们肯定不知道,但是如果我们知道了A资产一周前的价格只有50,而B资产一周前的价格是200,那么我们就有更大的把握说A超买了,B超卖了。MD在这里就是起到这个作用。

从统计学上来说,CCI指标的计算跟数据标准化的过程有些类似。我们回忆下z标准化的过程:

x ^ = x − μ σ \hat{x} = \frac{x - \mu}{\sigma} x^=σxμ

原值减去均值,并除以标准差,跟CCI的计算是不是很像?区别在于标准化过程中的除数是标准差(STD),而CCI计算过程中的除数是平均绝对偏差(MAD),数据在经历了标准化过程之后,会有95%的值处于均值的两倍标准差范围内,99%的值处于均值的三倍标准差范围内(这里假设了数据近似服从正态分布)。

我们可以大概这么来理解CCI,在大多数情况下,它的取值应该处于±100以内,一旦偏离了这个范围,就说明出现了超买超卖现象。

二、CCI的魔改思路

事实上,CCI中我们可以魔改的地方非常多。比如说ATP中的N和SMA算法,MD中的N和MAD算法。

1. 调整ATP

我们提到,ATP实质上就是TP的简单移动平均。那么这里我们可以考虑调整的就是把移动平均的周期拉长,或者把简单移动平均算法改为EMA、WMA等(详见专栏或合集历史文章)。

以移动平均的周期N为例。假设我们的风格偏长期或者某资产的价值长期稳定,那么我们可以适当提高N的取值,反之亦然。举一个极端的例子,如下图,某资产价格长期在0到2之间波动,1就是价值中枢。

那么很明显,这里长期均值线1就是真正有价值的ATP,价格偏离越多,回归的概率就越大。我们看到,蓝线和红线交叉的点都在1处,这正是这个资产的价值中枢。而蓝线和绿线交叉的点,仅仅能代表短期的趋势。从长期来看,低于红线开始低吸、高于红线逐步卖出大抵是不会错的。而绿线则没有这种指示意义。

一般来说,越长的周期得到的指标,对应的趋势空间也越大。越是长周期的指标发生了巨大的偏离,那么当均值回归时潜在的收益(或落差)就越大。

2. 调整MD

前边我们提到,MD的作用是缩放数据以使得不同资产的指标之间具有可比性。那么这里只要我们使用的指标在量纲上和价格的量纲在一个级别,理论上就是可以考虑的,比如我们可以考虑在统计学中更常用的标准差。

调整之后,如果我们还是希望在指标超过[-100,100]这个范围时发出信号,那么我们需要结合实际情况修改0.015这个系数。或者我们干脆去掉这个系数,结合我们得到的新指标的数据分布来判断指标落在不同值域内的概率,从而调整我们信号触发的阈值。

实际上,这里的N我们也可以考虑修改为跟ATP的N取不同的值。比如我们认为某个资产的价格一年的周期里是具有稳定中枢的,那么我们ATP的N可以考虑选择250,但是我们发现这个资产往往一年波动大、一年波动小。那么我们就可以考虑对MD的N取500,这样,我们的CCI指标就可以在更长期的周期里具有可比性。否则,哪怕是同一个权益资产,跨越较长时间的CCI之间的对比也是有问题的,甚至我们看到的CCI的趋势线也未必是可靠的。

现在我们在各大财经类APP上看到的这个经典的指标,都存在这个问题。

三、CCI计算实战

1. 通达信计算

其实通达信中系统内置了这个指标,如果不做魔改的话,在超买超卖型指标中选择这个指标就可以直接使用了。不过这里还是贴一下公式吧,整体来说还是很简单的。

TYP:=(HIGH+LOW+CLOSE)/3;
CCI:(TYP-MA(TYP,N))*1000/(15*AVEDEV(TYP,N));

我再把官方的指标翻译贴一下,如果还有看不懂的可以留言。

TYP赋值:(最高价+最低价+收盘价)/3
输出CCI:(TYP-TYP的N日简单移动平均)×1000 / (15× TYP的N日平均绝对偏差)

2. Python计算

我们先手动实现一版,然后用神器talib计算一版,并与同花顺、通达信等APP进行对比。

首先,我们用tushare获取上证指数今年以来的数据,并按照日期做一个增序排列。

import pandas as pd
import talib# 从自建数据库中获取沪深300指数数据
# 找不到行情数据的朋友,可以参考前边的金融数据库搭建教程,把常用数据存储下来
df = pd.read_sql('SELECT * FROM index_a.ts_a_index_daily_quotes WHERE ts_code="000300.SH"', con=con)

接下来,我们按照上边的公式实现CCI指标的计算,并用talib计算一版作为对比。

df = pd.read_sql('SELECT * FROM index_a.ts_a_index_daily_quotes WHERE ts_code="000300.SH"', con=con)
df['TP'] = (df.close.values + df.high.values + df.low.values) / 3
df['ATP'] = talib.SMA(df.TP.values, timeperiod=14)
df['MD'] = 0
for i in range(len(df)-13):df['MD'].iloc[i+13] = np.mean(abs(df['TP'].values[i:i+14] - df['ATP'].values[i+13]))
df['CCI14_Q'] = (df.TP - df.ATP) / (df.MD * 0.015)
df['CCI14'] = talib.CCI(df.high, df.low, df.close, timeperiod=14)
df.tail(10)[['ts_code', 'date', 'CCI14_Q', 'CCI14']]

可以看到,两种方法的结果完全一致。经过对比,我们的计算与同花顺等APP也保持一致。

image

四、CCI的实战应用

以±100为操作信号到底靠谱吗?Talking is cheap,我们来看看真实的数据表现。

我们先来做个简单的统计,看下CCI14的分布情况:

df.CCI14.quantile([0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 0.90, 0.95, 0.99])

输出为:

0.01   -225.302040
0.05   -164.952592
0.10   -137.246979
0.25    -82.598690
0.50     14.500720
0.75     98.992095
0.90    144.239111
0.95    167.839295
0.99    215.487870
Name: CCI14_Q, dtype: float64

怎么理解呢?对沪深300来说,当CCI14<-225或CCI14>215的时候,是“百日一遇”的顶底极端值区域;有大概10%的时间里,CCI高于168或者低于-165。

我们看下±100之外的数据有多少。

print('低于-100的时间占比: ', len(df[df.CCI14 < -100]) / len(df))
print('高于100的时间占比: ', len(df[df.CCI14 > 100]) / len(df))

输出为:

低于-100的时间占比:  0.20012507817385866
高于100的时间占比:  0.2461955388784657

也就是说,有超过44%的时间里CCI是在±100之外的。

CCI经典的用法是下穿100时卖出,上穿100时买入,那么我们来看下这个策略的表现。

我们假设当某一天CCI上穿-100后,第二天我们以开盘价买入;当某一天CCI下穿100后,第二天我们以开盘价卖出。

limit = 100
df2['buy_flag'] = df2.apply(lambda row: 1 if row['CCI14_pre'] < -limit and row['CCI14'] > -limit else 0, axis=1)
df2['sell_flag'] = df2.apply(lambda row: 1 if row['CCI14_pre'] > limit and row['CCI14'] < limit else 0, axis=1)
for d in [1, 3, 7, 14, 30]:df2['future_{0}_change'.format(d)] = df2.close.shift(d) / df2.close - 1
future_cols = ['future_{0}_change'.format(d) for d in [1, 3, 7, 14, 30]]
df2.groupby(['buy_flag', 'sell_flag'])[future_cols].mean().T

上图中,绿色框代表我们卖出后未来1天、3天、7天、14天和30天股价的累计涨幅。可以看到,在下穿-100后,第二天开盘卖出,3天内的收盘价平均下来和我们的卖出价非常接近。但是拉长周期到7天至30天来看,平均涨幅大概在-3.5到-6.4%。也就是说,拉长到一周以上来看,我们卖出很可能是正确的。

红色框代表我们买入后未来1天、3天、7天、14天和30天股价的累计涨幅。可以看到,买入当天收盘价和我们的买入价基本持平。但是拉长周期看,我们持有3、7、14、30天的收益分别是1.2%、4.8%、6.4%和6.6%。

当然,上边这个估算存在一些问题。因为我们并没有考虑在持有期间触发了卖出信号以及在卖出时触发了买入信号的情况。那么我们就以发出买入信号则立即买入,发出卖出信号则立即卖出,来看下买入和卖出期间沪深300的表现分别是怎么样的。这里我们采用掘金量化终端来实现这一策略,绩效表现见下图。

image

很明显,这一策略大幅跑输了基准,在近20年的时间里仅仅实现了4.36%的总收益,年化0.23%,这可是连银行存款利率都远远不如啊!

所以,网上再讲那些玄学用法时,不要再相信了!要相信科学,相信数据,相信量化的力量!

五、CCI魔改之主升浪战法

既然公开的用法不靠谱,那我们就结合CCI的特性,来设计一个可能有效的策略。

这里的核心思路是:

  1. 每一次大机会,都一定伴随着短期的见底
  2. 每一次大机会,都一定伴随着右侧的突破

所以,我们需要在策略中实现以下几点:

  1. 我们需要判断短期的底部,这里我们通过对CCI指标的周期和阈值做设计来实现这一效果。
  2. 有些底部是V字反转,有些底部是横盘突破,所以CCI出现信号后并不一定马上能看到右侧信号,如果只用当天的CCI和均线做配合,很可能会错过一些横盘突破的主升浪。
  3. 我们需要判断右侧信号,这里可以考虑使用均线突破的策略。

下面我们看下策略的回测表现。可以看到,这个策略在回撤方面控制得非常好,在基准最大回撤超过70%的情况下保持了仅仅28%的最大回撤,同时基本上每次大涨的鱼身段都能吃到,最终在基准收益360%的情况下,策略得到了超过14倍的收益!可以看到,策略的历史高点在20年,在国庆节前这一波上涨之后,已经逼近了历史高点!然而沪深300本身距离历史高点还有不小的距离呢……

image

当然,这个策略也有其劣势。最显而易见的问题就是胜率较低,这是因为这个策略为了保证不错过主升浪,在买入信号方面会相对敏感,不过快进快出的特性也确保了每次试错的成本不会太高,所以综合来看,较低的胜率也可以接受。

另外这个策略本身仍然算是一个相对右侧的策略,所以也摆脱不了右侧的通病,那就是起涨第一波一般会错过一些、见顶后第一波一般逃不过。但是从整体的回撤表现和收益曲线来看,这都不是什么大问题。以本次大涨为例,虽然策略没有在9月18日最低点买入,但是在9月24日收盘进场也没差太多,核心的鱼身段并没有错过。

image

我已经将策略的细节、代码和通达信公式都放到圈子中,欢迎大家加入老Q的圈子,我们一起研究量化,武装自己!

image

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1555476.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

野火STM32F103VET6指南者开发板入门笔记:【1】点亮RGB(基于结构体)

文章目录 硬件介绍软件介绍&#xff1a;结构体方式软件介绍&#xff1a;宏定义方式 硬件介绍 提示&#xff1a;本文是基于野火STM32F103指南者开发板所写例程&#xff0c;其他开发板请自行移植到自己的工程项目当中即可。 RGB-LEDPin引脚&#xff1a;低电平-点亮&#xff0c;高…

表达式求值(可以计算两位数以上)

此程序可计算两位数以上的表达式 import java.util.Stack;public class ExpressionEvaluator {public int evaluate(String s) {Stack<Integer> numbers new Stack<>();Stack<Character> operators new Stack<>();int i 0;char c s.charAt(i);whil…

灵足时代:具身智能核心部件的新秀崛起——解析数千万元天使轮融资

在智能科技日新月异的今天,具身智能作为连接物理世界与数字世界的重要桥梁,正逐步成为科技创新的前沿阵地。近日,具身智能核心部件领域的新锐公司——“灵足时代”宣布完成数千万元天使轮融资,这一消息无疑为行业内外带来了强烈的震撼与期待。本轮融资由雅瑞智友科学家基金…

在 MySQL 中处理和优化大型报告查询经验分享

在 MySQL 数据库的使用过程中&#xff0c;我们经常会遇到需要生成大型报告的情况&#xff0c;这些查询可能涉及大量的数据和复杂的计算&#xff0c;对数据库的性能提出了很高的要求。 一、问题背景 大型报告查询通常具有以下特点&#xff1a; 数据量大&#xff1a;涉及大量的…

【2024年最新】基于Spring Boot+vue的旅游管理系统lw+ppt

作者&#xff1a;计算机搬砖家 开发技术&#xff1a;SpringBoot、php、Python、小程序、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;Java精选实战项…

用js和css实现一行一行文字交替显示

用js和css实现&#xff0c;效果是&#xff1a;有多行文字&#xff0c;一行一行的交替显示&#xff0c;每隔几秒显示一行&#xff0c;循环显示。 代码如下&#xff0c;保存为html即可看到效果&#xff1a; <!DOCTYPE html> <html lang"en"> <hea…

数据库软题6.1-关系模式-关系模式的各种键

关系模式的各种键 题1-由关系模式求候选键 1. 候选键唯一不冗余 对选项进行闭包运算&#xff0c;如果得到全部属性U&#xff0c;则为候选码 A:AC-ABC-ABCD B:AB-ABC-ABCD C:AE-ABE-ABCE -ABCDE-ABCDEH D:DE2. R的候选码可以从A1,A2,A3,A1A2,A1A3,A2A3,A1A2A3中选择&#xff…

JC2804快速入门

目录 一、硬件接线二、软件操作2.1、CAN分析仪2.2、默认参数2.3、读取校准参数2.4、闭环控制2.5、调整PI参数2.6、切换控制模式 三、其它CAN模块操作3.1、使用CANable3.2、发送指令3.3、其它 一、硬件接线 红色接电源正极&#xff0c;黑色接电源负极&#xff0c;电源电压7—12V…

每日一道算法题——二分查找

文章目录 开口闭口区分:1、问题2、示例3、解决方法&#xff08;1&#xff09;注意点&#xff08;2&#xff09;代码 开口闭口区分: 开口闭口区分: [1,2,3] 左闭右闭[1,2,3) 左闭右开(1,2,3] 左开右闭 开口如数组(1,2,3)不包含当前数据&#xff0c;也就是指只有2&#xff0c;闭口…

分布式锁--redission 最佳实践!

我们知道如果我们的项目服务不只是一个实例的时候&#xff0c;单体锁就不再适用&#xff0c;而我们自己去用redis实现分布式锁的话&#xff0c;会有比如锁误删、超时释放、锁的重入、失败重试、Redis主从一致性等等一系列的问题需要自己解决。 当然&#xff0c;上述问题并非无…

【Java】—— 泛型:泛型的理解及其在集合(List,Set)、比较器(Comparator)中的使用

目录 1. 泛型概述 1.1 生活中的例子 1.2 泛型的引入 2. 使用泛型举例 2.1 集合中使用泛型 2.1.1 举例 2.1.2 练习 2.2 比较器中使用泛型 2.2.1 举例 2.2.2 练习 1. 泛型概述 1.1 生活中的例子 举例1&#xff1a;中药店&#xff0c;每个抽屉外面贴着标签 举例2&…

【JavaEE】——文件IO

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;认识文件 1&#xff1a;文件的概念 2&#xff1a;文件的结构 3&#xff1a;文件路径…

【操作系统】体系结构

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 操作系统的内核 操作系统结构——分层结构 操作系统结构——模块化 操作系统结构——宏内核、微内核…

修改Anaconda虚拟环境默认安装路径(Linux系统)

文章目录 修改Anaconda虚拟环境默认安装路径(Linux系统)1.方法一&#xff1a;使用--prefix参数2.方法二&#xff1a;配置conda环境的默认安装位置 修改Anaconda虚拟环境默认安装路径(Linux系统) 1.方法一&#xff1a;使用--prefix参数 在创建虚拟环境时&#xff0c;使用--pre…

BUSHOUND的抓包使用详解

BUSHOUND是个过滤软件&#xff0c;确切来说是在windows操作系统它的驱动层USB传输的数据。所以这个数据上可能是与USB的总线上的数据是有一点差异的。 先要选择设备的抓包。所以就是在device这个界面底下&#xff0c;我们首先要选择我们要抓的设备。 尝试下键盘设备 电脑键盘…

【可视化大屏】将柱状图引入到html页面中

到这里还是用的死数据&#xff0c;先将柱状图引入html页面测试一下 根据上一步echarts的使用步骤&#xff0c;引入echarts.js后需要初始化一个实例对象&#xff0c;所以新建一个index.js文件来进行创建实例化对象和配置数据信息等。 //在index.html引入<script src"j…

Python爬虫使用实例-mdrama

一个Python爬虫使用实例&#xff1a;主要用于下载指定的剧集音频。分别从网页和json文件中获取剧集的title和剧集中所存在音频的id&#xff0c;调用you-get&#xff0c;最后自动重命名下载文件夹为剧集名title。 目标网址&#xff1a; https://www.missevan.com/mdrama/其中为…

开源AI智能名片小程序源码:私域电商构建独特竞争力的新机遇

摘要&#xff1a;本文旨在探讨私域电商如何利用开源AI智能名片小程序源码构建独特竞争力。在强调独特性是通向成功的必要条件的基础上&#xff0c;分析开源AI智能名片小程序源码在私域电商发展独特性方面的作用及相关策略。 一、引言 在竞争激烈的商业环境中&#xff0c;让自己…

RTX4060安装nvidia显卡驱动

文章目录 nvidia drivers下载删除原有nvidia驱动安装nvidia驱动如果报错Unable to find the kernel source tree for the currently runningbuilding kernel modules解决方法 报错成功安装!!! nvidia drivers下载 https://www.nvidia.cn/geforce/drivers/#:~:textNVIDIA%20GeF…

Python从入门到高手5.1节-Python简单数据类型

目录 5.1.1 理解数据类型 5.1.2 Python中的数据类型 5.1.3 Python简单数据类型 5.1.4 特殊的空类型 5.1.5 Python变量的类型 5.1.6 广州又开始变热 5.1.1 理解数据类型 数据类型是根据数据本身的性质和特征来对数据进行分类&#xff0c;例如奇数与偶数就是一种数据类型。…