Momentum:CTI(相关趋势指标)技术指标详解

Momentum:CTI(相关趋势指标)技术指标详解

一、CTI的定义

CTI(Correlation Trend Indicator,相关趋势指标) 是由著名技术分析师、数字信号处理专家John Ehlers于2020年在《股票与商品期货技术分析》(Stocks & Commodities)杂志上正式发表的一种新型动量震荡指标。

核心思想

CTI通过测量价格序列与理想趋势线 之间的统计相关性来判断市场的趋势强度。其中,"理想趋势线"被定义为一条具有恒定向上斜率的直线。CTI的本质是斯皮尔曼相关系数(Spearman Correlation Coefficient)在技术分析中的应用------它量化了当前价格走势与理想上升趋势之间的拟合程度。

与传统的趋势跟踪指标(如ADX、MACD)不同,CTI输出的数值严格限定在-1到+1之间,具有明确的统计意义。

CTI的核心特征

特征 说明
数值范围 -1 到 +1(与相关系数相同)
理论基础 斯皮尔曼等级相关系数
零轴分界 +1表示完美上升趋势,-1表示完美下降趋势,0表示无趋势/随机
开发者 John Ehlers(2020年)
默认周期 12或20

CTI的设计背景

Ehlers开发CTI的初衷是创建一个既客观又直观的趋势测量工具。传统的趋势指标要么依赖于主观的参数选择,要么缺乏统一的度量标准。CTI通过引入严格的统计学方法,将复杂的趋势分析简化为一个在-1到+1之间波动的单值,使得不同品种、不同时间周期的趋势强度具有了可比性。

CTI与其他趋势指标的对比

对比维度 CTI ADX RSI
数值范围 -1 到 +1(对称) 0 到 100 0 到 100
趋势方向 同时提供方向(正负) 不提供方向(仅强度) 不直接提供
理论基础 统计相关性 价格波动扩张 涨跌幅比率
趋势识别 严格统计意义 经验阈值判断 超买超卖判断

二、CTI的计算方法

1. 核心公式

CTI的核心计算公式为:

CTI=SpearmanCorrelation(价格,理想趋势线) \mathrm{CTI} = \mathrm{SpearmanCorrelation}(价格,理想趋势线) CTI=SpearmanCorrelation(价格,理想趋势线)

其中,"理想趋势线"是一条从1到 nnn 的递增序列(1,2,3,⋯ ,n1,2,3,\cdots,n1,2,3,⋯,n)。

2. 斯皮尔曼相关系数分解

设周期为 nnn 的价格序列为 P1,P2,...,PnP_1,P_2,...,P_nP1,P2,...,Pn(PnP_nPn 为最新价格),理想趋势线序列为 T=1,2,3,⋯ ,nT = 1,2,3,\cdots,nT=1,2,3,⋯,n。

步骤一:计算价格序列的秩(Rank)

对于价格序列 PiP_iPi,计算其在 nnn 个价格中的排名 Rank(Pi)\mathrm{Rank}(P_i)Rank(Pi)(升序排列,最低价为1,最高价为 nnn)。如有价格相等,取平均秩次。

步骤二:计算秩差值

对于每个位置 iii,计算价格秩与趋势线秩的差值:

di=Rank(Pi)−i d_i = \mathrm{Rank}(P_i) - i di=Rank(Pi)−i

步骤三:计算斯皮尔曼相关系数

CTI=1−6∑i=1ndi2n(n2−1) \mathrm{CTI} = 1 - \frac{6\sum_{i=1}^n d_i^2}{n(n^2-1)} CTI=1−n(n2−1)6∑i=1ndi2

3. pandas_ta的简化实现

根据pandas_ta官方文档,CTI 的实现是线性回归相关系数的包装函数:

CTI=corr(价格,趋势线) \mathrm{CTI} = \mathrm{corr}(价格, 趋势线) CTI=corr(价格,趋势线)

