保持敬畏之心
交易是一场持久战

Pine Script(152):叠加背景色、交易时段背景与热力图效果

#Pine Script入门教学

叠加多层背景色

在TradingView中,我们可以为图表背景着色,并利用该功能有条件地或偏移地应用背景色。但这些背景色也可以相互叠加。那么,我们该如何实现呢?

以编程方式重复为TradingView背景着色

当我们在TradingView中通过编程方式使用颜色时,我们可以从标准的基础颜色和十六进制颜色值中进行选择。在脚本中使用了颜色后,我们还可以手动更改该颜色。

bgcolor() 是一个与颜色相关的函数,它可以从上到下为图表背景着色。该函数影响的图表区域取决于脚本的显示位置:如果脚本叠加在主图表的交易品种上,那么 bgcolor() 会为价格K线的背景着色;当脚本在自己的子图中绘制时,该函数则为该子图区域的背景着色。

通常,bgcolor() 在一个脚本中只使用一次,这已经允许实现更复杂的功能,比如有条件地为TradingView背景着色。但我们其实可以根据需要多次在脚本中添加此函数。多次使用 bgcolor() 可以使我们的代码更易于阅读,更有趣的是,它允许我们将着色的背景相互叠加。让我们更仔细地看看这是如何工作的。

组合着色背景:函数调用顺序的影响

当我们在一个脚本中多次使用 bgcolor() 时,它们的调用顺序很重要:第一个 bgcolor() 函数调用创建了最底层的背景,后续的背景色会依次叠加在它上面。换句话说,最后一个 bgcolor() 函数调用的背景色会显示在最顶层。

下面的示例很好地说明了这一点:

//@version=5
indicator(title="Overlaying coloured backgrounds", overlay=false)

bgcolor(color.new(color.blue, 25))
bgcolor(close > open ? color.new(color.lime, 25) : na)

我们首先使用 indicator() 设置指标的属性。通过将其 overlay 参数设为 false,脚本会显示在一个单独的子图中。

第一个 bgcolor() 语句将图表背景设为带有25%透明度的蓝色(color.blue),我们通过 color.new() 函数来实现透明效果。

第二个 bgcolor() 函数调用则有条件地设置背景色。为此,我们使用了条件(三元)运算符(?:)。该运算符会评估一个条件,如果条件为 true,则返回运算符的第二个值;当条件为 false 时,则返回其第三个值。

我们在这里检查的条件是K线的收盘价(close)是否大于开盘价(open)。如果是,条件运算符返回一个带有25%透明度的酸橙绿(color.lime),我们随即使用该颜色通过 bgcolor() 函数来改变图表背景。

当K线收盘下跌或不变时,条件运算符返回 na。这个内置变量代表一个非数字的值,它能使着色的背景变得不可见(就像关闭它一样)。这意味着我们只为收盘上涨的K线叠加一层酸橙绿的背景色,而其他价格K线的背景则保持不变(即底层的蓝色)。

当将此示例脚本添加到图表时,它看起来是这样的:

在这里,主背景色是蓝色,因为每个收盘下跌或持平的K线都显示了这个颜色的背景。这是由于这些K线没有被第二个 bgcolor() 语句着色,因此它们仍然保留着第一个 bgcolor() 函数调用所设置的背景色。

当我们交换这两个 bgcolor() 函数调用的位置时,就可以更清楚地看到 bgcolor() 语句顺序所带来的影响。代码变为:

//@version=5
indicator(title="Overlaying coloured backgrounds", overlay=false)

bgcolor(close > open ? color.new(color.lime, 25) : na)
bgcolor(color.new(color.blue, 25))

这里唯一的改变是我们现在首先将图表背景有条件地设为酸橙绿或透明(na),然后第二个 bgcolor() 语句再将背景设为蓝色。这会将我们的欧元/美元图表变为:

现在所有K线都有一个蓝色的背景。然而,一些价格K线带有一种蓝绿色的色调,这是因为绿色的背景透过了蓝色的背景。当我们关闭背景色的透明度时,这种蓝色背景覆盖在酸橙绿背景之上的效果会更加明显:

//@version=5
indicator(title="Overlaying coloured backgrounds", overlay=false)

bgcolor(close > open ? color.new(color.lime, 0) : na)
bgcolor(color.new(color.blue, 0))

这里,最后一个语句仍然无条件地将背景涂成蓝色,但现在 color.new() 函数为这个颜色设置了0%的透明度,使其成为一个完全不透明的背景。这会将图表变为:

现在,由第一个 bgcolor() 语句创建的绿色背景已经完全看不见了,因为它被第二个 bgcolor() 函数调用所创建的蓝色背景完全覆盖了。现在,让我们看一个在TradingView中叠加背景的更实用的例子。

通过叠加TradingView背景高亮显示交易信号

接下来的示例指标会为背景着色两次。第一次是基于移动平均线,第二次则是基于相对强弱指数(RSI)。

