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

Pine Script(135):赫尔均线HMA、相对均线RMA及两者与EMA的区别

#Pine Script入门教学

计算赫尔移动平均线(HMA)

在Pine Script中,我们使用 ta.hma() 函数来计算赫尔移动平均线(HMA)。

默认语法

该函数的定义如下:

ta.hma(source, length)
  • source:要处理的数值序列。这是我们计算HMA所依据的数据。
  • length:一个整数,用于设置移动平均线的周期长度(以K线数量计)。它是平均线的回看周期。

ta.hma() 会返回一个浮点值,该值是 source 在过去 length 根K线上的赫尔平均值。

快速范例

所以,要获取赫尔移动平均线(HMA),我们需要向 ta.hma() 提供两样东西:要处理的数据和一个长度。我们来看一些例子。

  • 一个典型的移动平均线任务是平均K线的收盘价。要从该数据中获取赫尔移动平均线,我们在收盘价(close)上运行该平均线。例如:
    // 计算8周期和48周期的赫尔移动平均线
    fastHull = ta.hma(close, 8)
    slowHull = ta.hma(close, 48)
    
    // 在图表上显示两条平均线
    plot(fastHull, color=color.fuchsia)
    plot(slowHull, color=color.orange)
    
  • 除了K线的价格,赫尔移动平均线可以对任何数值序列进行计算。比方说,我们想知道平均成交量。在这种情况下,我们让 ta.hma() 处理 volume 变量:
    // 计算20周期的成交量赫尔移动平均线
    volumeAverage = ta.hma(volume, 20)
    
    plot(volumeAverage)
    
  • 从任何返回一个值序列的数值表达式中获取平均值也是可以的。例如,要计算成交量单根K线差值的平均值,我们可以这样做:
    // 获取成交量差值的12周期平均值
    averageVolumeDiff = ta.hma(volume - volume[1], 12)
    
    plot(averageVolumeDiff)
    
  • 另一个选择是从其他函数返回的数据计算平均值。让我们假设我们想要获取资金流指数(MFI)的平均值。因此我们首先用 ta.mfi() 函数计算MFI,然后取该函数返回值的平均值:
    // 首先计算MFI,然后取其HMA值
    mfiValue   = ta.mfi(close, 14)
    mfiAverage = ta.hma(mfiValue, 8)
    
    plot(mfiValue, color=color.blue)
    plot(mfiAverage, color=color.yellow)
    
  • 如果我们的脚本不需要MFI值本身,我们也可以将 ta.mfi() 直接放在 ta.hma() 函数内部,这样可以缩短代码:
    // 首先计算MFI,然后取其HMA值
    mfiAverage = ta.hma(ta.mfi(close, 14), 8)
    
    plot(mfiAverage, color=color.yellow)
    

脚本范例

让我们看看一个完整的脚本如何使用赫尔移动平均线(HMA)。下方的指标会计算两条HMA,它们的周期长度分别是20和125,都基于交易品种的收盘价进行计算。

我们将这两条平均线以实线的形式显示在图表上,然后比较它们来寻找交易信号。当快线在慢线之上,且价格在快线之上时,我们将K线涂成绿色。如果快线在慢线之下,且价格低于快线时,我们将K线涂成红色。其余的中性K线我们则涂成黄色。

该指标的完整代码如下:

//@version=5
indicator(title="Hull Moving Average example", overlay=true)

// 输入项
averageData = input.source(close, title="Average Data Source")

fastLength = input.int(20, title="Fast Average Length")
slowLength = input.int(125, title="Slow Average Length")

// 计算平均线
fastAverage = ta.hma(averageData, fastLength)
slowAverage = ta.hma(averageData, slowLength)

// 在图表上显示赫尔移动平均线
plot(fastAverage, color=color.red, title="Fast HMA")
plot(slowAverage, color=color.gray, title="Slow HMA")

// 基于HMA决定K线颜色
hmaBarColour = if fastAverage > slowAverage and close > fastAverage
    #3CD070
else if fastAverage < slowAverage and close < fastAverage
    #FC0FC0
else
    #FFC40C

barcolor(hmaBarColour)

我们以 indicator() 函数开始,用于命名该脚本并将其放置在主图的交易品种之上。

接下来,我们创建了三个输入项。第一个是数据源输入(input.source()),用于指定赫尔移动平均线的计算价格数据。另外两个输入是整数输入(input.int()),它们用于设置快线和慢线的周期长度。