其中 corrcorr 为皮尔逊相关系数。这一简化在数学上与斯皮尔曼相关系数有细微差异,但在大多数应用中结果相近。

皮尔逊相关系数公式:

CTI=∑i=1n(Pi−Pˉ)(Ti−Tˉ)∑i=1n(Pi−Pˉ)2∑i=1n(Ti−Tˉ)2 \mathrm{CTI} = \frac{\sum_{i=1}^n(P_i-\bar{P})(T_i - \bar{T})}{\sqrt{\sum_{i=1}^n(P_i-\bar{P})^2} \sqrt{\sum_{i=1}^n (T_i - \bar{T})^2}} CTI=∑i=1n(Pi−Pˉ)2 ∑i=1n(Ti−Tˉ)2 ∑i=1n(Pi−Pˉ)(Ti−Tˉ)

其中:

  • Pˉ\bar{P}Pˉ:价格序列的均值
  • Tˉ\bar{T}Tˉ:趋势线序列的均值

4. 参数说明

参数 类型 默认值 说明
length int 12 CTI计算周期(John Ehlers通常建议12或20)
offset int 0 结果偏移周期数

5. 计算示例

假设某股票最近5个交易日(length=5)的收盘价如下:

位置(iii) 趋势线(TiT_iTi) 收盘价(PiP_iPi) Rank(Pi)\mathrm{Rank}(P_i)Rank(Pi) di=Rank(Pi)−id_i = \mathrm{Rank}(P_i)-idi=Rank(Pi)−i di2d_i^2di2
1 1 100 1 0 0
2 2 102 2 0 0
3 3 105 4 1 1
4 4 103 3 -1 1
5 5 108 5 0 0

计算过程

  • 价格排序:100(1), 102(2), 103(3), 105(4), 108(5)
  • n=5n=5n=5,∑di2=0+0+1+1+0=2\sum d_i^2=0+0+1+1+0=2∑di2=0+0+1+1+0=2
  • CTI=1−6×25×(25−1)=1−12120=1−0.1=0.9\mathrm{CTI} = 1− \frac{6 \times 2}{5 \times (25−1)} = 1 − \frac{12}{120} = 1 − 0.1 = 0.9CTI=1−5×(25−1)6×2=1−12012=1−0.1=0.9

该CTI值为0.9,表示价格序列与理想趋势线的相关性极高,存在强上升趋势。

6. 斯皮尔曼 vs 皮尔逊的区别

对比维度 斯皮尔曼相关系数 皮尔逊相关系数
测量对象 等级序的相关性 线性相关程度
对异常值敏感度 低(基于秩次) 高(基于原始值)
对数据分布要求 无(非参数) 需近似正态分布
pandas_ta实现 --- 采用皮尔逊法

三、CTI的使用方法

1. 趋势强度判断------最核心用法

CTI的正负值和绝对值大小反映了趋势的方向和强度:

CTI区间 趋势含义 操作倾向
CTI > 0.5 强上升趋势 价格与理想趋势高度相关,多头强势持仓
0.2 < CTI ≤ 0.5 中等上升趋势 上升趋势存在但不够强劲,顺势持仓
0 < CTI ≤ 0.2 弱上升趋势 上升趋势初期或末期,谨慎做多
-0.2 ≤ CTI < 0 弱下降趋势 下降趋势初期或末期,谨慎做空
-0.5 ≤ CTI < -0.2 中等下降趋势 下降趋势存在,顺势持仓空头
CTI < -0.5 强下降趋势 价格与理想趋势呈强负相关,空头强势

CTI ≈ 0:价格序列呈随机漫步状态,无明显趋势,建议观望。

2. 零轴穿越

CTI围绕零轴波动,零轴是多空力量的分界线:

信号类型 触发条件 含义 操作建议
看涨穿越 CTI从下方向上穿越零轴 市场从无趋势转向正相关,上升趋势可能启动 考虑建立多头仓位
看跌穿越 CTI从上方向下穿越零轴 市场从正相关转向无趋势/负相关,上升趋势可能结束 考虑平仓或建立空头

