无论投资流派如何划分,其核心目标都是构建一个可持续、可优化、能适应市场的个人策略体系。在这个过程中,借助先进的生产力工具成为关键。本文将探讨一种将传统技术分析与现代机器学习 思维结合的思路:利用K近邻算法与卡尔曼滤波来优化经典的相对强弱指标,以期获得更适应市场动态的信号。
1. 命题:当传统指标遇见机器学习
技术指标的本质是基于历史价格数据来推断未来走势,这决定了其天然的滞后性,且容易因历史数据的特定模式而产生“过拟合”。因此,一个核心问题是:能否通过监督学习的方法,为RSI这类指标注入新的活力?
本文的核心思路是:在计算标准RSI的基础上,构建多维特征,运用KNN算法寻找与当前市场状态相似的历史模式,生成一个“机器学习增强版”的RSI信号,最后通过卡尔曼滤波进行平滑降噪,从而得到一个更稳健、更能反映市场结构变化的指标。
2. 概念:RSI的局限性
相对强弱指标通过计算特定周期内平均涨幅与平均跌幅的比率,来评估资产的超买超卖状态。其公式为:
RSI = 100 - 100 / (1 + RS),其中 RS = 平均涨幅 / 平均跌幅。
尽管应用广泛,RSI在实际使用中仍存在几点明显的数学局限性:
- 权重均等:其滚动平均计算对周期内所有价格变动赋予相同权重,无法强化近期波动(更反映当前情绪)或弱化远期数据的影响。
- 响应滞后:当价格出现突发性趋势行情时,指标需等待数个周期数据更新后才能充分反映变化,难以捕捉短期拐点。
- 横盘失真:在价格窄幅震荡期间,RSI会因短期涨跌交替而频繁穿越阈值,产生大量无效的虚假信号。
3. 解题:融合思路
为解决上述问题,我们设计以下步骤:
- 多特征提取:在标准RSI基础上,构建如RSI动量、波动率、斜率以及与价格本身的动量关系等特征,形成描述市场状态的特征向量。
- 历史模式匹配:利用KNN算法,在当前时点向前回溯一定窗口,寻找历史上与当前特征向量最相似的K个状态,并以这些历史状态的RSI值来“修正”当前的RSI预期。
- 信号融合与平滑:将标准RSI与KNN修正后的RSI进行加权融合,得到初步的机器学习RSI。最后,应用卡尔曼滤波器对这一信号序列进行平滑处理,滤除噪声,得到最终信号。
4. 代码实现
我们使用Python 的akshare库获取数据,并利用scikit-learn实现KNN算法。以下是关键步骤的代码摘要。
4.1 参数配置
# RSI参数
rsiLength = 14
useSmoothing = True
smoothingLength = 3
maType = 'EMA'
# KNN参数
useKnn = True
knnNeighbors = 5
knnLookback = 100
knnWeight = 0.5
featureCount = 3
# 交易阈值
rsiOverbought = 70
rsiOversold = 30
# 滤波参数
useFilter = True
filterMethod = 'Kalman'
filterStrength = 0.3
4.2 数据获取与特征工程
import akshare as ak
import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsRegressor
from sklearn.preprocessing import MinMaxScaler
def download_data(symbol, start_date, end_date, interval='daily'):
"""使用akshare下载ETF日线数据"""
df = ak.fund_etf_hist_em(symbol=symbol, period="daily")
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)
df.sort_index(inplace=True)
df = df.loc[start_date:end_date]
df = df[['开盘', '最高', '最低', '收盘', '成交量']]
df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']
return df
def calculate_rsi(series, period):
"""计算标准RSI"""
delta = series.diff()
gain = delta.clip(lower=0)
loss = -delta.clip(upper=0)
avg_gain = gain.ewm(alpha=1/period, adjust=False).mean()
avg_loss = loss.ewm(alpha=1/period, adjust=False).mean()
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
return rsi
# 计算标准RSI
df['standardRsi'] = calculate_rsi(df['Close'], rsiLength)
# 构建特征:例如RSI动量、波动率、斜率等
df['rsi_mom'] = df['standardRsi'] - df['standardRsi'].shift(3)
df['rsi_vol'] = df['standardRsi'].rolling(10).std()
df['price_mom'] = df['Close'] - df['Close'].shift(5)
features = ['rsi_mom', 'rsi_vol', 'price_mom']
4.3 应用KNN与卡尔曼滤波
def apply_kalman(series, strength):
"""简易卡尔曼滤波实现(一维)"""
out = series.copy()
for i in range(1, len(series)):
out.iloc[i] = out.iloc[i-1] + strength * (series.iloc[i] - out.iloc[i-1])
return out
# 初始化结果列
ml_rsi = pd.Series(index=df.index, dtype=float)
if useKnn:
print("正在应用KNN算法...")
for idx in range(knnLookback, len(df)):
# 准备训练窗口
window = df.iloc[idx - knnLookback:idx]
X_train = window[features].values
y_train = window['standardRsi'].values
# 归一化
scaler = MinMaxScaler()
Xs = scaler.fit_transform(X_train)
# 训练KNN并预测
knn = KNeighborsRegressor(n_neighbors=knnNeighbors, weights='distance')
knn.fit(Xs, y_train)
x_curr = df.iloc[[idx]][features].values
x_curr_scaled = scaler.transform(x_curr)
pred = knn.predict(x_curr_scaled)[0]
# 加权融合
base_rsi = df['standardRsi'].iloc[idx]
ml_rsi.iloc[idx] = (1 - knnWeight) * base_rsi + knnWeight * pred
# 填充前期的数据
ml_rsi.iloc[:knnLookback] = df['standardRsi'].iloc[:knnLookback]
else:
ml_rsi = df['standardRsi'].copy()
# 应用卡尔曼滤波平滑
if useFilter and filterMethod == 'Kalman':
print("正在应用卡尔曼滤波...")
final_rsi = apply_kalman(ml_rsi, filterStrength)
else:
final_rsi = ml_rsi
df['enhancedRsi'] = final_rsi
5. 结果与分析
执行上述代码后,我们可以得到优化后的RSI序列。下图展示了标准RSI(橙色)与增强后RSI(蓝色)的对比。可以观察到,经过KNN调整与卡尔曼滤波后的信号曲线更为平滑,对趋势的响应在保持灵敏度的同时,减少了在横盘区域的无效波动。

趋势特征分析示例(基于某ETF数据):
- 整体趋势:指标从某一高位持续下降至中性偏低区间,显示市场情绪转弱。
- 信号质量:增强后的RSI有效过滤了部分盘整期间的锯齿状波动,使得超买/超卖信号更为清晰。
- 应用价值:这种方法为技术指标的分析提供了一种数据驱动的优化思路,尤其适合希望将量化交易 思维与传统分析相结合的个人投资者,用于构建更稳健的信号生成模块。
注:本文所有分析与结论均基于历史数据与模型回测,旨在提供技术思路分享,不构成任何投资建议。市场有风险,投资需谨慎。