解析 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 = 10ATR 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值。默认 changeATRtrue,所以使用 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.7
    • dn = 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线最终计算出的 upnz() 函数处理空值,确保在第一根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,则下跌趋势延续,当前最终阻力线 dnmin(当前初始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 的值:

  1. 计算初始轨道 (已完成):

    • 初始 up = 102.7
    • 初始 dn = 118.3
  2. 计算最终轨道 updn:

    • 计算 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
  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)时,buySignaltrue
  • sellSignal: 同理,定义了卖出信号。
plotshape(buySignal ? up : na, title="Buy", ...)
  • plotshape(): 在图表上绘制形状(如标签、箭头等)。
  • buySignal ? up : na: 如果 buySignaltrue,则在 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指标平滑且阶梯式移动的独特视觉效果,使其成为一个优秀的趋势跟踪工具。

为者常成,行者常至