3. 趋势衰竭识别

CTI值处于高位(>0.5)时,若开始从高点回落,可能意味着:

CTI状态 含义 操作建议
CTI从>0.5的高位回落 趋势强度正在减弱 警惕趋势反转,考虑减仓
CTI连续多周期下降 趋势动能持续衰减 趋势可能即将结束,做好离场准备

4. 底背离与顶背离

与价格走势的背离是CTI的重要辅助信号:

背离类型 价格表现 CTI表现 信号含义
顶背离 价格创出新高 CTI未能创出新高(形成更低高点) 上涨趋势强度减弱,警惕见顶
底背离 价格创出新低 CTI未能创出新低(形成更高低点) 下跌趋势强度减弱,关注反弹

5. 与其他指标的配合

配合指标 作用 具体用法
移动平均线 确认价格位置 CTI > 0.5 + 价格在MA20上方 → 强趋势确认
ADX 验证趋势强度 CTI与ADX同时显示强趋势时信号更可靠
成交量 验证动能 CTI上升伴随成交量放大 → 趋势确认
支撑/阻力位 确认关键位置 CTI信号出现在关键价位时可靠性更高

6. 注意事项与局限性

使用CTI前需了解以下要点

局限性 说明
计算窗口敏感 CTI仅关注固定窗口内的相关性,可能忽略更长时间尺度的趋势结构
滞后性质 基于历史数据的相关系数计算,本质上有滞后性
震荡市假信号 在横盘整理市场中,CTI可能在零轴附近随机波动,产生假穿越信号
参数需要优化 默认12周期可能不适合所有品种和时间框架,需要根据实际情况调整
不能单独使用 建议结合其他趋势确认指标使用

四、使用pandas_ta计算CTI(附示例代码)

1. pandas_ta中的CTI函数

pandas_ta库内置了CTI指标的完整实现,函数位于momentum模块中。

2. 函数完整参数

python 复制代码
pandas_ta.momentum.cti(close, length=None, offset=None, **kwargs)

参数详解

参数 类型 默认值 说明
close pd.Series 必需 收盘价序列
length int 12 CTI计算周期(John Ehlers建议12或20)
offset int 0 结果偏移周期数
fillna (可选) --- 填充NaN值的方式

返回值pd.Series------CTI值序列(范围-1到+1)。

注意:pandas_ta中的CTI实现使用皮尔逊相关系数,而非原始的斯皮尔曼相关系数。在多数实际应用中两种方法给出的趋势方向判断是一致的。

3. 示例代码

python 复制代码
import pandas as pd
import pandas_ta as ta
import numpy as np
import matplotlib.pyplot as plt

# ========== 第一步:准备数据 ==========
np.random.seed(42)
dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='D')
n = len(dates)

# 生成带趋势和周期波动的价格序列
trend = np.linspace(0, 25, n)
cycle = np.sin(np.linspace(0, 6 * np.pi, n)) * 8
noise = np.random.randn(n) * 2
price_series = 100 + trend + cycle + noise

df = pd.DataFrame(index=dates)
df['close'] = price_series
df['high'] = df['close'] + np.abs(np.random.randn(n)) * 2 + 1
df['low'] = df['close'] - np.abs(np.random.randn(n)) * 2 - 1
df['volume'] = np.random.randint(1000000, 10000000, n)

print("=" * 60)
print("数据预览:")
print(df.head())
print("\n" + "=" * 60 + "\n")

# ========== 第二步:计算CTI(基础用法) ==========
# 使用默认参数 length=12
df['CTI'] = ta.cti(df['close'])

print("CTI计算结果(最近10行):")
print(df[['close', 'CTI']].tail(10))
print("\n" + "=" * 60 + "\n")

