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

Pine Script(100):交叉信号三剑客,ta.crossover/crossunder/cross详解

#Pine Script入门教学

在TradingView Pine脚本中,一个非常常见的任务是判断某个数值是否穿越了另一个数值。例如,我们可能想检查10周期的移动平均线是否上穿了30周期的SMA,或者判断相对强弱指数 (RSI) 是否下穿了30。接下来,我们就来看看如何用代码实现这些判断。

在TradingView Pine中判断数值的交叉

TradingView Pine中变量的独特之处在于,它们并非只包含一个单一的值,而是持有一系列的值(即时间序列,series),每一个价格K线都对应一个值。这使得我们可以轻松地获取例如前一根K线的平均真实波幅 (ATR) 值。我们也可以利用这种时间序列的特性,来判断一个序列的值是否穿越了某个固定值,或者穿越了另一个序列。

TradingView提供了三个非常有用的函数,来帮助我们判断数值的交叉情况:

  • ta.crossover():用于判断一个时间序列的值是否上穿了另一个序列或某个固定值。
  • ta.crossunder():用于判断一个时间序列的值是否下穿了另一个序列或某个固定值。
  • ta.cross():用于判断一个时间序列的值是上穿还是下穿了另一个序列或某个固定值(即任意方向的交叉)。

让我们来更深入地了解这些函数,以及如何在我们的脚本中应用它们。

判断一个值是否上穿另一个值

内置的 ta.crossover() 函数用于检查一个序列的值是否向上穿越了另一个序列。当向上交叉发生时,ta.crossover() 返回 true;如果没有发生上穿,该函数则返回 false

ta.crossover() 有两种主要用法:

  1. 函数可以检查一个时间序列是否上穿了另一个时间序列。例如,我们可以用它来监控10周期的简单移动平均线 (SMA) 是否上穿了20周期的SMA。
  2. 函数也可以判断一个时间序列是否上穿了某个固定的数值。例如,用它来判断相对强弱指数 (RSI) 是否上穿了80。

相应地,ta.crossover() 也有两种语法形式:

ta.crossover(seriesA, seriesB)
ta.crossover(series, value)

上面代码片段的第一行,展示了如何使用 ta.crossover() 来判断一个序列是否上穿了另一个序列。第二行则展示了如何判断一个序列的当前值是否上穿了某个固定值(例如一个止盈目标、计算出的数值,或是一个输入选项的值)。

特别说明

要让 ta.crossover() 函数判定为一次有效的上穿,必须同时满足以下两个条件:

  1. 前一根K线上,第一个参数的值必须小于或等于第二个参数的值。
  2. 并且,在当前K线上,第一个参数的值必须大于第二个参数。

当这两个条件同时成立时,ta.crossover() 才会返回 true,否则返回 false

现在,让我们通过两个示例脚本,来分别看看 ta.crossover() 函数的这两种用法。

示例:判断一个序列是否上穿另一个序列

ta.crossover() 的第一种用法,是判断一个时间序列的值是否向上穿越了另一个序列。假设我们绘制了一条14周期的相对强弱指数 (RSI) 和它自身的5周期指数移动平均线 (EMA)。现在,我们希望指标能够高亮显示RSI指标线上穿其均线的那些K线。实现这个功能的一种方法就是使用 ta.crossover() 函数。

当我们用背景色来高亮这些交叉点时,图表看起来是这样的:

该示例指标的完整代码如下:

//@version=5
indicator(title="Crossover example", overlay=false)

// 计算指标值
rsiValue = ta.rsi(close, 14)
rsiEMA   = ta.ema(rsiValue, 5)

// 当RSI上穿其EMA时,高亮背景色
bgcolor(ta.crossover(rsiValue, rsiEMA) ? color.new(color.fuchsia, 90) : na)

// 绘制指标值并显示超买超卖线
plot(rsiValue, color=color.orange)
plot(rsiEMA, color=color.teal, linewidth=2)

hline(30)
hline(70)

让我们来解析一下代码。首先,我们使用 indicator() 函数来定义指标的属性。然后,我们计算RSI和它的EMA:

// 计算指标值
rsiValue = ta.rsi(close, 14)
rsiEMA   = ta.ema(rsiValue, 5)

接着,当RSI上穿其移动平均线时,我们高亮显示背景:

// 当RSI上穿其EMA时,高亮背景色
bgcolor(ta.crossover(rsiValue, rsiEMA) ? color.new(color.fuchsia, 90) : na)

