解析 supertrend 超级趋势策略
超级趋势代码
//@version=4
study("Supertrend", overlay = true, format=format.price, precision=2, resolution="")
Periods = input(title="ATR Period", type=input.integer, defval=10)
src = input(hl2, title="Source")
Multiplier = input(title="ATR Multiplier", type=input.float, step=0.1, defval=3.0)
changeATR= input(title="Change ATR Calculation Method ?", type=input.bool, defval=true)
showsignals = input(title="Show Buy/Sell Signals ?", type=input.bool, defval=true)
highlighting = input(title="Highlighter On/Off ?", type=input.bool, defval=true)
atr2 = sma(tr, Periods)
atr= changeATR ? atr(Periods) : atr2
up=src-(Multiplier*atr)
up1 = nz(up[1],up)
up := close[1] > up1 ? max(up,up1) : up
dn=src+(Multiplier*atr)
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
upPlot = plot(trend == 1 ? up : na, title="Up Trend", style=plot.style_linebr, linewidth=2, color=color.green)
buySignal = trend == 1 and trend[1] == -1
plotshape(buySignal ? up : na, title="UpTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.green, transp=0)
plotshape(buySignal and showsignals ? up : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.green, textcolor=color.white, transp=0)
dnPlot = plot(trend == 1 ? na : dn, title="Down Trend", style=plot.style_linebr, linewidth=2, color=color.red)
sellSignal = trend == -1 and trend[1] == 1
plotshape(sellSignal ? dn : na, title="DownTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.red, transp=0)
plotshape(sellSignal and showsignals ? dn : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.red, textcolor=color.white, transp=0)
mPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0)
longFillColor = highlighting ? (trend == 1 ? color.green : color.white) : color.white
shortFillColor = highlighting ? (trend == -1 ? color.red : color.white) : color.white
fill(mPlot, upPlot, title="UpTrend Highligter", color=longFillColor)
fill(mPlot, dnPlot, title="DownTrend Highligter", color=shortFillColor)
alertcondition(buySignal, title="SuperTrend Buy", message="SuperTrend Buy!")
alertcondition(sellSignal, title="SuperTrend Sell", message="SuperTrend Sell!")
changeCond = trend != trend[1]
alertcondition(changeCond, title="SuperTrend Direction Change", message="SuperTrend has changed direction!")
解析
好的,没问题。为了真正吃透这个 Pine 脚本,我们将采用“代码逐行解析 + 数据实例演算”的方式。这能让你清晰地看到每一步计算是如何进行的,以及数据是如何在逻辑之间流动的。
我们将使用默认参数:ATR Period = 10,ATR Multiplier = 3.0。
Pine 脚本逐行深度解析
第一部分:初始化与参数定义
//@version=4
study("Supertrend", overlay = true, format=format.price, precision=2, resolution="")
//@version=4: 声明此脚本使用 Pine Script 第 4 版语法。study(...): 定义这是一个指标(Indicator)脚本,而不是一个策略(Strategy)。overlay = true: 指标将直接叠加在主图表(K线图)上,而不是在下方的独立窗口中。format=format.price: 数值格式化为价格。precision=2: 显示两位小数。
Periods = input(title="ATR Period", type=input.integer, defval=10)
src = input(hl2, title="Source")
Multiplier = input(title="ATR Multiplier", type=input.float, step=0.1, defval=3.0)
changeATR= input(title="Change ATR Calculation Method ?", type=input.bool, defval=true)
showsignals = input(title="Show Buy/Sell Signals ?", type=input.bool, defval=true)
highlighting = input(title="Highlighter On/Off ?", type=input.bool, defval=true)
- 这部分定义了用户可以在指标设置中调整的参数。
Periods: ATR 计算周期,默认10。src: 计算指标所用的数据源,默认为hl2((High + Low) / 2)。Multiplier: ATR 乘数,默认3.0。changeATR: 是否切换ATR计算方法,默认为true(使用atr()函数)。showsignals,highlighting: 控制图表上视觉元素(买卖标签、背景高亮)的开关。
第二部分:核心计算逻辑 (重点)
这是整个脚本的灵魂所在。我们将用一个假设的数据表格来演算这个过程。
假设数据 (K线索引从1开始):
| Index | High | Low | Close | hl2 | tr | atr(10) |
|---|---|---|---|---|---|---|
| ... | ... | ... | ... | ... | ... | ... |
| 9 | 108 | 106 | 107 | 107.0 | 2.0 | 2.5 |
| 10 | 110 | 108 | 109 | 109.0 | 3.0 | 2.55 |
| 11 | 112 | 109 | 111 | 110.5 | 3.0 | 2.6 |
| 12 | 115 | 110 | 114 | 112.5 | 4.0 | 2.74 |
1. ATR 计算
atr2 = sma(tr, Periods)
atr = changeATR ? atr(Periods) : atr2
tr(True Range) 是内置变量,代表真实波幅。atr2: 使用简单移动平均(SMA)计算ATR,作为备选。atr: 最终使用的ATR值。默认changeATR为true,所以使用atr(Periods)函数,它内部使用RMA(一种加权移动平均)计算,这是TradingView指标的标准。- 演算 (Index 11): 假设
atr(10)在第11根K线上的值为2.6。
2. 初始轨道线计算
up = src - (Multiplier * atr)
dn = src + (Multiplier * atr)
up: 上涨趋势的支撑线 (Up Trend Line)。它的计算公式是中间价 - 乘数 * ATR。dn: 下跌趋势的阻力线 (Down Trend Line)。它的计算公式是中间价 + 乘数 * ATR。- 演算 (Index 11):
up= 110.5 - (3.0 * 2.6) = 110.5 - 7.8 = 102.7dn= 110.5 + (3.0 * 2.6) = 110.5 + 7.8 = 118.3
3. 最终轨道线计算 (最关键的迭代逻辑)
up1 = nz(up[1], up)
up := close[1] > up1 ? max(up, up1) : up
up1 = nz(up[1], up): 获取前一根K线最终计算出的up值。nz()函数处理空值,确保在第一根K线时不出错。up[1]表示引用前一根K线的up值。up := ...: 这是重新赋值操作符,用于更新up变量的值。- 核心逻辑: 如果前一根K线的收盘价
close[1]大于 前一根K线的最终支撑线up1,意味着上涨趋势在延续。此时,当前K线的最终支撑线up应该取max(当前计算的初始up, 前一根的最终up1)。这确保了支撑线只会抬高或保持不变(阶梯式上升)。否则,如果趋势可能反转,就直接采用当前计算的初始up值。
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? min(dn, dn1) : dn
- 逻辑与
up完全对称。如果前一根K线收盘价低于前一根的最终阻力线dn1,则下跌趋势延续,当前最终阻力线dn取min(当前初始dn, 前一最终dn1),确保阻力线只会降低或保持不变。
4. 趋势方向判断
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
trend = 1: 初始化trend变量,默认值为1(上涨)。trend := nz(trend[1], trend): 将当前trend的值先设定为与前一根K线相同,实现趋势的延续。- 核心逻辑: 在延续的基础上,检查是否反转。
- 如果前一趋势是下跌 (
trend == -1) 并且 当前收盘价close向上突破了前一根K线的最终阻力线dn1,则趋势反转为上涨 (1)。 - 如果前一趋势是上涨 (
trend == 1) 并且 当前收盘价close向下跌破了前一根K线的最终支撑线up1,则趋势反转为下跌 (-1)。 - 否则,趋势保持不变。
- 如果前一趋势是下跌 (
数据演算完整示例 (从 Index 10 到 11)
假设在 Index 10 时,我们已计算出:
最终 up(up1) = 101.5最终 dn(dn1) = 119.0最终 trend= 1 (上涨趋势)收盘价(close) = 109
现在,我们计算 Index 11 的值:
-
计算初始轨道 (已完成):
初始 up= 102.7初始 dn= 118.3
-
计算最终轨道
up和dn:- 计算
up:- 判断条件:
close[1] > up1? ->109 > 101.5? -> True。 - 上涨趋势延续,
up=max(初始up, up1)=max(102.7, 101.5)= 102.7。
- 判断条件:
- 计算
dn:- 判断条件:
close[1] < dn1? ->109 < 119.0? -> True。 - (虽然趋势是上涨,但这个计算仍会进行)
dn=min(初始dn, dn1)=min(118.3, 119.0)= 118.3。
- 判断条件:
- 计算
-
计算最终趋势
trend:trend先继承前一根的值,所以trend暂时为1。- 检查反转条件:
trend == 1 and close < up1? ->1 == 1 and 111 < 101.5? -> False。 (当前收盘价111没有跌破前一支撑线101.5)
- 没有反转,所以
trend最终为 1。
Index 11 的最终结果:
最终 up= 102.7最终 dn= 118.3最终 trend= 1
第三部分:绘图与信号
这部分代码负责将计算结果可视化。
upPlot = plot(trend == 1 ? up : na, ...)
dnPlot = plot(trend == 1 ? na : dn, ...)
plot(): 绘图函数。trend == 1 ? up : na: 这是一个三元运算符。如果trend为1(上涨),则绘制up线(支撑线);否则,不绘制任何东西 (na)。dnPlot同理,只在trend为-1(下跌)时绘制dn线(阻力线)。
buySignal = trend == 1 and trend[1] == -1
sellSignal = trend == -1 and trend[1] == 1
buySignal: 定义了一个布尔变量。当趋势从下跌(trend[1] == -1)刚刚反转为上涨(trend == 1)时,buySignal为true。sellSignal: 同理,定义了卖出信号。
plotshape(buySignal ? up : na, title="Buy", ...)
plotshape(): 在图表上绘制形状(如标签、箭头等)。buySignal ? up : na: 如果buySignal为true,则在up线的位置绘制一个形状。- 后续的
plotshape只是绘制了不同样式的信号(一个圆圈,一个带文字的标签)。
fill(mPlot, upPlot, title="UpTrend Highligter", color=longFillColor)
fill(): 在两条线之间填充颜色。这里用于实现趋势背景高亮。longFillColor: 如果是上涨趋势,颜色为绿色;否则为透明。fill(mPlot, upPlot, ...): 在K线(mPlot,这里用ohlc4近似)和上涨趋势线upPlot之间填充绿色。
第四部分:警报条件
alertcondition(buySignal, title="SuperTrend Buy", message="SuperTrend Buy!")
alertcondition(): 定义了一个可以用于创建TradingView警报的条件。- 当
buySignal变为true时,用户可以设置一个基于此条件的警报,在图表上收到"SuperTrend Buy!"的通知。
总结
这个脚本的核心在于其迭代计算的本质。当前K线的最终结果(轨道线和趋势)并不仅仅取决于当前K线的数据,而是严重依赖于前一根K线计算完成后的最终结果。正是这种“记忆”效应,创造了SuperTrend指标平滑且阶梯式移动的独特视觉效果,使其成为一个优秀的趋势跟踪工具。
为者常成,行者常至
自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)