说到计算,我们接下来就来计算这些平均线:

// 计算平均线
fastAverage = ta.hma(averageData, fastLength)
slowAverage = ta.hma(averageData, slowLength)

第一个 ta.hma() 调用计算快速平均线。该函数处理 averageData 输入变量,该变量默认持有交易品种的收盘价(close)。其周期长度为 fastLength,该输入变量的默认值为20。

要得到慢速平均线,我们做类似的操作。ta.hma() 再次处理 averageData 变量。这一次,周期长度使用 slowLength 输入变量,其标准周期为125。

计算完平均线后,脚本继续执行其他代码。这些代码首先用 plot() 函数绘制两条平均线。快线显示为红色(color.red),慢线则使用灰色(color.gray)。由于我们没有设置绘图类型,Pine Script会默认将它们都创建为常规的线图。

然后,级联 if 语句用于决定K线的颜色。当快线高于慢线,且价格(close)高于快线时,颜色变为 #3CD070(UFO绿的十六进制颜色值)。如果快线低于慢线,且K线收盘价低于快线,我们则选择 #FC0FC0(亮粉色)。如果两种信号都未发生,我们使用 #FFC40C(帝王黄)作为中性的K线颜色。

然后,在脚本的最后一行代码中,barcolor() 函数将该K线颜色应用到图表上。

在图表上,我们得到了两条用于赫尔移动平均线的实线。该脚本在上升趋势期间将K线变为绿色,下降趋势时为粉色,当赫尔平均线未确认趋势时则为黄色:

总结

  • ta.hma() 函数用于计算赫尔移动平均线(HMA)。
  • 该函数需要两样东西:一个要处理的数值序列,以及要计算的K线数量。

计算相对移动平均线(RMA)

在Pine Script中,我们使用 ta.rma() 函数来计算相对移动平均线(RMA)。

相对移动平均线会给予近期数据更多的权重(并降低旧数据的重要性)。这使得RMA与指数移动平均线相似,尽管它的响应速度比EMA要慢一些。

默认语法

该函数的定义如下:

ta.rma(source, length)
  • source:要处理的数值序列。这是我们计算RMA所依据的(价格)数据。
  • length:一个整数,用于设置移动平均线的周期长度(以K线数量计)。这是Pine Script计算平均线的回看周期。

ta.rma() 会返回相对移动平均线,其结果为一个浮点值。

快速范例

所以,要获取RMA,我们需要向 ta.rma() 提供两样东西:要分析的数据和要计算的周期长度。让我们看看这在实践中是如何运作的。

  • 一个典型的任务是获取K线收盘价的移动平均线。要从该数据中获取一个相对移动平均线,我们在 close 变量上运行该函数。例如:
    // 获取12周期的收盘价相对移动平均线
    closeAverage = ta.rma(close, 12)
    
    plot(closeAverage)
    
  • 除了K线价格,相对移动平均线可以对任何带数字的序列进行计算。比方说,我们想要成交量的相对平均值。为此,我们让 ta.rma() 处理 volume 变量:
    // 计算20周期的成交量RMA
    volumeAverage = ta.rma(volume, 20)
    
    plot(volume, style=plot.style_histogram)
    plot(volumeAverage)
    
  • ta.rma() 函数并不局限于内置变量。事实上,我们可以在任何每根K线上都有值的数值表达式上运行该函数。例如,如果我们想要成交量在5根K线内的差值的平均值,我们可以这样做:
    // 获取5周期成交量变化的15周期平均值
    volChangeAvg = ta.rma(volume - volume[5], 15)
    
    plot(volChangeAvg)
    
  • 另一个选择是在其他函数返回的数据上计算平均值。比方说,我们想平滑商品通道指数(CCI)。要做到这一点,我们首先用 ta.cci() 函数计算CCI,然后让 ta.rma() 处理 ta.cci() 返回的数据:
    // 获取12周期商品通道指数的10周期平均值
    cciValue = ta.cci(close, 12)
    rmaValue = ta.rma(cciValue, 10)
    
    plot(cciValue)
    plot(rmaValue, color=color.orange)
    
  • 如果我们的脚本不需要将CCI作为一个单独的值来使用,我们也可以将 ta.cci() 直接放在 ta.rma() 内部,这样可以创建更紧凑的代码:
    // 获取12周期商品通道指数的10周期平均值
    rmaCciValue = ta.rma(ta.cci(close, 12), 10)
    
    plot(rmaCciValue, color=color.orange)
    