我们使用 bgcolor() 函数来通过背景色高亮交叉点。但我们只想在发生上穿的K线上进行高亮。因此,我们将 rsiValuersiEMA 作为参数传递给 ta.crossover() 函数。当14周期的RSI向上穿越其5周期的EMA时,该函数返回 true(否则返回 false)。

当这种交叉发生时,TradingView的条件运算符 (?:) 会返回带有90%透明度的紫红色 (color.fuchsia)。这个颜色随后被 bgcolor() 函数用于渲染背景。如果没有发生RSI-EMA的交叉,条件运算符则返回 na,这个值会禁用背景色。最终的效果是,我们只高亮了那些确切发生上穿的K线。

之后,我们使用 plot() 函数将RSI和它的移动平均线以常规线图的形式显示出来:

// 绘制指标值并显示超买超卖线
plot(rsiValue, color=color.orange)
plot(rsiEMA, color=color.teal, linewidth=2)

最后,我们使用 hline() 函数绘制出两条代表超买和超卖区域的水平线:

hline(30)
hline(70)

示例:判断一个序列是否上穿某个固定值

ta.crossover() 的另一种应用,是检查一个时间序列的值是否向上穿越了某个固定的数值。假设我们绘制了一个相对强弱指数 (RSI),并希望高亮显示那些RSI指标线上穿其中性水平线50的K线。实现这个功能的一种方法就是使用 ta.crossover() 函数。

当我们用背景色来高亮这些上穿时,它们在图表上看起来是这样的:

该示例指标的完整代码如下:

//@version=5
indicator(title="Crossover example", overlay=false)

// 计算 RSI 指标值
rsiValue = ta.rsi(close, 12)

// 当 RSI 上穿 50 中性水平线时,高亮背景色
bgcolor(ta.crossover(rsiValue, 50) ? color.new(color.lime, 90) : na)

// 绘制 RSI 及其中性水平线
plot(rsiValue, color=color.orange)
hline(50)

这段代码首先用 ta.rsi() 函数计算12周期的RSI。随后,我们将 rsiValue 变量和固定数值 50 一起传入 ta.crossover() 函数:只要RSI从下方向上穿越50,该函数就返回 true。此时,条件运算符 (?:) 会返回一个带有90%透明度的青柠色 (color.lime),供 bgcolor() 函数渲染背景;没有发生上穿时则返回 na,背景保持无色。最后,我们用 plot() 绘制RSI线,并用 hline() 画出50这条中性水平线。

判断一个值是否下穿另一个值

ta.crossover() 相对应,内置的 ta.crossunder() 函数用于检查一个序列的值是否向下穿越了另一个序列或某个固定值。当向下交叉发生时,ta.crossunder() 返回 true;如果没有发生下穿,该函数则返回 false

它同样有两种语法形式:

ta.crossunder(seriesA, seriesB)
ta.crossunder(series, value)

第一行用于判断一个序列是否下穿了另一个序列,第二行则用于判断一个序列是否跌破了某个固定数值。

特别说明

要让 ta.crossunder() 函数判定为一次有效的下穿,必须同时满足以下两个条件:

  1. 前一根K线上,第一个参数的值必须大于或等于第二个参数的值。
  2. 并且,在当前K线上,第一个参数的值必须小于第二个参数。

当这两个条件同时成立时,ta.crossunder() 才会返回 true,否则返回 false

示例:判断一个序列是否下穿另一个序列

ta.crossunder() 的第一种用法,是判断一个时间序列的值是否向下穿越了另一个序列。假设我们绘制了随机指标 (Stochastic) 的 %K和 %D两条线,并希望高亮显示 %K线跌破 %D线的那些K线。

当我们用背景色来高亮这些下穿时,图表看起来是这样的:

该示例指标的完整代码如下:

//@version=5
indicator(title="Crossunder example", overlay=false)

// 计算指标值
stochK = ta.sma(ta.stoch(close, high, low, 14), 3)
stochD = ta.sma(stochK, 3)

// 判断下穿条件
crossBelow = ta.crossunder(stochK, stochD)

// 当发生下穿时,高亮背景色
bgcolor(crossBelow ? color.new(color.red, 80) : na)

// 绘制随机指标线
plot(stochK, color=color.orange)
plot(stochD, color=color.teal)

hline(20)
hline(80)

