你有没有过这样的经历?
某个下午,你盯着一只股票,价格在关键支撑位上来回试探。突然,一根大阳线拔地而起,突破了阻力位。你兴奋地点下买入,心想"终于等到了"。
结果呢?第二天,价格掉头向下,直接跌回原来的区间。你被挂在了最高点。
更让人崩溃的是,这种事不是偶尔发生——是反复发生。一次、两次、五次、十次。每次突破你都追进去,每次都被打回来。你开始怀疑自己是不是被市场针对了。
真相是:你不是运气差,你是缺少一个趋势过滤器。
市场大部分时间(大约70%)都处于震荡状态,真正的趋势行情只占30%左右。如果你在震荡市里不断追逐"突破信号",就会被反复假突破打脸。
今天这篇文章,就是帮你解决这个问题。我们会讲清楚:假突破到底是什么、为什么会出现、怎么用ADX指标判断趋势强度、双滤心法则怎么用、多周期过滤怎么做。
Why:为什么假突破是趋势跟踪的头号杀手?
假突破有多常见?
先给你一个数据感受一下。
有研究对过去20年A股主要指数的突破信号做了统计。以20日高点突破为例,大约有40%-60%的突破是假突破——也就是价格突破后短期内又回到了原区间。
换句话说,你每追一次突破,就有将近一半的概率被假突破打脸。
这个比例比你想象的高吧?
假突破的三大成因
成因一:震荡市中的反复试探
在震荡行情中,价格会反复测试支撑和阻力位。每次测试看起来都像是要突破,但最终都会回来。
想象一个乒乓球在桌面上来回弹跳。每次弹到边缘,看起来都像要飞出去,但大部分时候它都会弹回来。这就是震荡市里的"假突破"。
成因二:流动性不足导致的毛刺
当市场流动性不足时(比如开盘前、收盘前、节假日前后),少量的买单或卖单就能让价格出现剧烈波动。这种波动会制造出"突破"的假象,但很快价格就会回到正常水平。
特别是在A股市场,9:25-9:30的集合竞价、14:57-15:00的收盘集合竞价,以及一些低流动性个股的日常交易中,毛刺现象非常普遍。
成因三:主力资金的故意诱骗
这是最不厚道的一种。主力资金知道很多交易者会用突破策略,于是故意制造假突破来"收割"这些跟风盘。
具体做法是:先把价格推到关键阻力位上方,引诱突破交易者追入;然后反手卖出,把价格打回去。追突破的人被全部套住。
这种现象在期货市场中尤其常见,专业术语叫"扫止损"(stop hunting)。
假突破的代价
假突破不只是让你亏一笔钱那么简单。它还有几个隐性代价:
1. 手续费和滑点损耗:每次假突破都会产生交易成本,频繁假突破会不断侵蚀你的本金
2. 心理打击:连续被假突破打脸后,你会开始怀疑所有信号,甚至错过真正的突破
3. 策略失效:如果你因为几次假突破就不断修改策略参数,最终会把策略改废
所以,趋势过滤不是锦上添花,而是趋势跟踪策略的生死线。
What:趋势过滤的核心工具
一、ADX指标:判断趋势强度的"温度计"
ADX(Average Directional Index,平均趋向指数)是判断趋势强度最经典的指标。它由技术分析大师 J. Welles Wilder 在1978年发明。
ADX的核心思想是:趋势有强弱之分,ADX告诉你当前趋势有多强。
ADX的解读标准
| ADX 值 | 市场状态 | 操作建议 | | --- | --- | --- | | < 20 | 震荡市,无明显趋势 | 不做趋势跟踪,改用震荡策略或观望 | | 20-25 | 趋势可能正在形成 | 开始关注,但暂不入场 | | 25-50 | 明确趋势 | 可以做趋势跟踪 | | 50-75 | 强趋势 | 趋势跟踪的最佳时机 | | > 75 | 极端趋势 | 警惕反转,谨慎追高 |
记住这个关键阈值:ADX > 25 做趋势,ADX < 20 做震荡或观望。
ADX的计算原理(通俗版)
ADX的计算基于三个概念:
1. +DI(正向方向指标):衡量上涨方向的力量
2. -DI(负向方向指标):衡量下跌方向的力量
3. DX(方向指数):|+DI - -DI| / (+DI + -DI) × 100
ADX就是DX的14周期移动平均。
通俗理解:
• 当 +DI 远大于 -DI 时,说明上涨力量远大于下跌力量,ADX 会上升
• 当 +DI 和 -DI 差不多时,说明多空力量均衡,ADX 会下降
• ADX上升 = 趋势在加强;ADX下降 = 趋势在减弱
ADX的Python实现
// python
import pandas as pd
import numpy as np
def calculate_adx(df, period=14):
"""计算ADX指标"""
# 计算 True Range
df['high_low'] = df['high'] - df['low']
df['high_close'] = abs(df['high'] - df['close'].shift(1))
df['low_close'] = abs(df['low'] - df['close'].shift(1))
df['true_range'] = df[['high_low', 'high_close', 'low_close']].max(axis=1)
# 计算 +DM 和 -DM
df['up_move'] = df['high'] - df['high'].shift(1)
df['down_move'] = df['low'].shift(1) - df['low']
df['plus_dm'] = np.where(
(df['up_move'] > df['down_move']) & (df['up_move'] > 0),
df['up_move'], 0
)
df['minus_dm'] = np.where(
(df['down_move'] > df['up_move']) & (df['down_move'] > 0),
df['down_move'], 0
)
# 平滑计算(使用 Wilder 平滑法)
atr = df['true_range'].rolling(window=period).sum()
plus_di = 100 * (df['plus_dm'].rolling(window=period).sum() / atr)
minus_di = 100 * (df['minus_dm'].rolling(window=period).sum() / atr)
# 计算 DX 和 ADX
dx = 100 * abs(plus_di - minus_di) / (plus_di + minus_di)
df['ADX'] = dx.rolling(window=period).mean()
df['plus_DI'] = plus_di
df['minus_DI'] = minus_di
return df
# 使用示例
df = pd.read_csv('stock_data.csv')
df = calculate_adx(df)
# 判断当前趋势状态
latest_adx = df['ADX'].iloc[-1]
if latest_adx > 25:
print(f"当前ADX={latest_adx:.1f},处于趋势市场,可以做趋势跟踪")
elif latest_adx < 20:
print(f"当前ADX={latest_adx:.1f},处于震荡市场,建议观望或做震荡策略")
else:
print(f"当前ADX={latest_adx:.1f},趋势尚不明确,继续观察")
二、双滤心法则:时间和幅度的双重确认
双滤心法则是过滤假突破的实战利器。核心思想很简单:不要相信第一次突破,要等时间和幅度的双重确认。
滤心一:时间过滤(隔日确认)
假突破通常持续时间很短——可能就是一根K线的毛刺。真正的突破则会持续多天。
所以最简单的过滤方法是:突破后要等至少1-2天的确认。
// python
def time_filter_breakout(df, breakout_day, confirm_days=2):
"""时间过滤:突破后等待N天确认"""
breakout_price = df['close'].iloc[breakout_day]
# 检查后续N天是否保持在突破位之上
for i in range(1, confirm_days + 1):
if breakout_day + i >= len(df):
return False, "数据不足"
if df['close'].iloc[breakout_day + i] < breakout_price:
return False, f"第{i}天收盘价回落,假突破"
return True, f"突破已确认{confirm_days}天,为有效突破"
# 示例
confirmed, msg = time_filter_breakout(df, breakout_day=100, confirm_days=2)
print(f"突破确认结果:{msg}")
时间过滤的优缺点:
• 优点:简单有效,能过滤掉大部分毛刺型假突破
• 缺点:入场会延迟1-2天,可能错过部分利润空间
滤心二:幅度过滤(突破X%才认定)
另一个过滤方式是要求突破必须达到一定幅度。小幅度的突破不算突破,可能是噪音。
// python
def magnitude_filter_breakout(current_price, resistance_level, threshold=0.02):
"""幅度过滤:突破幅度必须超过阈值"""
breakout_pct = (current_price - resistance_level) / resistance_level
if breakout_pct >= threshold:
return True, f"突破幅度{breakout_pct*100:.2f}%,超过阈值{threshold*100:.1f}%"
else:
return False, f"突破幅度{breakout_pct*100:.2f}%,未达阈值{threshold*100:.1f}%"
# 示例
resistance = 50.0 # 阻力位50元
current = 50.8 # 当前价50.8元
confirmed, msg = magnitude_filter_breakout(current, resistance, threshold=0.02)
print(f"突破确认:{msg}")
# 输出:突破幅度1.60%,未达阈值2.0% → 假突破
幅度阈值怎么定?
这取决于品种的波动特性:
• 波动小的品种(如大盘蓝筹股):1%-2%
• 波动中等的品种(如中小盘股):2%-3%
• 波动大的品种(如创业板、期货):3%-5%
双滤心联合使用
最佳实践是把时间过滤和幅度过滤结合使用:
// python
def dual_filter_breakout(df, breakout_day, resistance,
confirm_days=2, threshold=0.02):
"""双滤心法则:时间+幅度双重确认"""
# 幅度检查
breakout_pct = (df['close'].iloc[breakout_day] - resistance) / resistance
if breakout_pct < threshold:
return {
'confirmed': False,
'reason': f'幅度不足:{breakout_pct*100:.2f}% < {threshold*100:.1f}%',
'action': '不操作'
}
# 时间检查
for i in range(1, confirm_days + 1):
if breakout_day + i >= len(df):
return {
'confirmed': False,
'reason': '确认天数不足,继续观察',
'action': '等待'
}
if df['close'].iloc[breakout_day + i] < resistance:
return {
'confirmed': False,
'reason': f'第{i}天回落,假突破',
'action': '不操作'
}
return {
'confirmed': True,
'reason': f'幅度{breakout_pct*100:.2f}%,已确认{confirm_days}天',
'action': '可以入场'
}
三、多周期过滤:从大到小确认趋势
单看一个时间周期容易被骗。多周期过滤就是用大周期定方向,小周期找入场点。
多周期过滤的逻辑
• 大周期(如周线、日线):判断大趋势方向
• 中周期(如4小时、2小时):确认趋势的持续性
• 小周期(如1小时、30分钟):找具体的入场点
规则很简单:
• 大周期趋势向上 → 只找做多机会
• 大周期趋势向下 → 只找做空机会
• 大周期震荡 → 不做趋势跟踪
多周期过滤代码实现
// python
def multi_timeframe_filter(daily_data, weekly_data):
"""多周期趋势过滤"""
# 大周期(周线)判断趋势方向
weekly_adx = calculate_adx(weekly_data.copy())['ADX'].iloc[-1]
weekly_ma20 = weekly_data['close'].rolling(20).mean().iloc[-1]
weekly_price = weekly_data['close'].iloc[-1]
if weekly_adx < 20:
return {
'trend': '震荡',
'direction': '无',
'action': '观望,不做趋势跟踪'
}
if weekly_price > weekly_ma20 and weekly_adx >= 25:
big_trend = '上升'
elif weekly_price < weekly_ma20 and weekly_adx >= 25:
big_trend = '下降'
else:
big_trend = '不明朗'
# 小周期(日线)寻找入场时机
daily_adx = calculate_adx(daily_data.copy())['ADX'].iloc[-1]
daily_price = daily_data['close'].iloc[-1]
daily_ma20 = daily_data['close'].rolling(20).mean().iloc[-1]
if big_trend == '上升' and daily_price > daily_ma20:
return {
'trend': '上升',
'direction': '做多',
'action': '周线上升趋势确认,日线出现买入信号,可以入场做多'
}
elif big_trend == '下降' and daily_price < daily_ma20:
return {
'trend': '下降',
'direction': '做空',
'action': '周线下降趋势确认,日线出现卖出信号,可以入场做空'
}
else:
return {
'trend': big_trend,
'direction': '等待',
'action': '大小周期不一致,等待共振'
}
How:完整的趋势过滤系统实战
第一步:建立你的趋势过滤清单
每次做趋势跟踪交易前,过一遍这个清单:
| 检查项 | 通过标准 | 当前状态 | | --- | --- | --- | | ADX > 25? | 是→趋势市,继续 | | | 突破幅度 > 阈值? | 是→有效突破 | | | 突破持续 > 确认天数? | 是→确认突破 | | | 大周期趋势一致? | 是→顺势交易 | | | 成交量配合? | 放量突破更有效 | |
5项中至少4项通过,才值得入场。
第二步:ADX + 双滤心 + 多周期联合策略
// python
class TrendFilterSystem:
"""趋势过滤系统"""
def __init__(self, adx_period=14, adx_threshold=25,
breakout_threshold=0.02, confirm_days=2,
swing_order=5):
self.adx_period = adx_period
self.adx_threshold = adx_threshold
self.breakout_threshold = breakout_threshold
self.confirm_days = confirm_days
self.swing_order = swing_order
def check_signal(self, daily_data, weekly_data):
"""综合趋势过滤检查"""
result = {
'signal': '无',
'adx_ok': False,
'breakout_ok': False,
'time_ok': False,
'multi_tf_ok': False,
'details': []
}
# 1. ADX 过滤
daily_with_adx = calculate_adx(daily_data.copy(), self.adx_period)
current_adx = daily_with_adx['ADX'].iloc[-1]
if current_adx >= self.adx_threshold:
result['adx_ok'] = True
result['details'].append(f"✓ ADX={current_adx:.1f},趋势市场")
else:
result['details'].append(f"✗ ADX={current_adx:.1f},震荡市场,不建议趋势跟踪")
return result
# 2. 检测突破
highs = daily_data['high'].rolling(self.swing_order).max()
resistance = highs.iloc[-self.confirm_days - 1] # 前N天的高点
current_price = daily_data['close'].iloc[-1]
breakout_pct = (current_price - resistance) / resistance
if breakout_pct >= self.breakout_threshold:
result['breakout_ok'] = True
result['details'].append(f"✓ 突破幅度{breakout_pct*100:.2f}%")
else:
result['details'].append(f"✗ 突破幅度{breakout_pct*100:.2f}%不足")
return result
# 3. 时间确认
confirmed = True
for i in range(1, self.confirm_days + 1):
idx = len(daily_data) - 1 - i
if idx < 0 or daily_data['close'].iloc[idx] < resistance:
confirmed = False
break
if confirmed:
result['time_ok'] = True
result['details'].append(f"✓ 已确认{self.confirm_days}天")
else:
result['details'].append(f"✗ 时间确认失败")
return result
# 4. 多周期过滤
weekly_with_adx = calculate_adx(weekly_data.copy(), self.adx_period)
weekly_adx = weekly_with_adx['ADX'].iloc[-1]
weekly_ma = weekly_data['close'].rolling(20).mean().iloc[-1]
weekly_price = weekly_data['close'].iloc[-1]
if weekly_price > weekly_ma and weekly_adx >= self.adx_threshold:
result['multi_tf_ok'] = True
result['details'].append(f"✓ 大周期趋势向上")
else:
result['details'].append(f"✗ 大周期趋势不支持")
# 综合判断
checks_passed = sum([
result['adx_ok'],
result['breakout_ok'],
result['time_ok'],
result['multi_tf_ok']
])
if checks_passed >= 3:
result['signal'] = '做多'
else:
result['signal'] = '观望'
return result
第三步:参数优化建议
不同的市场和品种,参数需要调整:
| 市场 | ADX周期 | ADX阈值 | 突破幅度 | 确认天数 | | --- | --- | --- | --- | --- | | A股日线 | 14 | 25 | 2%-3% | 2 | | A股周线 | 14 | 20 | 3%-5% | 1 | | 期货日线 | 14 | 25 | 1%-2% | 2 | | 外汇日线 | 14 | 25 | 0.5%-1% | 2-3 | | 加密货币 | 14 | 20 | 3%-5% | 1-2 |
关键原则:
• 波动大的品种:提高突破幅度阈值,避免噪音
• 流动性好的品种:可以降低确认天数
• 震荡频繁的市场:提高ADX阈值到30
第四步:回测验证过滤效果
// python
def backtest_with_filter(df, system):
"""回测对比:有过滤 vs 无过滤"""
# 无过滤:所有突破都交易
no_filter_signals = []
resistance = df['high'].rolling(20).max().shift(1)
for i in range(21, len(df)):
if df['close'].iloc[i] > resistance.iloc[i]:
no_filter_signals.append(i)
# 有过滤:通过ADX+双滤心过滤
filtered_signals = []
for i in range(21, len(df)):
if df['close'].iloc[i] > resistance.iloc[i]:
# 检查ADX
if df['ADX'].iloc[i] >= 25:
# 检查幅度
pct = (df['close'].iloc[i] - resistance.iloc[i]) / resistance.iloc[i]
if pct >= 0.02:
# 检查时间确认
if i >= 2 and df['close'].iloc[i-1] >= resistance.iloc[i-1]:
filtered_signals.append(i)
return {
'no_filter_count': len(no_filter_signals),
'filtered_count': len(filtered_signals),
'reduction_rate': f"{(1 - len(filtered_signals)/len(no_filter_signals))*100:.1f}%"
}
根据历史数据回测,使用趋势过滤系统后:
• 交易次数减少约40%-60%
• 胜率提升约15%-25%
• 最大回撤降低约30%-40%
• 总体风险调整后收益显著提升
这说明:少做,反而做得更好。
总结
今天的内容核心就是一个字:滤。
趋势跟踪策略的死穴不是"抓不住趋势",而是"被假突破反复打脸"。过滤掉假突破,你的策略才能真正跑起来。
六条核心要点:
1. 假突破是常态:大约40%-60%的突破是假的,不要每次突破都追
2. ADX是最实用的趋势过滤器:ADX>25做趋势,<20做震荡或观望
3. 时间过滤:突破后等1-2天确认,不追第一根突破K线
4. 幅度过滤:突破幅度要达到阈值(通常2%-3%)才算有效
5. 多周期过滤:大周期定方向,小周期找入场,顺大逆小
6. 少做反而做得更好:过滤后交易次数减少,但胜率和风险调整收益显著提升
最后送你一句话:
在趋势跟踪的世界里,耐心比聪明更重要。能忍住不追假突破的人,才能抓住真突破的大行情。
下一期,我们进入趋势跟踪的实战风控篇——如何设计渐进式止损、如何管理仓位、如何在趋势反转时及时离场。这才是趋势跟踪能不能长期活下去的关键。