# ========== 第三步:手动验证CTI计算 ==========
def manual_cti(close, length=12):
    """手动计算CTI验证pandas_ta结果"""
    # 创建理想趋势线
    trend_line = np.arange(1, length + 1)
    n = length
    
    cti_values = []
    for i in range(len(close)):
        if i < length - 1:
            cti_values.append(np.nan)
            continue
        
        # 取最近length个价格
        prices = close.iloc[i-length+1:i+1].values
        
        # 计算皮尔逊相关系数
        corr_matrix = np.corrcoef(prices, trend_line)
        cti = corr_matrix[0, 1]
        cti_values.append(cti)
    
    return pd.Series(cti_values, index=close.index)

df['CTI_manual'] = manual_cti(df['close'])

# 验证一致性
diff = (df['CTI'] - df['CTI_manual']).abs().max()
print(f"pandas_ta与手动计算的最大差异:{diff:.10f}")
print("\n" + "=" * 60 + "\n")

# ========== 第四步:不同周期的CTI ==========
# 短线参数 (9)
df['CTI_9'] = ta.cti(df['close'], length=9)

# 标准参数 (12)
df['CTI_12'] = ta.cti(df['close'], length=12)

# 长线参数 (20)
df['CTI_20'] = ta.cti(df['close'], length=20)

print("不同周期CTI对比(最近5行):")
print(df[['close', 'CTI_9', 'CTI_12', 'CTI_20']].tail())
print("\n" + "=" * 60 + "\n")

# ========== 第五步:生成趋势强度信号 ==========
# 定义趋势强度阈值
STRONG_TREND = 0.5
WEAK_TREND = 0.2

df['trend_signal'] = ''
df.loc[df['CTI'] > STRONG_TREND, 'trend_signal'] = '强上升趋势'
df.loc[(df['CTI'] > WEAK_TREND) & (df['CTI'] <= STRONG_TREND), 'trend_signal'] = '中等上升趋势'
df.loc[(df['CTI'] > 0) & (df['CTI'] <= WEAK_TREND), 'trend_signal'] = '弱上升趋势'
df.loc[(df['CTI'] < 0) & (df['CTI'] >= -WEAK_TREND), 'trend_signal'] = '弱下降趋势'
df.loc[(df['CTI'] < -WEAK_TREND) & (df['CTI'] >= -STRONG_TREND), 'trend_signal'] = '中等下降趋势'
df.loc[df['CTI'] < -STRONG_TREND, 'trend_signal'] = '强下降趋势'

print("趋势信号统计:")
print(df['trend_signal'].value_counts())
print("\n" + "=" * 60 + "\n")

# ========== 第六步:零轴穿越信号 ==========
df['CTI_above_zero'] = df['CTI'] > 0
df['cross_above_zero'] = (df['CTI_above_zero'] == True) & (df['CTI_above_zero'].shift(1) == False)
df['cross_below_zero'] = (df['CTI_above_zero'] == False) & (df['CTI_above_zero'].shift(1) == True)

df['signal'] = ''
df.loc[df['cross_above_zero'], 'signal'] = '买入(上穿零轴)'
df.loc[df['cross_below_zero'], 'signal'] = '卖出(下穿零轴)'

print("零轴穿越信号(最近10个):")
signals = df[df['signal'] != ''].tail(10)
if not signals.empty:
    print(signals[['close', 'CTI', 'signal']])
else:
    print("近期无穿越信号")
print("\n" + "=" * 60 + "\n")

# ========== 第七步:趋势衰竭检测 ==========
# 检测CTI从高位回落的趋势衰竭信号
df['cti_peak'] = (df['CTI'] > 0.5) & (df['CTI'] < df['CTI'].shift(1)) & (df['CTI'].shift(1) > df['CTI'].shift(2))
df['trend_exhaustion'] = df['cti_peak'] & (df['CTI'].shift(1) > 0.6)

print("趋势衰竭信号统计:")
print(f"高位回落(趋势衰竭预警)数量:{df['trend_exhaustion'].sum()}")
print("\n" + "=" * 60 + "\n")

