日线CCI的计算与展示

用户头像sh_***388rgt
2025-11-05 发布

CCI指标,又称顺势指标,是美国股市技术分析 家唐纳德·蓝伯特(Donald Lambert)于20世纪80年代提出的。该指标专门测量股价、外汇或者贵金属交易是否已超出常态分布范围,属于超买超卖类指标中较特殊的一种。该指标波动于正无穷大和负无穷大之间。但是,它不需要以0为中轴线,这一点也和波动于正无穷大和负无穷大的指标不同。

它最早是用于期货市场的判断,后运用于股票市场的研判,并被广泛使用。与大多数单一利用股票的收盘价、开盘价、最高价或最低价而发明出的各种技术分析指标不同,CCI指标是根据统计学原理,引进价格与固定期间的股价平均区间的偏离程度的概念,强调股价平均绝对偏差在股市技术分析中的重要性,是一种比较独特的技术指标。

按照指标分析的常用思路,CCI指标的运行区间也分为三类:+100以上为超买区,—100以下为超卖区,+100到—100之间为震荡区。在+100到—100之间的震荡区,该指标基本上没有意义,不能够对大盘及个股的操作提供多少明确的建议,因此它在正常情况下是无效的。

有时候CCI指标还是比较好使的。以最近比较活跃的平潭发展为例,在股价大幅上涨的时候,CCI指标有剧烈的波动。下面给出获取股票数据以及计算CCI并且画图的python代码,希望能抛砖引玉。

本人将使用baostock的数据来进行代码展示:

import baostock as bs
import matplotlib.pyplot as plt
import matplotlib.font_manager as matfont
import numpy as np
import pandas as pd

# 设置中文字体
zhfont1 = matfont.FontProperties(fname='C:/Windows/Fonts/simkai.ttf')


def get_stock_data(stock_code='sz.000592'):
    """获取股票历史数据"""
    # 登录baostock
    bs.login()

    # 查询历史K线数据
    rs = bs.query_history_k_data_plus(
        stock_code,
        "date,open,high,low,close,volume",
        start_date='2025-01-01',  # 调整为更早的日期确保有数据
        end_date='2025-10-31',
        frequency="d",
        adjustflag="3"  # 复权类型:3-后复权
    )

    # 转换为DataFrame
    data_list = []
    while (rs.error_code == '0') and rs.next():
        data_list.append(rs.get_row_data())

    # 登出
    bs.logout()

    if data_list:
        df = pd.DataFrame(data_list, columns=rs.fields)
        # 转换数据类型
        for col in ['open', 'high', 'low', 'close', 'volume']:
            df[col] = pd.to_numeric(df[col], errors='coerce')
        return df
    else:
        return pd.DataFrame()


def calculate_cci(high, low, close, period=14):
    """计算CCI指标"""
    # 典型价格
    typical_price = (high + low + close) / 3

    # 典型价格的简单移动平均
    sma_tp = typical_price.rolling(window=period).mean()

    # 平均绝对偏差
    mad = typical_price.rolling(window=period).apply(
        lambda x: np.mean(np.abs(x - np.mean(x))), raw=True
    )

    # 计算CCI
    cci = (typical_price - sma_tp) / (0.015 * mad + 1e-8)
    return cci


def plot_cci_chart(stock_code='sz.000592', stock_name='平潭发展'):
    """绘制CCI指标图表"""
    # 获取数据
    print(f"正在获取{stock_name}({stock_code})数据...")
    data = get_stock_data(stock_code)

    if data.empty:
        print("获取数据失败,请检查网络连接或股票代码")
        return

    print(f"成功获取 {len(data)} 条数据")

    # 计算CCI
    data['CCI'] = calculate_cci(data['high'], data['low'], data['close'])

    # 取最近100个交易日数据
    recent_data = data.tail(100).reset_index(drop=True)

    # 创建图表
    fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10))

    # 子图1:价格走势
    ax1.plot(recent_data.index, recent_data['close'], 'b-', linewidth=2, label='收盘价')
    ax1.set_ylabel('价格', fontproperties=zhfont1)
    ax1.set_title(f'{stock_name}({stock_code}) - 收盘价走势', fontproperties=zhfont1, fontsize=14)
    ax1.legend(prop=zhfont1)
    ax1.grid(True, alpha=0.3)

    # 子图2:CCI指标
    ax2.plot(recent_data.index, recent_data['CCI'], 'r-', linewidth=1.5, label='CCI')
    ax2.axhline(y=100, color='g', linestyle='--', alpha=0.7, label='超买线(+100)')
    ax2.axhline(y=-100, color='g', linestyle='--', alpha=0.7, label='超卖线(-100)')
    ax2.axhline(y=0, color='k', linestyle='-', alpha=0.5)
    ax2.fill_between(recent_data.index, 100, recent_data['CCI'], where=(recent_data['CCI'] > 100),
                     color='red', alpha=0.3, label='超买区域')
    ax2.fill_between(recent_data.index, -100, recent_data['CCI'], where=(recent_data['CCI'] < -100),
                     color='green', alpha=0.3, label='超卖区域')
    ax2.set_ylabel('CCI指标', fontproperties=zhfont1)
    ax2.set_xlabel('交易日', fontproperties=zhfont1)
    ax2.set_title('CCI指标', fontproperties=zhfont1, fontsize=14)
    ax2.legend(prop=zhfont1)
    ax2.grid(True, alpha=0.3)

    # 设置x轴刻度
    date_labels = []
    for i, date in enumerate(recent_data['date']):
        if i % 20 == 0:  # 每20个交易日显示一个日期
            date_labels.append(date[5:])  # 显示月-日
        else:
            date_labels.append('')

    ax2.set_xticks(range(len(date_labels)))
    ax2.set_xticklabels(date_labels, rotation=45)

    plt.tight_layout()
    plt.show()

    # 打印最新的CCI值
    latest_cci = recent_data['CCI'].iloc[-1]
    print(f"\n最新CCI值: {latest_cci:.2f}")
    if latest_cci > 100:
        print("状态: 超买区域")
    elif latest_cci < -100:
        print("状态: 超卖区域")
    else:
        print("状态: 正常区域")


if __name__ == '__main__':
    # 绘制平潭发展的CCI指标图
    plot_cci_chart('sz.000592', '平潭发展')

画出图像如下:

7f00b2705b09e3b55c4c3bc0b14bb01b.png

评论