ta.rma() 的特性

  • 相对移动平均线并不是一种广为人知的移动平均线。但TradingView在两个流行的指标中使用了这种平均线:相对强弱指数(RSI)和平均真实波幅(ATR)。
  • 相对移动平均线所使用的加权因子是呈指数级递减的。这样,最近的K线拥有最高的权重,而更早的K线随着时间的推移,其权重会变得越来越小。
  • ta.rma() 函数可能会导致脚本重绘。为了计算RMA,Pine Script会使用到前一根K线的数据,这使得该平均线对脚本从哪一根K线开始计算非常敏感。由于TradingView的图表没有固定的日期范围,脚本的第一根K线并不总是相同的。(然而,在拥有数千根K线的图表上,这种效应极其微小。)

计算过程

TradingView通过以下公式计算相对移动平均线:

在代码层面,Pine Script按如下方式实现RMA:

pine_rma(source, length) =>
    alpha = 1 / length
    sum = 0.0
    sum := na(sum[1]) ? 
		 ta.sma(source, length) : 
		 alpha * source + (1 - alpha) * nz(sum[1])

plot(pine_rma(close, 15))

为方便起见,我们最好使用内置的 ta.rma() 函数,而不是这个自定义函数。此外,由于TradingView在后台执行的优化,内置的 ta.rma() 函数也可能运行得更高效。

脚本范例

让我们看看一个完整的脚本如何使用相对移动平均线(RMA)。下方的指标会计算两条这样的平均线,它们都基于收盘价,周期长度分别为10和40。

我们将这两条RMA以实线的形式绘制出来,然后比较当前价格与这些平均线的关系来判断市场趋势。基于这个结果,我们为图表上的价格K线赋予特定的颜色。

该指标的完整代码如下:

//@version=5
indicator(title="Relative Moving Average example", overlay=true)

// 输入选项
averageData = input.source(close, title="Average Data Source")

fastLength = input.int(10, title="Fast Average Length")
slowLength = input.int(40, title="Slow Average Length")

// 计算相对移动平均线
fastAverage = ta.rma(averageData, fastLength)
slowAverage = ta.rma(averageData, slowLength)