其理念是,第一层着色的背景用于显示交易品种的总体趋势,而第二层叠加的背景则用于显示实际的买卖信号。我们稍后会看该指标及其输入选项的样子,但首先是代码:

//@version=5
indicator(title="Colouring the background repeatedly", overlay=false)

// 输入选项
srcData    = input.source(close, title="Source Data")
rsiLength  = input.int(14, title="RSI Length")
overbought = input.int(70, title="RSI Overbought")
oversold   = input.int(30, title="RSI Oversold")
smaLength  = input.int(5, title="SMA Length")

// 计算数值
rsiValue = ta.rsi(srcData, rsiLength)
smaValue = ta.sma(srcData, smaLength)

// 显示数值
plot(rsiValue, color=color.purple, linewidth=2)
hline(overbought, color=color.black)
hline(oversold, color=color.black)

// 基于SMA为背景着色
backgroundColour = if close > smaValue
    color.new(color.green, 85)
else
    color.new(color.red, 85)
bgcolor(backgroundColour)

// 当RSI信号发生时为背景着色
buySignal = rsiValue > oversold and rsiValue[1] <= oversold and close > smaValue
sellSignal = rsiValue < overbought and rsiValue[1] >= overbought and close < smaValue
bgcolor(buySignal ? color.new(color.lime, 50) : na)
bgcolor(sellSignal ? color.new(color.red, 50) : na)

我们以 indicator() 函数开始,这是每个指标代码都必需的。通过将其 overlay 参数设为 false,指标会在主图表下方的一个单独图表面板中绘制。

然后,我们向脚本添加几个输入选项:

// 输入选项
srcData    = input.source(close, title="Source Data")
rsiLength  = input.int(14, title="RSI Length")
overbought = input.int(70, title="RSI Overbought")
oversold   = input.int(30, title="RSI Oversold")
smaLength  = input.int(5, title="SMA Length")

我们使用专门的Pine Script函数创建这五个输入项。这些函数不仅在脚本的设置中创建输入,还会返回输入的当前值。这里我们将每个值存入一个变量,以便稍后在脚本中使用。

第一个是 input.source() 创建的数据源输入选项,它会在脚本选项中创建一个下拉菜单,允许我们从图表上的交易品种中选择不同的价格数据。其默认值为收盘价(close)。

另外四个输入都是通过 input.int() 创建的数值整数输入。我们分别将它们命名为“RSI Length”、“RSI Overbought”、“RSI Oversold”和“SMA Length”,并设置了相应的默认值。这些值分别存储在 rsiLengthoverboughtoversoldsmaLength 变量中。

接下来,我们计算RSI和SMA的值:

// 计算数值
rsiValue = ta.rsi(srcData, rsiLength)
smaValue = ta.sma(srcData, smaLength)

我们通过 ta.rsi() 函数计算振荡器的值,该函数需要一个数据序列和RSI周期作为参数。这里我们使用 srcDatarsiLength 输入变量。

然后我们使用 ta.sma() 来确定SMA,它同样需要一个数据序列和周期作为参数,我们使用 srcDatasmaLength。我们将计算出的均线值赋给 smaValue 变量。

现在,我们在图表上绘制一些数值:

// 显示数值
plot(rsiValue, color=color.purple, linewidth=2)
hline(overbought, color=color.black)
hline(oversold, color=color.black)

我们使用 plot() 来显示RSI值。默认情况下,该函数绘制一条线图,我们将其颜色设为紫色,并使其比标准尺寸稍粗。

然后,我们使用 hline() 函数在超买和超卖水平(由 overboughtoversold 输入变量定义)绘制两条黑色的水平线。这样,当我们调整输入选项时,这些线条的位置也会随之改变。

请注意,我们并没有绘制我们的SMA。这是因为它与RSI的价格刻度不同,如果绘制出来会扭曲指标子图的显示。不过,我们稍后会在确定买卖信号时使用这条移动平均线。但首先,我们应用第一层背景色:

// 基于SMA为背景着色
backgroundColour = if close > smaValue
    color.new(color.green, 85)
else
    color.new(color.red, 85)
bgcolor(backgroundColour)

我们首先通过一个 if/else 语句来确定背景颜色。if 条件在这里检查K线的收盘价(close)是否大于(>) SMA (smaValue)。

当价格K线确实收于该移动平均线上方时,if 条件返回一个由 color.new() 函数设置了85%透明度的绿色(color.green)。

否则,当价格不高于简单移动平均线时,else 代码块会返回一个由 color.new() 函数提供85%透明度的红色(color.red)。

返回的绿色或红色就是Pine Script存储在 backgroundColour 变量中的颜色。接下来,我们使用 bgcolor() 函数并传入该变量,这会为当前K线的背景着上绿色或红色。

在添加了第一层背景之后,每当有RSI信号发生时,我们就要再次为背景上色。但在此之前,我们需要先实现我们的买卖逻辑:

