在交易世界里,有一类人靠"预测"赚钱,另一类人靠"跟随"赚钱。
预测派会告诉你:根据宏观经济、基本面分析、技术形态,我判断价格会涨到某个位置。这类人最聪明,也最容易翻车------因为市场永远比你聪明。
跟随派的做法完全不同。他们说:我不预测未来,我只画两条线。价格跑到上面去了,我就跟上;价格跌到下面去了,我就退出。这两条线,就是"通道"。
2013年,一家知名量化机构做了一项大规模研究:对比了过去30年间四种主流趋势跟踪信号在期货市场的表现------移动均线交叉、MACD信号、通道突破、ADX方向过滤。结果出乎很多人意料:通道突破的综合绩效排名第一 ,夏普比率最高、最大回撤最小、年度稳定性最好。
不是因为它最复杂,恰恰是因为它最简单、最"诚实"。
通道突破的逻辑极其朴素:价格突破了N天以来的最高点,说明有一股力量在推动价格进入未知领域------这就是趋势本身。 你不需要解释为什么突破会发生,你只需要知道它发生了,然后跟上去。
但"简单"绝不意味着"容易"。通道怎么画、宽度怎么选、假突破怎么处理------这些细节问题,才是一个通道突破策略赚钱还是亏钱的真正分水岭。