我们首先使用 indicator() 函数来定义指标的属性。然后,我们计算随机指标的两条线:

// 计算指标值
stochK = ta.sma(ta.stoch(close, high, low, 14), 3)
stochD = ta.sma(stochK, 3)

接下来,ta.crossunder() 函数会判断其中一条线是否向下穿越了另一条:

crossBelow = ta.crossunder(stochK, stochD)

这里我们调用 ta.crossunder() 函数并传入两个参数。第一个参数 stochK 变量,持有随机指标 %K的值;另一个参数 stochD,则持有随机指标 %D的值。当 %K指标线向下跌破 %D指标线时,ta.crossunder() 函数便会返回 true。如果这种交叉没有发生,函数则返回 false

我们将 ta.crossunder() 的判断结果储存在 crossBelow 变量中。接着,在为图表背景上色时,我们会用到这个变量:

bgcolor(crossBelow ? color.new(color.red, 80) : na)

因为我们并不想为每一根K线的背景都上色,所以这里使用了TradingView的条件运算符 (?:)。该运算符会判断 crossBelow 变量的值。当其为 true 时,我们就通过 bgcolor() 函数将背景设为带有80%透明度的红色 (color.red)。否则,我们使用 na 值来禁用背景色。通过这种方式,我们只高亮了那些 %K线确切跌破 %D线的K线。

然后,我们使用 plot() 函数将两条随机指标线以常规线图的形式显示出来:

// 绘制随机指标线
plot(stochK, color=color.orange)
plot(stochD, color=color.teal)

最后,我们通过 hline() 函数来绘制该振荡指标的超买和超卖水平线:

hline(20)
hline(80)

示例:判断一个序列是否跌破某个固定值

ta.crossunder() 的另一种用法,是判断一个时间序列的值是否向下穿越了某个固定的数值。例如,我们可以用它来监控随机指标的 %K值是否跌破了20或80。当我们高亮这些情况时,图表看起来是这样的:

实现这一功能的指标代码如下:

//@version=5
indicator(title="Crossunder example", overlay=false)

// 计算指标值
stochK = ta.sma(ta.stoch(close, high, low, 14), 3)
stochD = ta.sma(stochK, 3)

// 当 %K 下穿 20 或 80 时为背景上色
osCross = ta.crossunder(stochK, 20)
obCross = ta.crossunder(stochK, 80)

backgroundColour = if osCross
    color.new(color.teal, 80)
else if obCross
    color.new(color.orange, 80)

bgcolor(backgroundColour)

// 绘制随机指标线
plot(stochK, color=color.orange)
plot(stochD, color=color.teal)

hline(20)
hline(80)

我们首先使用 indicator() 函数来定义指标的属性。然后,我们计算随机指标的 %K和 %D值:

stochK = ta.sma(ta.stoch(close, high, low, 14), 3)
stochD = ta.sma(stochK, 3)

接着,我们判断随机指标的 %K线是否跌破了20或80这两个水平位:

osCross = ta.crossunder(stochK, 20)
obCross = ta.crossunder(stochK, 80)

这里,我们首先让 ta.crossunder() 函数检查 stochK 变量的值是否跌破了固定的数值 20。如果确实发生了下穿,ta.crossunder() 会返回 true(否则返回 false)。我们将这个布尔结果储存在 osCross 变量中,以备后用。

随后,ta.crossunder() 函数再次检查 stochK 变量是否跌破了数值 80。如果是,函数返回 true(否则返回 false)。我们将这个结果存入 obCross 变量。

接下来,我们根据这两个交叉事件来为背景上色:

backgroundColour = if osCross
    color.new(color.teal, 80)
else if obCross
    color.new(color.orange, 80)

bgcolor(backgroundColour)

这段代码首先创建了 backgroundColour 变量。我们通过一个级联的if语句,为这个变量赋予两种颜色之一。

第一个 if 条件检查 osCross 变量是否为 true。如果是,代码会返回一个通过 color.new() 函数设置了80%透明度的青色 (color.teal),Pine Script随后将这个颜色值存入 backgroundColour 变量。

如果第一个 if 条件不成立,那么代码会继续检查第二个 if 条件,判断 obCross 变量是否为 true。如果是,代码会返回一个带有80%透明度的橘色 (color.orange)。

如果第二个条件也不成立,Pine Script会隐式地返回 na 值(并将其存入 backgroundColour 变量)。na 值的作用是禁用背景色。因此,当随机指标没有跌破20或80时,图表背景将保持无色。