// 当RSI信号发生时为背景着色
buySignal = rsiValue > oversold and 
     rsiValue[1] <= oversold and
     close > smaValue

sellSignal = rsiValue < overbought and 
     rsiValue[1] >= overbought and
     close < smaValue

我们首先创建了两个变量,buySignalsellSignal。它们通过 and 逻辑运算符组合多个表达式来获得一个布尔(真/假)值,这意味着所有表达式都必须为 true,整个组合的结果才为 true

因此,buySignal 变量要为 true 必须满足三个条件。首先,RSI (rsiValue)需要大于(>) oversold 输入变量(默认值为30)。

其次,前一根K线的RSI值(rsiValue[1])需要小于或等于(<=)超卖水平。

通过这两个条件,我们判断RSI值是否在当前K线上穿了超卖区。最后一个条件要求K线收盘于SMA之上(close > smaValue)。当所有三个条件都在当前K线上满足时,我们的 buySignal 变量才为 true

我们以几乎相同的方式来确定 sellSignal 变量的值:现在要求RSI低于超买区(rsiValue < overbought),而前一根K线仍在超买区内(rsiValue[1] >= overbought),并且K线收盘于SMA之下(close < smaValue)。

现在我们已经确定了买卖信号,就可以使用这两个变量来有条件地为背景着色了:

bgcolor(buySignal ? color.new(color.lime, 50) : na)
bgcolor(sellSignal ? color.new(color.red, 50) : na)

我们首先为任何发生买入信号的K线背景着色。为此,我们使用条件运算符(?:)将 bgcolor() 函数的第一个参数设为酸橙绿(color.lime)或 na 值。该绿色通过 color.new() 函数被设为透明。

条件运算符(?:)具体选择哪个值,取决于 buySignal 变量。当该变量为 true 时,背景被涂成酸橙绿;如果为 falsebgcolor() 则使用 na 值,其效果是关闭背景着色。

我们用另一个 bgcolor() 语句结束这个例子。这次,我们根据 sellSignal 变量的值,使用条件运算符将颜色设为红色(color.red)或 na。我们同样使用 color.new() 函数使这个颜色透明。最终的结果是,发生卖出信号的K线会有一个红色的背景。

使用背景色来高亮条件和信号

当上述示例指标被添加到S&P 500指数差价合约图表上时,它看起来是这样的:

添加到EuroStoxx 50指数差价合约图表上时,看起来如下:

该指标创建了以下输入选项:

如果我们,例如,将“Source Data”选项改为“hl2”(K线的中点;(high + low) / 2),并将“RSI Overbought”和“RSI Oversold”水平设为65和35,那么前一个EuroStoxx 50图表将变为:

总结

bgcolor() 函数可以从上到下为图表背景着色,这既可以是主图表区域(当脚本叠加在交易品种上时),也可以是脚本自己的子图。当我们在脚本中重复使用 bgcolor() 函数时,它们的调用顺序很重要:第一个 bgcolor() 语句创建了主背景色,后续的 bgcolor() 函数则会在之前的背景上进行叠加。这些额外的 bgcolor() 函数调用需要有条件地为背景着色;否则,它们会为所有K线的背景都着上颜色,从而导致我们无法看到第一层背景色。

为外汇交易时段的背景着色

在TradingView中,我们可以为图表背景着色,并利用该功能有条件地为背景着色或组合不同的背景色。但我们该如何利用背景着色来高亮显示特定的时间段,例如外汇市场的各个交易时段呢?

为TradingView中的外汇交易时段背景着色

标准的TradingView颜色以及十六进制颜色值可以与多个TradingView函数结合使用,其中包括 bgcolor()。该函数可以从上到下为K线的完整背景着色,其作用区域取决于脚本的显示位置(即主价格图表或子图)。

我们可以在同一个脚本中一次或多次使用 bgcolor()。当重复使用时,着色的背景会相互叠加,最后执行的 bgcolor() 函数会创建最顶层的背景色。利用这个特性,我们可以,例如,根据总体趋势状况为背景着色,然后在实际的买卖信号出现时再次为价格K线上色。

bgcolor() 的另一个用途是为交易时段的背景着色,当交易时段重叠时,这也会创建出叠加的背景。为了解这在TradingView中如何实现,在本文中,我们将编写一个指标,为以下外汇交易时段的背景着色:

外汇市场时段 时间(UTC-5)
纽约 8:00 – 17:00
伦敦 3:00 – 12:00
东京 18:00 – 3:00
悉尼 16:00 – 1:00

要通过编程为这些时段的背景着色,我们首先需要判断一根K线是否落在纽约、伦敦、东京或悉尼时段内。我们可以通过 time() 函数来实现,该函数接受两个参数:K线的时间周期和交易时段。如果K线落在该时段内,函数会返回K线的时间;如果不在,则返回NaN(不可用)值。通过这种方式,我们可以确定一根K线是否在某个时段内,并在条件成立时为其背景着色。