# ========== 第八步:背离检测(简化版) ==========
# 计算20日价格变化和CTI变化
df['price_change_20d'] = df['close'].diff(20)
df['cti_change_20d'] = df['CTI'].diff(20)

# 检测潜在背离
df['potential_bearish_div'] = (df['price_change_20d'] > 0) & (df['cti_change_20d'] < 0)
df['potential_bullish_div'] = (df['price_change_20d'] < 0) & (df['cti_change_20d'] > 0)

print("潜在背离信号统计(20日尺度):")
print(f"潜在顶背离(价格涨CTI跌)数量:{df['potential_bearish_div'].sum()}")
print(f"潜在底背离(价格跌CTI涨)数量:{df['potential_bullish_div'].sum()}")
print("注:完整背离需结合局部高/低点分析,此处为方向对比")
print("\n" + "=" * 60 + "\n")

# ========== 第九步:策略回测(零轴穿越策略) ==========
# 策略:CTI > 0 时持仓多头
df['position'] = (df['CTI'] > 0).astype(int)

# 计算收益
df['returns'] = df['close'].pct_change()
df['strategy_returns'] = df['position'].shift(1) * df['returns']

total_return_buyhold = (1 + df['returns']).prod() - 1
total_return_strategy = (1 + df['strategy_returns']).prod() - 1
win_rate = (df['strategy_returns'] > 0).sum() / (df['strategy_returns'] != 0).sum() if (df['strategy_returns'] != 0).sum() > 0 else 0

print("=" * 60)
print("策略绩效统计(CTI零轴穿越策略回测):")
print(f"买入持有策略总收益率:{total_return_buyhold:.2%}")
print(f"CTI零轴穿越策略总收益率:{total_return_strategy:.2%}")
print(f"策略胜率:{win_rate:.2%}")
print("\n注意:此为简化回测,仅供参考")
print("=" * 60 + "\n")

# ========== 第十步:可视化 ==========
plt.figure(figsize=(14, 10))

# 子图1:价格走势
plt.subplot(2, 1, 1)
plt.plot(df.index[-150:], df['close'][-150:], label='Close Price', 
         linewidth=1.5, color='black')
plt.title('Price Chart (Last 150 days)', fontsize=14)
plt.ylabel('Price')
plt.legend()
plt.grid(True, alpha=0.3)

# 子图2:CTI指标
plt.subplot(2, 1, 2)
plt.plot(df.index[-150:], df['CTI'][-150:], label='CTI (length=12)', 
         linewidth=1.5, color='blue')
plt.axhline(y=0, color='gray', linestyle='-', linewidth=1, label='零轴')
plt.axhline(y=0.5, color='green', linestyle='--', linewidth=1, label='强趋势线 (+0.5)')
plt.axhline(y=-0.5, color='red', linestyle='--', linewidth=1, label='强趋势线 (-0.5)')
plt.axhline(y=0.2, color='orange', linestyle=':', linewidth=0.8, label='弱趋势线 (+0.2)')
plt.axhline(y=-0.2, color='orange', linestyle=':', linewidth=0.8, label='弱趋势线 (-0.2)')

# 填充强趋势区域
plt.fill_between(df.index[-150:], 0.5, 1, alpha=0.1, color='green', label='强上升区')
plt.fill_between(df.index[-150:], -1, -0.5, alpha=0.1, color='red', label='强下降区')

# 标记买卖点
buy_signals = df[df['cross_above_zero']]
sell_signals = df[df['cross_below_zero']]
plt.scatter(buy_signals.index[-20:], buy_signals['CTI'][-20:], 
            color='green', marker='^', s=80, label='买入信号', alpha=0.8)
plt.scatter(sell_signals.index[-20:], sell_signals['CTI'][-20:], 
            color='red', marker='v', s=80, label='卖出信号', alpha=0.8)

plt.title('CTI (Correlation Trend Indicator) - Trend Strength Analysis', fontsize=14)
plt.xlabel('Date')
plt.ylabel('CTI Value')
plt.ylim(-1.1, 1.1)
plt.legend(loc='upper left')
plt.grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