最后,我们调用 bgcolor() 函数来执行实际的背景着色操作,将 backgroundColour 变量的值(两种颜色之一或na)应用到图表背景上。

之后,我们用 plot() 函数绘制出两条常规的线图:

// 绘制随机指标线
plot(stochK, color=color.orange)
plot(stochD, color=color.teal)

最后,我们使用 hline() 函数来绘制代表超买和超卖区域的水平线:

hline(20)
hline(80)

判断任意方向的交叉

当我们不关心交叉的具体方向(是上穿还是下穿)时,可以使用TradingView的 ta.cross() 函数。该函数用于判断两个值是否相互交叉,无论方向如何。当交叉发生时,ta.cross() 返回 true;当没有上穿或下穿时,则返回 false

ta.cross() 函数有两种主要用法:

  1. 函数可以判断一个时间序列是否与另一个时间序列发生交叉。例如,用它来判断15周期的简单移动平均线 (SMA) 是否与35周期的SMA发生了交叉。
  2. 函数也可以判断一个时间序列是否穿越了某个固定的数值。例如,我们可以用它来判断一条移动平均线是否穿越了某个关键价位,或者相对强弱指数 (RSI) 是否穿越了50这个中性水平。

相应地,ta.cross() 也有两种语法形式:

ta.cross(seriesA, seriesB)
ta.cross(series, value)

第一行代码用于判断一个序列是否与另一个序列发生了交叉(向上或向下)。第二行则用于判断一个序列是否上穿或下穿了某个固定值。

特别说明

以下是 ta.cross() 函数如何定义上穿和下穿的:

  • 对于上穿 (crossover):
    • 前一根K线上,第一个参数的值必须小于或等于第二个参数的值。
    • 并且,在当前K线上,第一个参数的值必须大于第二个参数。
  • 对于下穿 (crossunder):
    • 前一根K线上,第一个参数的值必须大于或等于第二个参数的值。
    • 并且,在当前K线上,第一个参数的值必须小于第二个参数。

当上述的上穿或下穿发生时,ta.cross() 才会返回 true,在其他所有情况下,该函数都返回 false

为了解如何在实践中应用 ta.cross() 函数,让我们来看两个示例指标。

示例:判断一个序列是否与另一个序列交叉

ta.cross() 的第一种用法,是判断一个时间序列的值是否与另一个序列发生了交叉。假设我们有一个指标绘制了两条移动平均线,并且我们希望高亮显示这两条均线发生交叉的K线(无论它们是向上还是向下交叉)。

这样一个指标在图表上看起来是这样的:

该示例指标的完整代码如下:

//@version=5
indicator(title="Cross example", overlay=true)

// 计算移动平均线
fastMA = ta.sma(close, 15)
slowMA = ta.sma(close, 35)

// 使用形状高亮交叉点
plotshape(ta.cross(fastMA, slowMA), style=shape.diamond,
     color=color.red)

// 绘制指标值
plot(fastMA, color=color.teal)
plot(slowMA, color=color.orange, linewidth=2)

首先,我们使用 indicator() 函数来定义指标的属性。然后,我们计算两条简单移动平均线 (SMA):

// 计算移动平均线
fastMA = ta.sma(close, 15)
slowMA = ta.sma(close, 35)

我们使用 ta.sma() 函数,在收盘价 (close) 数据上分别计算周期为15和35的移动平均线。我们将计算结果储存在 fastMAslowMA 变量中,以备后用。

接着,我们高亮显示这两条移动平均线发生交叉的K线:

// 使用形状高亮交叉点
plotshape(ta.cross(fastMA, slowMA), style=shape.diamond,
     color=color.red)

我们使用一个形状来标记这些交叉K线。为此,我们调用 plotshape() 函数,它的作用是,当其第一个参数为 true 时,就在图表上绘制一个指定的形状。这里,我们将 ta.cross() 函数的返回值作为其第一个参数,并向 ta.cross() 传入 fastMAslowMA 变量。这样,当15周期的SMA与35周期的SMA发生交叉时,ta.cross() 就会返回 true

当交叉发生时,来自 ta.cross()true 值会促使 plotshape() 函数在图表上创建一个形状。我们使用的形状类型是菱形 (shape.diamond),颜色为红色 (color.red)。