注意

在TradingView中,交易时段总是以交易所时区来定义的。这就是为什么上表中的时间已经调整为UTC-5(TradingView中FXCM交易所的时区)。除此之外,图表自身的时区也需要设为交易所时区,这样下面讨论的示例指标才能正常工作。要将图表设为该时区,请在图表上单击右键,选择“属性”,然后切换到“时区/交易时段”标签页。

现在,让我们讨论如何为外汇交易时段的背景着色。

通过编程为TradingView Pine中的外汇交易时段背景着色

我们的示例指标最多可以为四个外汇时段的背景着色。由于伦敦时段与纽约时段重叠,而东京交易时间与悉尼重叠,我们将看到部分重叠的背景颜色。

在回顾完代码之后,我们将看看该指标及其输入选项的样子。但首先是代码:

//@version=5
indicator(title="Forex trading sessions", overlay=true)

// 输入选项
nySession   = input.session("0800-1700", title="New York session")
showNy      = input.bool(true, title="Display New York session?")
lonSession  = input.session("0300-1200", title="London session")
showLon     = input.bool(true, title="Display London session?")
tokSession  = input.session("1800-0300", title="Tokyo session")
showTok     = input.bool(true, title="Display Tokyo session?")
sydSession  = input.session("1600-0100", title="Sydney session")
showSyd     = input.bool(true, title="Display Sydney session?")