// 绘制平均线
plot(fastAverage, color=#FFC87C, title="Fast RMA")
plot(slowAverage, color=#B19CD9, title="Slow RMA")

// 用一个有色的K线显示移动平均线趋势
barColour = if close > fastAverage and fastAverage > slowAverage
    color.lime
else if fastAverage > slowAverage
    color.green
else if close < fastAverage and fastAverage < slowAverage
    color.red
else if fastAverage < slowAverage
    color.maroon
else
    color.orange

barcolor(barColour)

我们以 indicator() 函数开始,用于命名该脚本,并使用 overlay 将指标叠加显示在主图的交易品种之上。

然后,我们创建了三个输入项。第一个是数据源输入选项(input.source()),用于指定移动平均线的计算数据。另外两个输入是整数输入(input.int()),它们用于设置相对移动平均线的周期长度。

接下来,我们计算这些平均线:

// 计算相对移动平均线
fastAverage = ta.rma(averageData, fastLength)
slowAverage = ta.rma(averageData, slowLength)

第一个 ta.rma() 调用计算快速平均线。该函数处理 averageData 输入变量,该变量默认持有交易品种的收盘价。其周期长度由 fastLength 设定,该输入变量的初始值为10。

我们以类似的方式计算第二条相对移动平均线。我们再次调用 ta.rma() 并让它处理 averageData 值。对于其周期长度,我们使用 slowLength 输入变量,其标准值为40。

计算完平均线后,脚本继续执行其他任务。首先,它用 plot() 函数绘制两条RMA。快线显示为十六进制颜色值 #FFC87C(黄玉色),慢线则使用 #B19CD9(淡柔和紫色)。我们没有设置绘图类型,所以Pine Script默认将它们创建为常规的线图。

然后,一个级联 if 语句用于判断要使用哪种K线颜色。当收盘价高于快线,且快线高于慢线时,代码选择石灰绿(color.lime)。如果只是快线高于慢线,我们将使用绿色(color.green)。

如果快线不高于慢线,我们检查其他条件。如果收盘价低于快线,且快线低于慢线,我们使用红色(color.red)。如果只是快线低于慢线,我们则选用栗色(color.maroon)。万一两条平均线的值相同,我们使用橙色(color.orange)。

该指标的最后一行代码让 barcolor() 函数将选择的颜色应用到交易品种的价格K线上。

在图表上,快慢相对移动平均线显示为实线。K线的颜色则表明了价格与这些平均线的关系:

总结

  • ta.rma() 函数用于计算相对移动平均线(RMA)。
  • 该函数需要两样东西:一个要计算的数值序列,以及一个以K线数量为单位的周期长度。

EMA和RMA有何不同

TradingView的指数移动平均线(EMA)和相对移动平均线(RMA)的计算方式几乎完全相同,但它们在一个方面有所不同。让我们来仔细看看这两种移动平均线有何可比之处。

公式比较

要了解为什么EMA和RMA非常相似,让我们先看看它们的计算公式。这也揭示了它们唯一的不同之处。

TradingView按如下方式计算指数移动平均线(EMA):

EMA = alpha * price + (1 - alpha) * EMA[1]

而对于相对移动平均线(RMA),TradingView使用以下公式:

RMA = alpha * source + (1 - alpha) * RMA[1]

可以看出,两个公式非常相似。它们唯一的区别在于 alpha 变量。让我们来看看这个变量是怎么回事。

Alpha 值比较

EMA和RMA都在其公式中使用了一个 alpha 变量。这个变量决定了最新的价格能获得多大的权重,它说明了最后一个值对整个移动平均线的值有多大的影响。

EMA通过 2 / (length + 1) 来计算 alpha。而RMA则使用 1 / length。这使得RMA的 alpha 值大约只有EMA的一半。

为了更好地看清它们的差异,让我们来比较一下不同移动平均线周期长度下的 alpha 值:

周期长度 EMA alpha 最新价格权重 RMA alpha 最新价格权重
5 0.333 33.3% 0.200 20.0%
10 0.182 18.2% 0.100 10.0%
15 0.125 12.5% 0.067 6.7%
20 0.095 9.5% 0.050 5.0%
25 0.077 7.7% 0.040 4.0%
30 0.065 6.5% 0.033 3.3%
35 0.056 5.6% 0.029 2.9%
40 0.049 4.9% 0.025 2.5%

对于从5到40根K线的任何移动平均线长度,上表都显示出EMA使用的 alpha 值比RMA更高。那么,这意味着什么呢?

EMA和RMA都是通过取前一根K线的平均值,并结合当前K线的值来计算它们的平均值的。平均线使用多少当前值,取决于 alpha 的大小。

由于EMA的 alpha 值比RMA更高,因此EMA会给予最新的价格更大的权重。事实上,EMA使用的权重几乎可以是RMA的两倍(见上表)。

其结果是,EMA对价格变化的响应更快,因为它当前的值比RMA使用了更多的近期数据。

公式示例

让我们通过一个实例来让上面的内容更具体。假设我们有一个40周期的移动平均线,其前一根K线的值为 26.00。现在股票价格上涨并收盘于 26.50。基于这些变量,EMARMA 的值分别是多少?

当前 EMA 的值为 26.0256

RMA为26.0125:

这些公式揭示了两件有趣的事情:

  • 对于相同的移动平均线周期长度,EMA给予最新价格5.1%的权重,并使用前一根K线值的94.87%。然而,RMA只给予最新值2.5%的权重(并使用旧值的97.5%)。这使得最新价格对于RMA的重要性只有一半。
  • 因为EMA给予最后一个值更多的重要性,所以它在响应更高的收盘价时增长得更快。两条移动平均线在前一根K线上的值都是26.00。当股票收盘价走高时,EMA增加到26.025,而RMA的增幅则略小,为26.0125。

由于为最后一个值分配了更多的权重,EMA对价格方向变化的响应比RMA更快。其缺点是,当市场横盘整理时,EMA会比RMA产生更多的噪音。

脚本范例

让我们也用代码来进行比较。下方的指标会绘制一条指数移动平均线和一条相对移动平均线,两者使用相同的数据和周期长度。我们让代码找出收盘价与EMA或RMA发生交叉的位置。

当两条平均线在同一根K线上都产生信号时,我们用绿色背景来显示这个被确认的信号。如果价格只与RMA发生交叉,而没有与EMA交叉,我们使用蓝色背景。而当只有EMA交叉信号,而没有RMA交叉时,我们则将K线背景涂成橙色。这些不同的颜色可以快速地显示出哪个信号先出现。

该指标的完整代码如下:

//@version=5
indicator(title="RMA versus EMA", overlay=true)

// 输入项
avgData   = input.source(close, title="Average Data Source")
emaLength = input.int(20, title="EMA Length")
rmaLength = input.int(20, title="RMA Length")

// 用相同的数据和长度计算两条移动平均线
emaValue = ta.ema(avgData, emaLength)
rmaValue = ta.rma(avgData, rmaLength)

// 在图表上绘制两条平均线
plot(rmaValue, color=color.blue, linewidth=2, title="RMA")
plot(emaValue, color=color.orange, linewidth=2, title="EMA")

// 查看价格是否与移动平均线发生交叉
rmaCross = ta.cross(close, rmaValue)
emaCross = ta.cross(close, emaValue)

// 当两条平均线在同一K线上都有交叉信号时,
// 将背景设为绿色。否则,当只有一个触发时,
// 将背景设为与该平均线的绘图颜色相同。
backgroundColour = if rmaCross and emaCross
    color.new(color.green, 75)
else if rmaCross
    color.new(color.blue, 80)
else if emaCross
    color.new(color.orange, 80)

bgcolor(backgroundColour)

我们首先用 indicator() 函数配置该指标,用于命名脚本并将其放置在主图的交易品种之上。

然后,我们创建了三个输入项。第一个是数据源输入选项(input.source()),用于配置移动平均线的计算数据。另外两个整数输入(input.int())则用于设置EMA和RMA的周期长度。

接着,我们计算这两条移动平均线:

// 用相同的数据和长度计算两条移动平均线
emaValue = ta.ema(avgData, emaLength)
rmaValue = ta.rma(avgData, rmaLength)

ta.ema() 函数计算指数移动平均线。它处理 avgData 输入变量,该变量默认为收盘价。其周期长度是 emaLength 输入变量,标准值为20。

为了获取相对移动平均线,我们调用 ta.rma() 函数。这个函数同样处理 avgData 变量,其周期长度为 rmaLength,该输入变量的周期也为20。

在计算完平均线后,plot() 函数将它们都显示在图表上。EMA显示为橙色(color.orange),而RMA则使用蓝色(color.blue)。

接下来,ta.cross() 函数检查K线的收盘价是否与RMA发生上穿或下穿。然后,该函数再次检查是否与EMA发生了这样的交叉。

我们使用一个级联 if 语句来评估这些交叉的结果,以决定使用哪种背景颜色。首先,我们检查是否两条均线同时发生交叉(and)。如果是,我们使用一个透明的绿色(color.green)作为背景色。

如果没有同时的信号,我们检查是否只有RMA产生了信号。如果是这种情况,我们选择蓝色作为背景(与RMA线的颜色相同)。否则,第三个 if 条件会检查是否有EMA信号。如果有,我们使用EMA线的颜色(橙色)作为背景。

然后,在代码的最后一行,bgcolor() 函数将选择的颜色应用到图表的背景上。

图表示例

以上指标在图表上的效果如下:

EMA显示为一条橙色线,而RMA使用一条蓝色线。我们直接看到EMA比RMA响应更快。但让我们也考虑一下信号。

图表以一个绿色背景信号开始,那是一根EMA和RMA都同时产生信号的K线。

在图表的中部有一个橙色背景,EMA在那里产生了一个信号,而RMA没有。下一根K线有一个蓝色背景:RMA触发了一个信号(但EMA没有)。所以在这里,RMA的响应晚了一根K线。

图表的右边部分首先有另一个橙色背景(EMA)。这次过了三根K线,RMA才也产生它的信号(蓝色背景)。

由此可以看出,EMA比RMA响应更快。你可以亲自试用该指标,体验不同的设置如何改变脚本的信号。

总结

  • TradingView的指数移动平均线(EMA)和相对移动平均线(RMA)的公式非常相似。
  • 它们唯一的区别在于它们给予最新数值多大的权重。EMA可以给予该值两倍于RMA的重要性。
  • 这使得EMA对价格变化的响应更快。(但其结果是,也多了一点噪音。)
赞(0)
未经允许不得转载:图道交易 » Pine Script(135):赫尔均线HMA、相对均线RMA及两者与EMA的区别
分享到

评论 抢沙发

登录

找回密码

注册