唐奇安通道指标(Donchian Channel)
交易突破是一种流行的趋势跟踪策略。要衡量突破,我们可以使用最高价的最高点和最低价的最低点。唐奇安通道(Donchian Channel)就是一个能在图表上绘制这些价格的指标。接下来,让我们看看如何在TradingView中使用和编写这个指标。
使用唐奇安通道交易趋势跟踪突破
唐奇安通道是一种旨在识别趋势的价格跟踪指标,由理查德·唐奇安(Richard Donchian)开发。他在当时是一位成功的趋势跟踪交易者,也是机械交易的先驱。唐奇安还在1949年推出了行业内第一支管理基金,并以骄人的业绩持续交易至90多岁高龄。
唐奇安通道在图表上绘制两条价格带。上轨显示指定周期内的最高价,而下轨则显示最低价。默认情况下,这些最高价和最低价是基于过去20根K线计算的,但更短或更长的周期也同样常用。其默认周期为4个交易周,这也是为什么唐奇安通道有时被称为四周规则(the 4-week rule)的原因。
唐奇安通道背后的理念是:当价格突破具有心理重要性的最高价或最低价时,表明市场的观点已经发生了改变。换句话说,市场对价值的认知发生了重大转变。这使得突破行情得以持续的可能性变得更大。大多数趋势跟踪策略都建立在这个看似简单的概念之上。
唐奇安通道是一个功能多样的指标。它几乎适用于所有时间周期,从一分钟图一直到周线和月线图。该指标在具有趋势性的交易品种上表现最佳,幸运的是,这包括了大多数股票、期货、差价合约、外汇货币对以及加密货币。
如何使用唐奇安通道指标进行交易
唐奇安通道是一个纯粹的趋势跟踪指标。它只关注价格数据,而不会去猜测支撑和阻力区在哪里。这听起来可能有些初级,但实际上是它的一大优势。由于唐奇安通道紧随趋势,它几乎能保证我们始终站在重要趋势的正确一边。
要交易这些趋势,唐奇安通道可以产生两种信号:
- 当价格穿越上轨时,建立多头头寸。当价格穿越对面的轨道时,平仓。
- 当价格穿越下轨时,建立空头头寸。当价格穿越另一边的轨道时,回补仓位。
唐奇安通道的一个优秀特性是它会随着价格移动。当出现上升趋势时,新的高点会推动上轨不断走高。同时,上升趋势也伴随着更高的低点,这使得唐奇安通道的下轨也随之抬升。这样一来,趋势持续的时间越长,我们的多头出场点位就变得越有利。
唐奇安通道的宽度也为我们提供了一些信息。当市场处于剧烈波动的下跌趋势中时,通道的高度会增加。而当价格波动性减弱时,通道也会随之收窄。(当通道变得异常狭窄时,甚至预示着一次剧烈突破的可能性。)
不幸的是,交易唐奇安通道并非总是那么容易。在盘整行情中,该指标可能会产生大量假信号。并且当趋势持续时间不长时,价格可能没有足够的波动空间来实现盈利退出。在这些市场环境下,使用振荡器类指标会比趋势跟踪指标更好。
将唐奇安通道编写为TradingView Pine脚本
在了解了唐奇安通道的背景和信息之后,让我们把注意力转向编写一些代码。
以下是我们准备为唐奇安通道指标实现的特性:
- 我们将使用线图来显示通道。通过输入选项来设置其周期,以便能快速配置脚本。
- 我们将用彩色背景来高亮那些收盘价在通道之外的K线,并提供一个输入选项来启用或禁用此功能,以保持图表整洁。
- 我们将提供一个输入选项,用于指定K线收盘价必须超出通道多少个最小变动价位(ticks),才算作有效的突破信号。这可以方便地过滤掉假突破。
- 我们将在通道的上下轨之间绘制一条中线。一些交易者将其用作止损线或价格目标,它也有助于判断市场趋势。为了避免图表混乱,我们也会提供一个选项来关闭这条线。
- 为了能轻松识别价格突破,我们会高亮显示那些移动到通道之外的K线。如果不需要,可以通过输入选项关闭此功能。
- 当K线收盘价突破通道的上下轨时,我们会生成警报。这样即使用户没有盯着盘面,也能收到通知。
现在,就让我们看看如何在TradingView Pine脚本中实现这些功能吧!
用于编写TradingView指标的模板
为了将上述功能转化为TradingView代码,最简单的方法是使用一个模板。这样我们可以将整个工作分解成若干个小部分,并且有了一定的结构,就不必在空白的编辑器中从零开始。
这是我们将用于唐奇安通道指标的模板:
//@version=5
// 步骤一:脚本设置
// 步骤二:计算指标数值
// 步骤三:确定指标信号
// 步骤四:输出指标数据
// 步骤五:创建指标警报
如果你想和我一起编写唐奇安通道指标,请在TradingView的Pine编辑器中创建一个新的指标脚本,并粘贴以上模板。(如果你只想要完整的代码,可以直接滚动到本文末尾。)
为了让你对我们即将编写的代码有个直观的印象,下图是最终完成的唐奇安通道在图表上的样子:
现在,让我们开始动手编写唐奇安通道指标吧!
步骤一:设置指标参数与输入选项
首先,我们来定义指标的各项设置。为此,我们执行 indicator() 函数:
//@version=5
// 步骤一:脚本设置
indicator(title="Donchian Channel", overlay=true)
这里,我们使用 indicator() 函数的 title 参数来为我们的指标脚本命名。并通过 overlay 参数设为 true,让指标能够直接叠加显示在主图表的交易品种上。
接着,我们添加几个输入选项,以便能够方便地配置指标的参数。首先,我们为唐奇安通道的周期创建一个选项:
// 通道设置
dcLen = input.int(20, title="Channel Length", minval=2)
我们执行 input.int() 函数来创建一个整数输入选项。根据唐奇安通道的理论背景,我们将其默认值设为20根K线(20)。
我们还将其最小值设为2 (minval=2),以确保总有至少两根K线来计算最高价和最低价。
我们将 input.int() 函数的返回值存储在 dcLen 变量中,这样当我们在代码中使用该变量时,就能引用到用户在输入框中设定的当前值。
然后,我们创建两个影响唐奇安通道外观的选项:
// 外观设置
showMid = input.bool(false, title="Show Midpoint Line?")
fillDc = input.bool(false, title="Fill Donchian Channel?")
这两个选项都是布尔型(真/假)的输入选项(input.bool())。第一个名为“Show Midpoint Line?”(显示中线?),默认被禁用(false)。稍后我们会编写代码,当启用此选项时,指标将在唐奇安通道的上下轨之间显示一条中线。
另一个设置名为“Fill Donchian Channel?”(填充唐奇安通道?)。顾名思义,当启用此选项时,脚本会对唐奇安通道的区域进行颜色填充。
接下来是另外两个设置:
// 信号设置
brkOutFilter = input.int(0, title="Breakout Filter (Ticks)", minval=0) * syminfo.mintick
showBreakouts = input.bool(true, title="Highlight Breakouts?")
第一个选项,“Breakout Filter (Ticks)”(突破过滤器(跳动点)),是一个整数输入选项(input.int())。它定义了一根K线必须超出唐奇安通道多少个最小变动价位(ticks),我们才将其视为一个交易信号。
该输入的默认值为零,这使得指标在价格一收盘到通道外就立即生成信号。当我们将此值设得更高时,唐奇安通道能过滤掉更多噪音(但信号的产生也会相应延迟)。
我们还将这个输入值乘以 syminfo.mintick 变量。该变量返回当前图表交易品种的最小价格变动单位(即一个“跳动点”的大小)。通过相乘,我们将输入选项的值转换为了一个实际的价格位移量。
另一个输入,“Highlight Breakouts?”(高亮显示突破?),是一个布尔型输入选项(input.bool())。当我们勾选此复选框时,指标会为那些穿越了唐奇安通道的K线添加背景色。
步骤二:计算指标数值
接下来,我们编写代码来计算唐奇安通道的值:
// 步骤二:计算指标数值
hiHighs = ta.highest(high, dcLen)[1]
loLows = ta.lowest(low, dcLen)[1]
midPoint = (hiHighs + loLows) / 2
我们首先使用TradingView的 ta.highest() 函数来获取最高价的最高点。我们在 high 数据上运行该函数,周期设为 dcLen,即我们之前定义的输入变量,其默认值为20。
我们使用 ta.lowest() 函数来获取近期最低价的最低点。该函数使用 low 数据,周期同样为 dcLen。
请注意,我们在这两个函数调用后面都加上了历史引用运算符 [1]。这样我们获取的是之前K线的最高价和最低价,不包含当前K线。如果我们包含了当前K线的数据,那么当前K线就永远不可能收盘于唐奇安通道之外。
我们还计算了中点值 midPoint,即最高价的最高点与最低价的最低点的平均值。
步骤三:确定指标的买卖交易信号
在第三步中,我们编写唐奇安通道指标可以触发的信号。基本上有两种:当K线收盘于上轨之上时,产生买入信号;当K线收盘于下轨之下时,则为卖出信号。
下面是如何将其转化为TradingView代码:
// 步骤三:确定指标信号
// 判断价格是否上穿/下穿了唐奇安通道
upBrkOut = barstate.isconfirmed and
ta.crossover(close, hiHighs + brkOutFilter)
downBrkOut = barstate.isconfirmed and
ta.crossunder(close, loLows - brkOutFilter)
upBrkOut(向上突破)变量的布尔值由 and 运算符连接的两个表达式决定。第一个是 barstate.isconfirmed。当脚本在K线收盘后进行计算时,该变量返回 true;而在K线内的计算过程中,它返回 false。
我们检查该变量的原因是:当价格在盘中暂时移动到通道之外时,我们不希望立即生成买卖信号,因为这很可能是噪音或其他随机波动。但当K线确认收盘在通道之外时,我们才希望将其视为一个有效信号。
为了判断K线是否确实收盘在通道之外,我们使用了TradingView的 ta.crossover() 函数。我们将其参数设为K线的收盘价(close)和20周期最高价(hiHighs)加上我们输入选项所设定的跳动点过滤器(brkOutFilter)。这使得 ta.crossover() 在K线收盘价上穿通道时返回 true,否则返回 false。
接着,我们创建了 downBrkOut 变量。它的值取决于价格是否跌破了20周期最低价(同样包含了“突破过滤器”的设置)。我们使用TradingView的 ta.crossunder() 函数来衡量这一点。
我们同样检查这个价格信号是否发生在K线收盘之时(barstate.isconfirmed)。当这两个条件都满足时,downBrkOut 的值为 true(否则为 false)。
步骤四:绘制或输出指标的数据与信号
在下一步中,我们将在图表上显示唐奇安通道。首先,我们绘制通道的上下轨:
// 步骤四:输出指标数据
// 绘制唐奇安通道
ub = plot(hiHighs, color=color.green, title="DoCh UB")
lb = plot(loLows, color=color.red, title="DoCh LB")
我们在这里两次调用 plot() 函数。第一次调用以绿色(color.green)绘制了20周期的最高价(hiHighs)线。另一个 plot() 语句则以红色(color.red)显示20周期的最低价(loLows)线。
两个绘图都是常规的线图。我们将每个绘图对象分别存储在一个变量中。稍后,我们会使用 ub 和 lb 这两个变量来为它们之间的背景区域上色。
接下来,我们就来实现这个背景填充功能:
// 填充唐奇安通道的背景
fill(plot1=ub, plot2=lb, color=fillDc ? color.new(#4169e1, 95) :
color.new(color.white, 100))
我们调用 fill() 函数来为唐奇安通道的背景上色。为了实现这一点,我们将其 plot1 参数设为 ub(存储了最高价绘图的变量),plot2 参数则设为 lb(存储了最低价绘图的变量)。
我们使用的另一个 fill() 参数是 color。我们通过TradingView的条件运算符(?:)来为其赋予一个条件性的颜色。逻辑如下:当我们的 fillDc 输入变量为 true 时,我们执行 color.new() 函数来获得一个带有95%透明度的宝蓝色(#4169e1)。
如果该输入变量为 false,我们再次执行 color.new() 函数,但这次我们将白色(color.white)设置为100%的透明度。后者看起来有点奇怪,因为它创建了一个我们无法看见的颜色。
这么做的原因如下:fillDc 输入变量对应于“Fill Donchian Channel?”(填充唐奇安通道?)的输入选项。当我们禁用该选项时,脚本不应该为上下轨之间的区域上色。然而,问题在于我们无法根据条件来执行或取消 fill() 函数。
因此,我们采用了一种变通方法:让 fill() 始终为通道区域上色,但当该输入选项被禁用时,我们就将背景色设为完全透明。这样一来,我们至少在视觉上看不到它了。
我们让脚本绘制的另一个元素是唐奇安通道的中线:
// 如果启用,则显示中线
plot(showMid ? midPoint : na, color=color.orange, title="DoCh Mid")
这里,plot() 函数负责将 midPoint 变量以橙色(color.orange)的常规线图形式显示在图表上。但我们并不会一直绘制这条线。
相反,条件运算符(?:)会评估 showMid 输入变量是否为 true。如果是,我们就绘制最高价与最低价的平均值。否则,我们使用 na 值来禁用该绘图。通过这种方式,showMid 变量——它存储了“Show Midpoint Line?”输入选项的值——决定了这条线是否被绘制。
我们让指标输出的最后一项内容,是在发生通道突破时为背景着色:
// 用彩色背景高亮显示突破
highlightColour = not showBreakouts ? na :
upBrkOut ? color.new(color.green, 80) :
downBrkOut ? color.new(color.red, 80) :
na
bgcolor(highlightColour)
首先,我们创建了 highlightColour 变量。它会得到三个可能的值之一:na(用于禁用背景色)、绿色(用于高亮买入信号)和红色(用于高亮卖出信号)。
具体得到哪个值,取决于我们使用TradingView的条件运算符(?:)所评估的条件。首先,我们检查 showBreakouts 输入变量是否不为 true。如果该变量确实为 false,我们就知道“Highlight Breakouts?”输入选项被禁用了,因此我们使用 na 值来稍后禁用背景色。
下一个条件运算符检查 upBrkOut 是否为 true,这种情况发生在K线收盘于唐奇安通道之上时。为此,我们将绿色(color.green)存储在 highlightColour 变量中,并使用 color.new() 函数为其设置80%的透明度。
否则,再下一个运算符会检查 downBrkOut 是否为 true,这种情况发生在价格K线收盘于唐奇安通道之下时。我们为此场景使用红色(color.red)。(最后的 na 值则用于处理既没有向上突破也没有向下突破的情况。)
然后,我们调用 bgcolor() 函数,并将其第一个参数设为我们刚刚计算出的 highlightColour 变量。这样,我们决定的颜色就会显示在图表背景上了。
步骤五:为TradingView指标添加警报条件
接下来,我们为指标编写警报条件。这样,即使我们没有盯着图表,也能在唐奇安通道发生突破时收到通知。
下面是我们如何创建这些警报:
// 步骤五:创建指标警报
alertcondition(condition=upBrkOut,
title="Long Entry",
message="Price closed above Donchian Channel")
alertcondition(condition=downBrkOut,
title="Short Entry",
message="Price closed below Donchian Channel")
为了在价格突破唐奇安通道上轨时创建警报,我们调用 alertcondition() 函数,并将其 condition 参数设为我们之前创建的 upBrkOut 变量。我们使用函数的 title 参数来命名这个警报(“多头入场”),并通过 message 参数提供一条标准的警报信息(“价格收盘于唐奇安通道之上”)。
第二行 alertcondition() 的代码非常相似。这里,我们将警报的条件设为 downBrkOut,即当价格突破唐奇安通道下轨时值为 true 的变量。并通过 title 和 message 参数进一步配置此警报条件。
注意
请注意,在我们编写了 alertcondition() 函数后,警报并不会自动触发。我们必须在“创建警报”窗口中手动启用并配置该警报,它才能真正生效。
在图表上绘制唐奇安通道指标
现在我们已经完成了唐奇安通道指标的编码,让我们来看看它在图表上的实际表现。该脚本很擅长捕捉长期趋势,例如下面比特币的这次大涨行情:
唐奇安通道在九月初发出了第一个买入信号。从那时起,价格一路飙升。尽管在趋势结束时价格波动加剧,但唐奇安通道让我们得以持仓到最后,从而充分获利。
在唐奇安通道的代码中,我们制作了两个可选设置:中线和背景填充。下图展示了当我们启用这两个选项时的图表外观:
在这里,当价格跌破橙色的中线时,欧元/美元首先显现出弱势。随后,当价格穿越20周期的最低价时,唐奇安通道产生了一个明确的卖出信号。自那时起,看跌情绪将价格从1.2200打压至1.1510。
当然,唐奇安通道也有其缺点。当市场没有趋势时,该指标的表现确实不佳。下面的欧元/日元图表就是一个例子。在几个月的时间里,该指标产生了数个买入信号,但没有一个最终带来盈利的交易:
改进唐奇安通道的方法
虽然唐奇安通道在趋势市场中表现出色,但在盘整行情中却容易产生假信号。以下是一些能提升该指标表现的方法:
- 使用移动平均线过滤信号。当价格位于均线上方时,只采纳买入信号;当价格位于均线下方时,只采纳卖出信号。
- 回调买入/反弹卖出。在稳定的上升趋势中,向唐奇安通道下轨的小幅回调可能是一个买入机会。同样,在下降趋势中,向通道上轨的短暂反弹也可以被视为空头入场机会。
- 使用双通道过滤。让周期更长的通道来产生入场信号(做多或做空),而周期更短的通道则用于触发平仓。这样一来,我们既可以延长通道的周期以捕捉大趋势,又不必因为周期变长而延迟平仓时机。
- 使用动量指标过滤。有效的唐奇安通道突破通常伴随着强劲的价格动量。如果突破时动能不足,那么很可能是假突破。我们可以使用相对强弱指数 (RSI)或动量指标来衡量动能。
- 分批建仓。当唐奇安通道产生信号时,不要一次性全仓买入,而是分批建仓。这样,如果信号最终被证明是错误的,损失也是有限的。而如果趋势确实启动了,我们也有足够的时间来逐步建立头寸。
- 在盘整期反向交易。当市场处于横盘整理时,不要交易那些发生在通道外的小幅突破。相反,应该使用振荡器(如随机指标 Stochastics或RSI)来反向交易这些波动,并将通道的另一侧轨道作为价格目标。
完整代码:适用于TradingView的唐奇安通道指标
为方便参考,下方提供了唐奇安通道指标的完整代码。更多细节和信息请参阅上文的讨论。
//@version=5
// 步骤一:脚本设置
indicator(title="Donchian Channel", overlay=true)
// 通道设置
dcLen = input.int(20, title="Channel Length", minval=2)
// 外观设置
showMid = input.bool(false, title="Show Midpoint Line?")
fillDc = input.bool(false, title="Fill Donchian Channel?")
// 信号设置
brkOutFilter = input.int(0, title="Breakout Filter (Ticks)", minval=0) * syminfo.mintick
showBreakouts = input.bool(true, title="Highlight Breakouts?")
// 步骤二:计算指标数值
hiHighs = ta.highest(high, dcLen)[1]
loLows = ta.lowest(low, dcLen)[1]
midPoint = (hiHighs + loLows) / 2
// 步骤三:确定指标信号
// 判断价格是否上穿/下穿了唐奇安通道
upBrkOut = barstate.isconfirmed and
ta.crossover(close, hiHighs + brkOutFilter)
downBrkOut = barstate.isconfirmed and
ta.crossunder(close, loLows - brkOutFilter)
// 步骤四:输出指标数据
// 绘制唐奇安通道
ub = plot(hiHighs, color=color.green, title="DoCh UB")
lb = plot(loLows, color=color.red, title="DoCh LB")
// 填充唐奇安通道的背景
fill(plot1=ub, plot2=lb, color=fillDc ? color.new(#4169e1, 95) :
color.new(color.white, 100))
// 如果启用,则显示中线
plot(showMid ? midPoint : na, color=color.orange, title="DoCh Mid")
// 用彩色背景高亮显示突破
highlightColour = not showBreakouts ? na :
upBrkOut ? color.new(color.green, 80) :
downBrkOut ? color.new(color.red, 80) :
na
bgcolor(highlightColour)
// 步骤五:创建指标警报
alertcondition(condition=upBrkOut,
title="Long Entry",
message="Price closed above Donchian Channel")
alertcondition(condition=downBrkOut,
title="Short Entry",
message="Price closed below Donchian Channel")