// 颜色常量
nyColour  = color.new(#4169E1, 85) // 宝蓝色 (85% 透明)
lonColour = color.new(#FF6347, 85) // 番茄色 (85% 透明)
tokColour = color.new(#CD853F, 85) // 秘鲁色 (85% 透明)
sydColour = color.new(#3CB371, 85) // 中海绿色 (85% 透明)

// InSession() 用于判断一根K线是否落在指定的时段内
InSession(sess) => na(time(timeframe.period, sess)) == false

// 为每个时段的背景着色
bgcolor(InSession(nySession)[1] and showNy ? nyColour : na, title="New York")
bgcolor(InSession(lonSession)[1] and showLon ? lonColour : na, title="London")
bgcolor(InSession(tokSession)[1] and showTok ? tokColour : na, title="Tokyo")
bgcolor(InSession(sydSession)[1] and showSyd ? sydColour : na, title="Sydney")

我们以 indicator() 函数开始来指定指标的名称。通过将其 overlay 参数设为 true,脚本会在主图表区域显示,而不是在一个单独的子图中。

然后,我们创建几个输入选项:

nySession   = input.session("0800-1700", title="New York session")
showNy      = input.bool(true, title="Display New York session?")
lonSession  = input.session("0300-1200", title="London session")
showLon     = input.bool(true, title="Display London session?")
tokSession  = input.session("1800-0300", title="Tokyo session")
showTok     = input.bool(true, title="Display Tokyo session?")
sydSession  = input.session("1600-0100", title="Sydney session")
showSyd     = input.bool(true, title="Display Sydney session?")

我们使用专门的函数来创建这些手动输入项。这些函数不仅在脚本的设置中创建一个输入选项,还会返回该输入的当前值。我们在这里使用赋值运算符(=)将这些值存储在变量中,这样稍后就可以在代码中引用输入的当前值。

我们在这里创建了两种输入选项。第一种是时间范围输入,它们定义了纽约、伦敦、东京和悉尼的交易时段,我们通过 input.session() 函数来创建。每个输入都通过 title 参数被赋予一个描述性的名称(如“New York session”)。

要为一个时段输入设置默认值,我们将其第一个参数设为一个包含24小时格式时段的字符串。因此,“New York session”输入的标准值被设为"0800-1700",而东京时间范围则被指定为"1800-0300"。这些手动时段输入的当前值分别存储在 nySessionlonSessiontokSessionsydSession 变量中。

其他的输入选项都是布尔型(真/假)输入。Pine Script通过 input.bool() 函数来创建这些复选框。我们将它们的当前值存储在 showNyshowLonshowTokshowSyd 变量中,稍后将使用这些输入来开启或关闭背景色的显示。

由于 input.bool() 返回的是输入的当前值,因此当复选框被勾选时,这些变量的值为 true,未勾选时则为 false。所有布尔型输入默认都是启用的(true),并使用 title 参数赋予一个描述性的名称(如“Display New York session?”和“Show Sydney session?”)。

然后,我们定义几种颜色:

nyColour  = color.new(#4169E1, 85) // 宝蓝色 (85% 透明)
lonColour = color.new(#FF6347, 85) // 番茄色 (85% 透明)
tokColour = color.new(#CD853F, 85) // 秘鲁色 (85% 透明)
sydColour = color.new(#3CB371, 85) // 中海绿色 (85% 透明)

这些变量中的每一个都被赋予一个十六进制颜色值。我们通过 color.new() 函数为这些颜色设置透明度。

通过将这些颜色存储在变量中,稍后引用正确的颜色会更容易,这在代码量很大且同一颜色被重复使用的脚本中尤其有帮助。

在那之后,我们创建一个自定义的单行函数:

InSession(sess) => na(time(timeframe.period, sess)) == false

自定义函数的好处在于我们只需编写一次,就可以在脚本中根据需要多次使用。这减少了代码量(以及潜在的错误),并且后续我们只需修改这个函数,就可以改变它在脚本中所有地方的行为。

创建单行函数的方法是:指定函数名称,在括号 () 内放置其接受的参数,后跟函数声明运算符 =>,最后是函数的表达式。在我们的外汇时段脚本中,我们创建了一个名为 InSession 的自定义函数,它接受一个参数 sess。在函数内部,我们判断 na(time(timeframe.period, sess)) 这个表达式是否等于 false

该表达式的评估是从内到外的,因此 time() 函数首先被执行。time() 函数在这里使用了两个参数:sess(即我们自定义函数 InSession() 的参数)和 timeframe.period(一个返回K线时间周期的内置变量)。通过这两个参数,time() 函数要么在K线落在指定时段内时返回K线的时间,要么在时段外时返回一个NaN值。

接着,na() 函数处理可能出现的NaN值。如果其括号内的值为NaN,该函数返回1(等同于true)。这意味着,当 time() 返回NaN来表示当前K线在指定时段之外时,na() 会返回 true。然而,我们关心的是哪些K线在时段之内,而非之外。因此,我们检查 na() 返回的值是否等于 false。当 time() 返回K线时间(表示K线在时段内)时,na() 会返回 false,此时我们的条件评估为 true

所以,我们的 InSession() 函数的作用是,当当前K线位于指定的时段内时返回 true,不在时则返回 false

创建完函数后,我们为每个交易时段的背景着色:

bgcolor(InSession(nySession)[1] and showNy ? nyColour : na, title="New York")
bgcolor(InSession(lonSession)[1] and showLon ? lonColour : na, title="London")
bgcolor(InSession(tokSession)[1] and showTok ? tokColour : na, title="Tokyo")
bgcolor(InSession(sydSession)[1] and showSyd ? sydColour : na, title="Sydney")

背景着色是通过 bgcolor() 完成的,这四个 bgcolor() 语句所使用的颜色由条件(三元)运算符(?:)返回。该运算符会评估一个条件,当条件为真时,返回运算符的第二个值;如果条件为假,则返回其第三个值。

第一个 bgcolor() 语句为纽约时段的背景着色,其条件运算符会检查 InSession(nySession)[1]showNy 是否都为真。由于我们使用 and 逻辑运算符连接这两个表达式,因此它们必须都为 true,整个组合条件才为 true

所以,我们首先使用 InSession() 函数,并传入 nySession 输入变量(默认持有 "0800-1700" 范围)。如上所述,该自定义函数在当前K线落在指定时段内时返回 true。然而,TradingView K线的时间是其收盘时间,这意味着8:00的K线并不代表时段的开始,而是包含了纽约时段开盘前的价格行为。这就是为什么我们在 InSession() 之后紧跟着加上了值为1的历史引用运算符[],以引入一根K线的延迟。现在,在一个30分钟的图表上,8:30的K线才被视为时段的第一根K线,而17:00结束该时段。

第二个表达式就是 showNy,即我们那个持有“Display New York session?”选项值的布尔输入变量。该输入默认被启用(true),这里用于启用或禁用纽约时段的背景。这是通过条件运算符完成的,它将 bgcolor() 函数的 color 参数设为 nyColour 变量(持有宝蓝色)或 nana 这个内置变量代表一个非数字的值,当用于着色时,会产生一种不可见的颜色。

这样做的效果是:如果当前K线位于纽约时段内,并且“Display New York session?”输入被启用,那么我们就将图表背景涂成宝蓝色。如果K线不在该时段内和/或该输入被禁用,那么背景就不会被着色。

我们使用的另一个 bgcolor() 参数是 title。它用于指定背景的名称,这个名称会显示在脚本的样式窗口中,以便在手动更改脚本颜色时使用。通过指定一个描述性的名称,我们可以轻松地在该设置窗口中识别出它。

接下来的三个 bgcolor() 函数调用与第一个几乎完全相同。在每一个调用中,我们都使用 InSession() 来检查K线是否落在指定的时段内(由 lonSessiontokSessionsydSession 输入变量持有)。并且,当它们对应的复选框被启用时(其值存储在 showLonshowTokshowSyd 变量中),我们就使用之前定义的颜色变量之一(lonColourtokColoursydColour)为背景着色;否则,背景被设为 na(这会关闭背景着色)。

注意

当背景色相互叠加时(就像这里重叠的外汇交易时段那样),最后执行bgcolor() 函数会创建出位于最顶层的背景。这意味着,改变 bgcolor() 语句的顺序会影响图表的外观。

示例:在TradingView中高亮显示外汇市场时段

当我们将上述示例指标添加到英镑/美元图表时,效果如下:

添加到15分钟的欧元/美元图表上时,我们的脚本看起来如下:

该指标创建了以下输入选项:

举个例子,如果我们通过这些输入禁用了伦敦和东京时段,那么前一张欧元/美元图表将变为:

现在,将悉尼时段的结束时间改为3:00(而不是默认的1:00),并让纽约时段提前2小时开始,图表会变为:

总结

bgcolor() 函数可以从上到下为图表背景着色,其作用区域既可以是主图表区域(当脚本叠加在交易品种上时),也可以是脚本自己的子图。当我们在代码中重复使用 bgcolor() 语句时,它们的调用顺序很重要:第一个 bgcolor() 语句创建了主背景色,而后续 bgcolor() 函数调用的背景色则会叠加在之前创建的背景之上。

用叠加背景做出热力图效果

在TradingView中,我们可以为图表背景着色,并利用该功能有条件地为背景着色或叠加不同的背景色。但我们该如何利用背景着色来创建一种类似热力图(heat map)的效果呢?

为背景着色并创建热力图效果

TradingView的 bgcolor() 函数可以从上到下为K线的完整背景着色,其作用区域既可以是主价格图表,也可以是子图(取决于脚本本身显示在哪里)。该函数可以使用标准的TradingView基础颜色或十六进制颜色值为图表背景着色。

我们可以在同一个脚本中一次或重复地使用 bgcolor()。当我们在代码中让 bgcolor() 在同一根价格K线上被执行多次时,其着色的背景会相互叠加:第一个 bgcolor() 函数调用创建了最底层的背景,而最后一个 bgcolor() 语句则会创建最顶层的背景色。

bgcolor() 的这个特性也可以用来创建一种热力图效果,例如,用绿色系的背景来表示上升趋势,用红色系的背景来表示下降趋势。这种效果是通过将叠加着色背景条件性着色相结合来实现的。

比方说,我们有5个 bgcolor() 语句,它们都有条件地将背景涂成红色或绿色。当它们全部将K线背景涂成绿色时,图表背景就完全是绿色的(红色背景同理)。但是,当三个 bgcolor() 语句将背景设为绿色,而另外两个设为红色时,我们最终会得到一个带有红色色度的偏绿色背景。通过在每根K线上都这样做,我们将创建出一种热力图效果,其中一些K线是全绿的,另一些是全红的,还有一些则是偏绿或偏红的。

使用MACD在TradingView中创建类似热力图的背景

一种常见思路是使用MACD(平滑异同移动平均线)指标来创建类似热力图的背景。MACD是一个利用快慢两条移动平均线的趋势-背离指标。在计算出这两条均线之间的差值后,这个差值(通常绘制成直方图)会再通过一条额外的移动平均线进行平滑,并作为信号线绘制出来。

在下方的示例指标中,我们使用MACD指标的不同值来创建一种热力图效果。在讨论完示例之后,我们将看看几个图表示例,但首先来讨论脚本的代码:

//@version=5
indicator(title="MACD background heatmap", overlay=true)

// 输入选项
srcData   = input.source(close, title="Price data")
firstMA   = input.int(12, title="Fast MA")
secondMA  = input.int(26, title="Slow MA")
signalLen = input.int(9, title="Signal length")

// 计算数值
fastMA     = ta.ema(srcData, firstMA)
slowMA     = ta.ema(srcData, secondMA)
macdDiff   = fastMA - slowMA
macdSignal = ta.ema(macdDiff, signalLen)
macdHist   = macdDiff - macdSignal

emaColour = fastMA > slowMA ? color.green : color.red

// 绘制线条
plot(fastMA, color=emaColour, linewidth=2)
plot(slowMA, color=emaColour, linewidth=2)

// 为背景着色
buyColour  = color.new(color.green, 97)
sellColour = color.new(color.red, 97)

// .. 基于均线
bgcolor(fastMA > slowMA ? buyColour : sellColour)
bgcolor(ta.change(fastMA) > 0 ? buyColour : sellColour)
bgcolor(ta.change(slowMA) > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdDiff) > 0 ? buyColour : sellColour)

// .. 基于直方图值
bgcolor(macdDiff > macdHist ? buyColour : sellColour)
bgcolor(macdHist > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdHist) > 0 ? buyColour : sellColour)

// .. 基于MACD信号线
bgcolor(macdDiff > macdSignal ? buyColour : sellColour)
bgcolor(macdSignal > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdSignal) > 0 ? buyColour : sellColour)

我们以 indicator() 函数开始,这是每个指标都必需的。通过将其 overlay 参数设为 true,该指标会显示在主价格图表上,而不是在单独的图表面板中。

接下来,我们创建几个输入选项:

// 输入选项
srcData   = input.source(close, title="Price data")
firstMA   = input.int(12, title="Fast MA")
secondMA  = input.int(26, title="Slow MA")
signalLen = input.int(9, title="Signal length")

我们使用专门的Pine Script函数来创建这些输入。这些函数不仅在脚本的设置中创建一个输入选项,还会返回该设置的当前值。通过使用赋值运算符(=)将该值存储在一个变量中,我们就可以方便地更改脚本中使用的某个值,而无需编辑脚本的源代码。

我们首先使用 input.source() 函数创建一个数据源输入类型,并将其当前值存入 srcData 输入变量。这种类型的输入会在脚本的设置中创建一个下拉菜单,用于从图表上的交易品种中选择不同的价格数据。该菜单例如包含high、low和close等选项。这里我们将输入的默认值设为 close

另外三个输入都是整数输入选项,我们通过 input.int() 函数创建。第一个,名为“Fast MA”,默认值为12。下一个输入名为“Slow MA”,默认为26。最后一个输入的标题是“Signal length”,我们将其标准值9存储在 signalLen 输入变量中。

然后,我们计算脚本中需要的一些值:

// 计算数值
fastMA     = ta.ema(srcData, firstMA)
slowMA     = ta.ema(srcData, secondMA)
macdDiff   = fastMA - slowMA
macdSignal = ta.ema(macdDiff, signalLen)
macdHist   = macdDiff - macdSignal

MACD的移动平均线是通过 ta.ema() 计算的,该函数返回一个指数移动平均线(EMA),并需要两个参数:一个要处理的值序列和一个设定EMA周期的整数。

为了得到快线均线的值,我们使用 ta.ema() 并传入 srcDatafirstMA 输入变量。慢线均线(其值我们赋给 slowMA 变量)的确定方式类似,只是这里我们将EMA的周期设为 secondMA 输入变量。

然后,我们从快线均线中减去慢线均线的当前值,并将差值存储在 macdDiff 变量中。接下来创建的 macdSignal 变量被设为快慢均线差值(macdDiff)的EMA,并在 signalLen 根K线上计算。最后,我们通过从 macdDiff 变量中减去 macdSignal 变量来计算MACD的直方图值(macdHist)。

在绘制移动平均线之前,我们首先确定它们的颜色:

emaColour = fastMA > slowMA ? color.green : color.red

绘图的颜色(我们存储在 emaColour 变量中)在这里由条件运算符(?:)确定。该运算符需要一个布尔(真/假)条件作为其第一个值。当该条件为 true 时,它返回其第二个值;当条件为 false 时,则返回其第三个值。

我们这里的条件是 fastMA 变量的值是否大于(>) slowMA 变量。当指标的输入选项设为其默认值时,这个条件评估的是12周期的收盘价EMA是否在26周期的收盘价EMA之上。

当这种情况在当前K线上发生时,条件运算符会返回绿色(color.green),该颜色随即被存储在 emaColour 变量中。如果快线均线小于或等于慢线均线(即条件不为真),那么条件运算符会返回红色(color.red)并赋给 emaColour 变量。这也意味着这个变量的值要么是绿色,要么是红色。

我们在绘制EMA值时使用 emaColour 变量:

// 绘制线条
plot(fastMA, color=emaColour, linewidth=2)
plot(slowMA, color=emaColour, linewidth=2)

plot() 函数默认会创建一个线图,其值由其第一个参数指定。在第一个 plot() 语句中,我们将该参数设为 fastMA 变量。这些快线EMA的值会根据 emaColour 变量进行着色,因此会根据两条EMA的相对位置显示为红色或绿色。通过将 linewidth 参数设为2,我们创建了一条比默认尺寸大一级的线条。第二个 plot() 语句几乎完全相同,只是这次我们在图表上显示的是 slowMA 的值。

在绘制完移动平均线之后,我们为图表的背景着色。这些叠加的背景色是通过三个步骤制作的:首先,我们基于移动平均线为图表背景着色;然后,我们使用直方图值;最后,bgcolor() 语句使用MACD信号线。

在开始之前,我们首先定义要使用的背景颜色:

buyColour  = color.new(color.green, 97)
sellColour = color.new(color.red, 97)

我们创建了两个变量:buyColoursellColour。第一个被设为一个透明的绿色(color.green)颜色值,另一个则持有一个透明的红色(color.red)。我们使用 color.new() 函数使它们的透明度都达到97%。

通过将这些颜色存储在两个变量中,我们就可以方便地重复使用相同的颜色,而无需每次都输入相同的代码。

然后,我们开始根据移动平均线的值为图表背景从上到下着色:

bgcolor(fastMA > slowMA ? buyColour : sellColour)
bgcolor(ta.change(fastMA) > 0 ? buyColour : sellColour)
bgcolor(ta.change(slowMA) > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdDiff) > 0 ? buyColour : sellColour)

在讨论这些 bgcolor() 语句的具体细节之前,我们先来看看它们的共同点。每一个都通过条件三元运算符(?:)将其第一个参数设为绿色或红色的背景色。如我们之前所见,该运算符会评估一个条件,并在条件为真时返回其第二个值,为假时则返回其第三个值。

我们从之前创建的 buyColoursellColour 变量中获取绿色和红色。我们为它们设置了97%的透明度,这创建了一个高度透明的背景。当我们组合着色背景时,这很有帮助:通过高透明度,我们能看到多层背景颜色相互渗透的效果。如果每个背景都是完全不透明的,这是不可能实现的。

现在让我们来讨论这四个 bgcolor() 语句的作用。第一个根据 fastMA > slowMA 这个条件来为图表背景着色。当快线均线在当前K线上确实大于慢线均线时,bgcolor() 会将背景涂成绿色,否则为红色。由于这个语句是脚本中第一个被调用的 bgcolor() 函数,它创建了所有后续背景色都将叠加于其上的最底层背景。

接下来的三个 bgcolor() 函数在条件运算符中使用了 ta.change() 函数。该函数返回当前值与前一根K线值之间的差值。因此,当括号内的值增加时,它返回一个正数;当值减少时,则返回一个负数。

所以在第二个 bgcolor() 语句中,它评估 change(fastMA) > 0 这个条件,我们判断快线均线在当前K线上是否相较于前一根K线有所上升。如果是,我们视其为看涨,条件运算符返回 buyColour 背景(否则使用 sellColour)。

下一个 bgcolor() 语句也使用 change() 函数,但这里用于评估慢线均线是否上升(change(slowMA) > 0)。如果是,当前K线的背景被涂成绿色。这部分的第四个也是最后一个 bgcolor() 语句则根据两条均线之间距离的变化来设置背景颜色(change(macdDiff) > 0)。

下一组 bgcolor() 语句使用MACD直方图来将背景涂成红色或绿色:

bgcolor(macdDiff > macdHist ? buyColour : sellColour)
bgcolor(macdHist > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdHist) > 0 ? buyColour : sellColour)

这三个 bgcolor() 语句与前面的类似:它们也使用高度透明的绿色(buyColour)或红色(sellColour)变量。

第一个 bgcolor() 调用让条件运算符判断 macdDiff 变量(即快慢均线之差)是否大于 macdHist。后一个变量持有 macdDiff 与其9周期移动平均线之间的差值。

在下一个 bgcolor() 语句中,条件检查MACD直方图(macdHist)是否在0之上。当快慢均线之差大于该差值的9周期EMA时,就会发生这种情况,这可以被视为积极信号,因此我们在此情况下将背景涂成绿色。

对于最后一个 bgcolor() 语句,我们让 change() 函数判断MACD直方图在当前K线上是否增加(change(macdHist) > 0)。由于这也可以被视为看涨,这种情况同样会导致一个绿色的背景。

我们用三个额外的 bgcolor() 语句来结束这个例子,它们根据MACD信号线的值为图表背景着色:

bgcolor(macdDiff > macdSignal ? buyColour : sellColour)
bgcolor(macdSignal > 0 ? buyColour : sellColour)
bgcolor(ta.change(macdSignal) > 0 ? buyColour : sellColour)

这里,我们再次让条件运算符为 bgcolor() 函数的使用选择两种颜色之一。

第一个 bgcolor() 调用在这里根据 macdDiff > macdSignal 这个条件被设为绿色或红色。每当快慢均线之间的差值大于该差值的EMA时,该条件就评估为真。

macdSignal 变量也用于第二个 bgcolor() 语句,但这次,快慢均线之差的EMA需要为正(macdSignal > 0),背景才会被涂成绿色。

我们示例的最后一行也使用了那个EMA,这次是一个 bgcolor() 函数调用,它根据该EMA与前一根K线的变化情况来为背景着色(change(macdSignal) > 0)。

以编程方式在TradingView中创建类似热力图的背景

当我们将示例指标添加到欧元/美元图表时,它看起来是这样的:

在S&P 500指数差价合约图表上,这些叠加的背景看起来是这样的:

在更改指标设置之前,它的背景在原油差价合约图表上看起来是这样的:

该指标的输入选项如下:

举个例子,当我们把“Fast MA”和“Slow MA”的输入值改为25和57后,前一张原油图表就变成了:

总结

bgcolor() 函数可以从上到下为K线的背景着色,颜色由其第一个参数设定。该函数的作用区域既可以是主图表区域(当脚本叠加在交易品种上时),也可以是脚本自己的子图。当我们在一个脚本中重复使用 bgcolor() 函数时,它们的调用顺序很重要:第一个 bgcolor() 语句创建了主背景色,而后续的 bgcolor() 函数调用则会创建叠加在之前背景之上的新背景色。这使得创建类似热力图的背景成为可能,前提是颜色要高度透明,以便底层的背景颜色能够透出来。

赞(0)
未经允许不得转载:图道交易 » Pine Script(152):叠加背景色、交易时段背景与热力图效果
分享到

评论 抢沙发

登录

找回密码

注册