指标代码的最后一部分,使用 plot() 函数将两条移动平均线以常规线图的形式绘制出来:

// 绘制指标值
plot(fastMA, color=color.teal)
plot(slowMA, color=color.orange, linewidth=2)

示例:判断一个序列是否与单个值交叉

ta.cross() 函数的另一种用法,是判断一个变量序列是否穿越了某个固定的数值,例如一个价格目标、振荡器读数或阻力水平。假设我们正在监控比特币 (BTC/USD) 的价格,并希望我们的TradingView脚本能够高亮显示30周期的简单移动平均线 (SMA) 穿越 $6,440这个价位的K线。

这样一个示例指标在图表上看起来是这样的:

要高亮这些交叉点,我们使用如下代码:

//@version=5
indicator(title="Cross example", overlay=true)

// 计算简单移动平均线
smaValue = ta.sma(close, 30)

// 当SMA穿越 $6,440 时高亮背景
bgcolor(ta.cross(smaValue, 6440) ? color.new(color.lime, 90) : na)

// 在图表上绘制SMA
plot(smaValue, color=color.orange, linewidth=2)

首先,我们使用 indicator() 函数来定义指标的设置。然后,我们使用 ta.sma() 函数来计算收盘价的30周期平均值:

// 计算简单移动平均线
smaValue = ta.sma(close, 30)

接下来,我们为那些发生交叉的K线,将图表背景进行上色:

// 当SMA穿越 $6,440 时高亮背景
bgcolor(ta.cross(smaValue, 6440) ? color.new(color.lime, 90) : na)

我们使用 bgcolor() 函数来为图表背景进行从上到下的填充。这里的条件运算符 (?:) 会根据条件,让背景色变为青柠绿色 (color.lime),或者在没有交叉发生时通过 na 值禁用背景色。我们使用 color.new() 函数为这个绿色设置了90%的透明度。

我们所判断的条件,是 ta.cross() 函数的返回值,其参数为 smaValue6440。这使得当30周期的SMA上穿或下穿6,440这个值时,该函数返回 true。当交叉发生时,我们便得到一个带有90%透明度的绿色背景;否则,我们使用 na 来关闭背景色。

该指标的最后一条语句使用 plot() 函数,将30周期的SMA以常规线图的形式显示在图表上:

// 在图表上绘制SMA
plot(smaValue, color=color.orange, linewidth=2)

历史数据与实时数据对交叉判断的影响

三个交叉函数(ta.crossover()ta.crossunder()ta.cross())的判断逻辑,始终是将当前K线的值与前一根K线的值进行比较。而当前K线的值具体是什么,则取决于该K线所处的状态:

  • 当K线是历史K线(即已经收盘)时,这些交叉函数比较的是该K线收盘时的值与前一根K线的收盘值。
  • 当K线是实时K线(即尚未收盘)时,这些函数比较的是当前的实时报价与前一根K线的收盘值。

这也意味着,在实时行情中,我们可能会在某个报价更新时看到交叉信号出现,但随着下一个报价的到来,这个交叉信号又可能消失。然后,在同一根K线内,稍后的某个报价更新又可能让交叉信号重新出现。

需要注意的是,这些交叉函数无法做到的是,比较当前的tick与上一个tick。它们始终是将当前的值与前一根K线的收盘价进行比较。

内容总结

TradingView提供了三个内置函数来监控交叉事件:

  • ta.crossover():我们用这个函数来检查一个序列的值是否上穿了另一个序列(或向上穿越了某个特定值)。例如,可以用它来判断10周期的SMA是否上穿了20周期的均线,或者相对强弱指数 (RSI) 是否上穿了80水平位。
  • ta.crossunder():这个函数用于检查一个序列的值是否下穿了另一个序列(或向下跌破了某个特定值)。例如,我们可以用它来编写“10周期移动平均线跌破30周期SMA”的场景,或者判断商品通道指数 (CCI) 是否下穿了-100。
  • ta.cross():我们用这个函数来监控一个序列的值是否与另一个序列发生了交叉(或穿越某个特定值),而不关心具体的交叉方向。例如,可以用它来编写“随机指标的%K线与%D线发生交叉”的情景,或评估某个指标是否穿越了某个关键数值。
赞(0)
未经允许不得转载:图道交易 » Pine Script(100):交叉信号三剑客,ta.crossover/crossunder/cross详解
分享到

评论 抢沙发

登录

找回密码

注册