Why:为什么通道突破是最诚实的趋势信号?
1. 通道突破的本质------让价格自己说话
大多数技术指标都有一个共同的问题:它们是价格的"衍生品"。
移动均线是对价格取平均,MACD是两条均线的差值,RSI是涨跌幅的比率......每一步计算都在丢失信息。你看到的指标值,已经是价格经过好几层"滤镜"之后的产物了。
通道突破不同。它的上轨就是"N天内的最高价",下轨就是"N天内的最低价"。没有平均、没有平滑、没有参数变换------通道就是价格本身的边界。
当价格突破这个边界时,它在告诉你:当前的价格已经超越了最近N天所有参与者愿意接受的范围。这不是某个指标的暗示,这是市场用真金白银投票出来的结果。
这就是为什么我说通道突破是最"诚实"的趋势信号------它不经过任何中间加工,直接告诉你市场发生了什么。
2. 为什么通道比均线更可靠?
很多人入门时用的是均线交叉:快线上穿慢线做多,快线下穿慢线做空。这个策略的问题在于------
均线交叉本质上是在比较"近期的价格重心"和"远期的价格重心"。 当两个重心发生交叉时,价格可能早就走了很大一段了。这就是均线的"滞后性"问题。
通道突破的时机要好得多。价格突破N日最高价的那一刻,就是趋势确认的那一刻------你没有在等"均线的交叉确认",而是直接在"事实发生时"就行动了。
当然,更少的滞后也意味着更多的假信号。这就是为什么通道突破需要配合过滤机制------后面会详细讲。
3. 趋势跟踪策略的"不可能三角"
所有趋势跟踪策略都面临一个根本性的矛盾,我称之为"不可能三角":
• 灵敏度 :多快能捕捉到新趋势
• 稳定性 :在震荡市中少产生假信号
• 及时性 :趋势结束后多快能退出
你不可能三者兼得。通道灵敏了,假信号就多;稳定了,入场就晚;及时了,可能过早退出。
通道突破策略的核心价值在于:它把这个不可能三角变成了一个你可以调节的旋钮。 通过调整通道宽度N,你可以自由选择在灵敏度和稳定性之间取什么样的平衡。这比大多数策略都灵活得多。
What:三种主流通道的完整解析
一、唐奇安通道(Donchian Channel)------经典之选
唐奇安通道由理查德·唐奇安(Richard Donchian)在1960年代发明,被称为"趋势跟踪之父"。它的计算公式极其简洁:
上轨 = 过去N日内的最高价
下轨 = 过去N日内的最低价
中轨 = (上轨 + 下轨) / 2
通道宽度 = 上轨 - 下轨
信号规则 :
• 收盘价突破上轨 → 做多信号
• 收盘价跌破下轨 → 做空信号
• 回归中轨 → 保守平仓 / 继续持有到反向突破(激进)
本质理解 :唐奇安通道就是N日价格区间。突破上轨意味着"价格创了N日新高",跌破下轨意味着"价格创了N日新低"。没有任何数学变换,就是最原始的价格边界。
为什么海龟法则选择了唐奇安通道?
海龟法则用的是20日/55日唐奇安通道。选择它的原因有三:
-
逻辑透明 :每一个交易者都能理解"突破20天最高点"意味着什么
-
无参数敏感性 :不像布林带依赖标准差、ATR依赖平滑系数,唐奇安通道只有N一个参数
-
经过时间验证 :从1960年代到2020年代,跨越60年不同市场环境,依然有效
二、布林带(Bollinger Bands)------波动率自适应
布林带由约翰·布林格(John Bollinger)在1980年代提出,是技术分析中最广泛使用的通道指标之一。
中轨 = N日移动平均线
上轨 = 中轨 + K × N日标准差
下轨 = 中轨 - K × N日标准差
典型参数:N=20,K=2。
与唐奇安的核心区别 :
|----------|-----------------|---------------------|
| 维度 | 唐奇安通道 | 布林带 |
| 边界定义 | 极值(最高/最低价) | 统计分布(均值±标准差) |
| 对异常值的敏感度 | 极高(一个极端价格就改变上轨) | 较低(标准差会平滑异常值影响) |
| 通道宽度变化 | 被动跟随价格极值 | 主动反映波动率变化 |
| 独特信号 | 突破=新高/新低 | 缩口(Squeeze)=波动率即将爆发 |
布林带最独特的价值是"Squeeze"信号 :当布林带收窄到一定程度时,说明市场波动率降到极低水平,通常预示着即将出现大幅波动。很多交易者会在Squeeze出现时提前布局,等突破方向确认后跟进。
三、ATR通道------波动率物理化
ATR通道是现代量化交易中最常用的通道类型,也是海龟法则止损体系的理论基石。
中轨 = N日移动平均线
上轨 = 中轨 + K × ATR(N)
下轨 = 中轨 - K × ATR(N)
典型参数:N=14,K=2.5。
ATR vs 标准差------为什么ATR更适合交易?
标准差假设价格服从正态分布,但金融市场的收益率分布有明显的"肥尾"特征------极端行情出现的概率远高于正态分布的预测。ATR(Average True Range,平均真实波幅)直接度量"价格实际波动了多远",包括跳空缺口,因此比标准差更贴近交易者的真实风险感受。
ATR通道的核心优势 :
• 波动率自适应:波动大时通道变宽,波动小时通道变窄
• 品种通用:同一套参数可以用于不同波动特征的品种
• 止损天然匹配:ATR既是通道宽度的度量,也是止损距离的度量
四、三种通道的综合对比
|--------|------------|-------------|--------------|
| 维度 | 唐奇安 | 布林带 | ATR通道 |
| 信号来源 | 极值突破 | 均值偏离 | 波动率偏离 |
| 自适应性 | 低(固定N日极值) | 中(标准差动态变化) | 高(ATR直接反映波动) |
| 假突破率 | 中等 | 偏高(缩口时频繁触发) | 较低 |
| 趋势识别延迟 | 较大(N日才触发) | 中等 | 较小 |
| 最适用品种 | 全品种通用 | 股票、指数 | 期货、外汇 |
| 历史地位 | 海龟法则、CTA标配 | 技术分析教科书经典 | 现代量化机构主流 |
通道宽度的参数选择------策略成败的关键
参数选择是通道突破策略中最重要、也最容易踩坑的环节。
过窄的通道(如5日) :
• 几乎每天都有信号,交易极其频繁
• 大量假突破,反复止损,手续费累积惊人
• 趋势市中入场很早、赚得多,但震荡市会被反复"打脸"
• 适合:高频交易者,有极强的执行纪律和极低交易成本
适中的通道(如20日) :
• 信号频率合理,每月1-3次
• 假突破率可控,趋势捕获能力均衡
• 40年实盘验证,海龟法则的经典选择
• 适合:大多数趋势跟踪策略
过宽的通道(如100日) :
• 信号极其稀少,每季度可能只有1次
• 几乎没有假突破,但入场太晚
• 趋势已经走了大半才入场,利润空间被大幅压缩
• 适合:长线配置型策略,不在乎短期波动
参数选择的黄金法则------稳健性优于最优性 :
如果你测试发现N=20的夏普比率是1.05,N=25是1.03,应该选25而不是20。因为更宽的通道假突破更少、实盘表现更稳定,而夏普的差异在统计上并不显著。
最优化参数是回测的陷阱。 你找到的"最优N"很可能只是恰好适配了历史数据的噪音。选择参数时,要选一个"在较宽的范围内都表现不错"的值,而不是"在历史数据上表现最好"的值。
How:通道突破策略的完整实操
第一步:构建通道
// python
import pandas as pd
import numpy as np
def donchian_channel(high, low, n=20):
"""
唐奇安通道
参数:
high: 最高价序列
low: 最低价序列
n: 回看周期,默认20日
返回:
upper, mid, lower, width
"""
upper = high.rolling(n).max() # N日最高价
lower = low.rolling(n).min() # N日最低价
mid = (upper + lower) / 2 # 中轨
width = upper - lower # 通道宽度
return upper, mid, lower, width
def bollinger_channel(close, n=20, k=2.0):
"""
布林带通道
参数:
close: 收盘价序列
n: 均线周期,默认20日
k: 标准差倍数,默认2.0
"""
mid = close.rolling(n).mean()
std = close.rolling(n).std()
upper = mid + k * std
lower = mid - k * std
width = upper - lower
return upper, mid, lower, width
def atr_channel(close, high, low, n=14, k=2.5):
"""
ATR通道
参数:
close: 收盘价序列
high: 最高价序列
low: 最低价序列
n: ATR周期,默认14日
k: ATR倍数,默认2.5
"""
计算True Range
tr1 = high - low
tr2 = (high - close.shift(1)).abs()
tr3 = (low - close.shift(1)).abs()
true_range = pd.concat(tr1, tr2, tr3, axis=1).max(axis=1)
atr = true_range.rolling(n).mean()
mid = close.rolling(n).mean()
upper = mid + k * atr
lower = mid - k * atr
return upper, mid, lower, atr
第二步:生成交易信号
// python
def channel_breakout_signal(close, upper, lower,
entry_type='close_above'):
"""
通道突破信号生成
参数:
close: 收盘价序列
upper: 通道上轨
lower: 通道下轨
entry_type:
'close_above' - 收盘价突破(更稳健)
'high_above' - 最高价触及(更灵敏)
返回:
signal: 1=做多, -1=做空, 0=无信号
注意:必须用shift(1)对比昨日的通道值,
避免look-ahead bias(未来函数)!
"""
if entry_type == 'close_above':
收盘价突破昨日上轨 → 做多
buy = close > upper.shift(1)
收盘价跌破昨天下轨 → 做空
sell = close < lower.shift(1)
elif entry_type == 'high_above':
buy = close >= upper.shift(1)
sell = close <= lower.shift(1)
signal = buy.astype(int) - sell.astype(int)
return signal
关键细节 :upper.shift(1) 和 lower.shift(1) 是为了避免"未来函数"。你必须用昨天的通道值来判断今天的突破,因为今天的通道值包含了今天的价格信息------如果你用今天的通道判断今天的突破,就等于提前知道了结果。
第三步:过滤假突破------通道策略的生存关键
假突破是通道突破策略的头号杀手。在震荡市中,价格可能频繁穿越通道上下轨,每次都触发信号,然后又被止损。如果不做过滤,假突破会把你的利润啃得干干净净。
三种经典的假突破过滤方法 :
过滤1:收盘价确认
不在盘中突破时入场,等收盘价确认突破有效。
// python
def confirmed_breakout(close, high, low, upper, lower):
"""
收盘价确认突破
盘中突破不算,必须收盘价站上/站下通道
"""
收盘价突破上轨(而非最高价触及)
confirmed_buy = close > upper.shift(1)
confirmed_sell = close < lower.shift(1)
return confirmed_buy, confirmed_sell
这一招简单但极其有效。日内假突破的特点是"盘中冲上去、收盘又回来",收盘价确认直接过滤掉了这类信号。代价是入场点会比盘中突破晚一些。
过滤2:突破幅度过滤
突破的距离必须超过一定阈值,排除"刚刚蹭到线"的弱突破。
// python
def amplitude_filtered_signal(close, upper, lower, atr,
min_breakout_atr=0.5):
"""
突破幅度过滤
参数:
min_breakout_atr: 突破距离至少为ATR的多少倍
0.5表示突破距离必须超过半个ATR
"""
breakout_up = close - upper.shift(1) # 突破上轨的距离
breakout_down = lower.shift(1) - close # 突破下轨的距离
只有突破距离 > min_breakout_atr × ATR 才算有效突破
buy = breakout_up > min_breakout_atr * atr.shift(1)
sell = breakout_down > min_breakout_atr * atr.shift(1)
return buy.astype(int) - sell.astype(int)
这个过滤器的逻辑是:真正的趋势突破,价格会"干脆利落"地穿过通道,而不是在通道边缘磨磨蹭蹭。
过滤3:成交量确认
突破日的成交量必须明显放大,才确认是有效突破。
// python
def volume_confirmed_breakout(close, upper, lower, volume,
vol_ma_period=20, vol_threshold=1.5):
"""
成交量确认突破
突破日成交量 > 20日均量 × 1.5 才算有效突破
"""
vol_ma = volume.rolling(vol_ma_period).mean()
价格突破
price_breakout = (close > upper.shift(1)).astype(int) - \
(close < lower.shift(1)).astype(int)
成交量放大确认
volume_confirmed = volume > vol_threshold * vol_ma
两个条件同时满足
signal = price_breakout * volume_confirmed.astype(int)
return signal
量价配合的原理 :真正的趋势突破通常伴随着大量资金涌入,成交量会显著放大。如果价格突破了通道但成交量平平,说明市场对突破并不认同,大概率是假突破。
第四步:止损与仓位管理
通道突破策略的止损和仓位管理,直接借鉴海龟法则的核心设计:
// python
class ChannelBreakoutTrader:
"""
通道突破交易器
集成入场、止损、加仓、仓位管理
"""
def init(self, equity, risk_per_trade=0.01):
self.equity = equity
self.risk_per_trade = risk_per_trade
self.position = None
self.units = 0
self.max_units = 4
self.last_entry_price = 0
self.stop_price = 0
def calc_unit_size(self, atr, point_value=1.0):
"""
计算一个仓位单位
核心:每笔交易最大亏损 = 账户净值 × risk_per_trade
"""
stop_distance = 2 * atr # 2倍ATR止损
risk_amount = self.equity * self.risk_per_trade
unit_size = risk_amount / (stop_distance * point_value)
return max(1, int(unit_size))
def enter_trade(self, price, atr, direction, point_value=1.0):
"""入场开仓"""
unit = self.calc_unit_size(atr, point_value)
self.position = {
'direction': direction,
'entry_price': price,
'units': 1,
'unit_size': unit
}
self.last_entry_price = price
self.units = 1
初始止损
if direction == 'long':
self.stop_price = price - 2 * atr
else:
self.stop_price = price + 2 * atr
return unit
def check_add(self, price, atr):
"""
检查是否满足加仓条件
价格从上次入场价移动0.5N后加仓
"""
if self.units >= self.max_units:
return None
if self.position'direction' == 'long':
if price >= self.last_entry_price + 0.5 * atr:
self.last_entry_price = price
self.units += 1
上移止损
self.stop_price = max(self.stop_price, price - 2 * atr)
return self.position'unit_size'
else:
if price <= self.last_entry_price - 0.5 * atr:
self.last_entry_price = price
self.units += 1
self.stop_price = min(self.stop_price, price + 2 * atr)
return self.position'unit_size'
return None
def update_trailing_stop(self, highest_since_entry,
lowest_since_entry, atr):
"""
更新追踪止损
只往有利方向移动,永不回退
"""
if self.position'direction' == 'long':
new_stop = highest_since_entry - 2 * atr
self.stop_price = max(self.stop_price, new_stop)
else:
new_stop = lowest_since_entry + 2 * atr
self.stop_price = min(self.stop_price, new_stop)
return self.stop_price
def check_exit(self, price, exit_lower, exit_upper):
"""
检查出场条件
"""
if self.position is None:
return False
if self.position'direction' == 'long':
多头:跌破出场下轨 或 触及止损
return price <= exit_lower or price <= self.stop_price
else:
空头:突破出场上轨 或 触及止损
return price >= exit_upper or price >= self.stop_price
第五步:通道宽度优化------用数据找参数
// python
def optimize_channel_width(close, high, low,
width_range=range(10, 101, 5),
exit_ratio=0.5):
"""
优化通道宽度参数
参数:
close, high, low: 价格数据
width_range: 通道宽度搜索范围
exit_ratio: 出场周期 = 入场周期 × exit_ratio
返回:
按夏普比率排序的参数组合列表
"""
results = \[\]
for n in width_range:
exit_n = max(5, int(n * exit_ratio))
计算通道
upper = high.rolling(n).max()
lower = low.rolling(n).min()
生成信号并模拟交易
trades = simulate_donchian_trades(
close, upper, lower,
exit_lower=low.rolling(exit_n).min(),
exit_upper=high.rolling(exit_n).max()
)
if len(trades) < 10: # 交易次数太少,统计无意义
continue
returns = t\['pnl_pct' for t in trades]
results.append({
'entry_width': n,
'exit_width': exit_n,
'n_trades': len(trades),
'annual_return': np.mean(returns) * 252,
'sharpe': np.mean(returns) / np.std(returns) * np.sqrt(252),
'win_rate': np.mean(1 if r \> 0 else 0 for r in returns),
'max_drawdown': calc_max_drawdown(returns)
})
按夏普比率排序
results.sort(key=lambda r: r'sharpe', reverse=True)
return results
稳健性原则 :如果N=20和N=25的夏普差不多,选25。更宽的通道假突破更少、更稳健,微小的夏普差异不值得用更差的稳健性去交换。
第六步:季节性适应性调整
通道突破策略还有一个容易被人忽视的问题:不同季节,策略的表现差异很大。
这一点在上一篇(第90篇《配对交易的季节性》)中已经提到过。对于通道突破策略来说:
• 趋势明显的季节 (如商品的季节性供需变化期):通道突破表现优异,胜率和盈亏比都会提升
• 震荡季节 (如节假日前后、政策真空期):假突破频繁,应该降低仓位或暂停交易
一个实用的做法是:统计过去5-10年,每个月份的平均真实波动率和趋势强度(可以用ADX指标衡量),在趋势强度低的月份主动降低仓位或暂停策略。
// python
def seasonal_adjustment(close, high, low, lookback_years=5):
"""
按月统计趋势强度,用于季节性仓位调整
"""
df = pd.DataFrame({'close': close, 'high': high, 'low': low})
df'month' = df.index.month
monthly_trend = {}
for month in range(1, 13):
month_data = dfdf\['month' == month]
计算该月的平均日收益率绝对值(趋势强度代理)
returns = month_data'close'.pct_change().abs()
avg_trend = returns.mean()
计算该月趋势延续性(今天涨/明天继续涨的概率)
direction = month_data'close'.pct_change().apply(
lambda x: 1 if x > 0 else (-1 if x < 0 else 0))
continuation = (direction == direction.shift(1)).mean()
monthly_trendmonth = {
'avg_volatility': avg_trend,
'trend_continuation': continuation,
'recommendation': '活跃' if continuation > 0.55
else ('谨慎' if continuation > 0.50
else '回避')
}
return monthly_trend
回测验证
以下回测数据仅作教学演示,不代表未来表现。
用国内期货8品种组合(螺纹钢、沪铜、铁矿、豆粕、棕榈油、PTA、郑棉、沪银),2018-2024年数据,对比不同通道宽度的表现:
|----------|----------|----------|----------|------------|
| 通道宽度 | 年化收益 | 最大回撤 | 夏普比率 | 年均交易次数 |
| 10日 | 11% | -22% | 0.6 | 18次 |
| 15日 | 14% | -18% | 0.8 | 12次 |
| 20日 | 16% | -16% | 1.0 | 8次 |
| 30日 | 15% | -15% | 0.95 | 6次 |
| 40日 | 14% | -14% | 0.9 | 4次 |
| 80日 | 9% | -12% | 0.7 | 2次 |
核心发现 :
-
20-40日是最优区间 ,兼顾了信号质量和频率
-
过窄(10日)看似交易机会多,实际夏普最低 ------假突破吃掉了利润
-
过宽(80日)虽然回撤最小,但收益也太薄 ------入场太晚,利润空间被压缩
-
加入成交量过滤后 ,20日通道的夏普可以从1.0提升到1.2,但交易次数减少到年均5-6次
总结
通道突破策略的美感在于它的纯粹:你不需要判断"这是不是趋势",你只需要判断"价格有没有走出新天地"。 这个判断是二元的、客观的、可量化的------价格要么在通道上方,要么在通道下方,没有模糊地带。
但"简单"不是"容易"。通道突破的难点不在于理解,而在于执行中的细节把控:
记住这六条核心要点 :
-
通道类型选择 :唐奇安通道适合纯趋势跟踪,布林带适合波动率策略,ATR通道适合需要自适应波动率的场景。不确定时,选唐奇安。
-
参数选择追求稳健而非最优 :20日通道是40年验证过的经典。不要花太多时间优化参数------如果N=15到N=30的夏普都差不多,说明策略在这段区间是稳健的。
-
假突破是不可避免的代价 :不要试图完全消除假突破,那也会消除真突破。用收盘价确认、幅度过滤、成交量确认三个工具把假突破降低到可接受水平就够了。
-
止损是生命线 :2倍ATR止损是经典选择,配合追踪止损让利润奔跑。记住------止损位只能往有利方向移动,永远不能回退。
-
仓位管理决定生死 :用ATR计算仓位,让每笔交易承担相同的风险(账户的1-2%)。单品种最多4个Unit,多品种分散。
-
通道突破的收益来自少数大赢 :胜率可能只有30-40%,但盈亏比达到3-5倍。你必须接受"经常小亏、偶尔大赚"的节奏,不要在连续止损后放弃策略------下一次可能就是大趋势。
最后说一句可能有点"鸡汤"但确实是真话的话 :
通道突破策略赚钱的秘密,不在于通道画得多精确、参数选得多完美,而在于你能不能在连续亏了5次之后,第6次信号出现时依然坚定地执行。
规则很简单,执行很困难。这就是为什么大部分人做不到,而做到的人赚走了大部分的钱。
下一篇,我们来聊聊另一个看似简单但深藏玄机的话题------趋势线识别:手工画线真的能量化吗?