# ========== 第十一步:不同周期CTI对比 ==========
plt.figure(figsize=(14, 6))
plt.plot(df.index[-150:], df['CTI_9'][-150:], label='CTI (9) - Fast', 
         linewidth=1, alpha=0.7)
plt.plot(df.index[-150:], df['CTI_12'][-150:], label='CTI (12) - Standard', 
         linewidth=1.5, color='blue')
plt.plot(df.index[-150:], df['CTI_20'][-150:], label='CTI (20) - Slow', 
         linewidth=1.5, color='green')
plt.axhline(y=0, color='gray', linestyle='-', linewidth=0.8)
plt.axhline(y=0.5, color='green', linestyle='--', linewidth=0.8)
plt.axhline(y=-0.5, color='red', linestyle='--', linewidth=0.8)
plt.title('CTI: Different Periods Comparison (9, 12, 20)', fontsize=14)
plt.xlabel('Date')
plt.ylabel('CTI Value')
plt.ylim(-1.1, 1.1)
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

# ========== 第十二步:数据清洗提示 ==========
nan_count = df['CTI'].isna().sum()
print(f"\nCTI初始NaN数量:{nan_count}")
print("原因:CTI需要至少length个周期的数据才能计算相关系数")
print("处理建议:df_clean = df.iloc[12:].copy()")

五、总结

CTI(相关趋势指标)是一种基于统计相关性的趋势量化工具,其核心价值与定位如下:

维度 特点
核心创新 将统计相关系数引入技术分析,量化价格与理想趋势的拟合程度
理论来源 John Ehlers(2020年),基于斯皮尔曼/皮尔逊相关系数
数值范围 -1 到 +1,具有明确的统计意义
三大核心信号 零轴穿越、趋势强度等级、极值回落预警
最佳应用场景 趋势确认、趋势强度评估、多品种趋势比较
主要局限 滞后性、窗口敏感、震荡市假信号

实战使用三原则

  1. 用CTI验证趋势,而非发现趋势:CTI更适合确认已识别的趋势强度,而非作为入场信号的唯一依据
  2. 大于0.5是强趋势门槛:当CTI值超过0.5时,表明价格走势与理想趋势高度相关,是较为可靠的趋势确认信号
  3. 高位回落是风险警示:当CTI从大于0.5的高位开始回落时,即使价格仍在上涨,也应警惕趋势强度正在衰减

最后提醒:CTI的最大特色在于其数学严谨性------它将"趋势强度"这一看似主观的概念量化为具有统计意义的相关系数。这使得不同品种、不同时间周期的趋势强度可以直接比较,为量化交易策略的开发提供了客观依据。然而,正如Ehlers本人所强调的,CTI并非完美的预测工具,而是帮助交易者"看到"市场当前状态的透镜。将其与移动平均线、成交量等传统工具配合使用,才能发挥最大价值。

相关推荐
fengxin_rou1 小时前
【滑动窗口与前缀和算法实战】:LeetCode560.438 高频题深度解析
java·算法·leetcode
Dillon Dong1 小时前
【风电控制】FPGA vs DSP 在ADC采样中的选择——从架构差异到工程实践
算法·变流器·风电控制·dfig
科研小白_1 小时前
【第九期:MATLAB点云处理基础】基于 Alpha Shapes 的边缘点提取
算法
sali-tec1 小时前
C# 基于OpenCv的视觉工作流-章80-长短脚
图像处理·人工智能·opencv·算法·计算机视觉
sul.i1 小时前
浅析·指针
算法
春日见1 小时前
策略梯度算法
算法
Brilliantwxx1 小时前
【算法从零到千】【1-7】 双指针算法
开发语言·c++·笔记·算法·leetcode·推荐算法
小许同学记录成长1 小时前
孔洞修补算法
算法
随意起个昵称1 小时前
线性dp-计数类题目9(斐波那契字符串)
算法·动态规划