math.min():取多个数值中的最小值
通过 Pine Script 的 math.min() 函数,我们可以从多个数值中获取最小值 。
该函数的默认语法格式如下 :
math.min(number1, number2, ...)
number1 和 number2 是我们希望从中找出最小值的整数或浮点数。
三个点(...)表示:可以有任意数量的参数。因此,number3、number4 和 number5 都是可以的,甚至可以有更多。TradingView 并未在文档中说明参数的最大数量。在我的测试中,我可以给 math.min() 传入75个不同的值,脚本依然能快速计算且不报错。
math.min() 会返回两种可能的值之一:
- 一个整数或浮点值,代表所提供数值中的最小值。
- 或者是
na值。只要math.min()的参数中有一个为na,该函数就会返回na。
快速范例
我们经常使用 math.min() 来获取两个值中的较小者。比方说,我们想得到当前K线的收盘价(close)和前一根K线开盘价(open[1])之间的最低值。要获取这个最小值,我们可以像这样使用 math.min():
// 获取当前K线收盘价与上一根K线开盘价的最小值
closeOpenMin = math.min(close, open[1])
我们也可以给 math.min() 传入两个以上的参数。比方说,我们对当前收盘价和最近4个开盘价的最低值感兴趣,那么我们可以这样使用该函数:
// 获取当前K线收盘价与
// 最近四个开盘价的最低值
lowestCloseOpen = math.min(close, open, open[1], open[2], open[3])
math.min() 与 ta.lowest() 的对比
Pine Script 有两个可以返回最小值(最低值)的函数,它们是 math.min() 和 ta.lowest()。它们的区别如下:
ta.lowest()处理的是 单一变量或函数 的历史数据。它找出该数据在 最近指定数量的K线内 达到过的最低值。例如,通过ta.lowest()函数,我们可以得到20周期内的最低价,或者过去5根K线内的最低收盘价。math.min()返回的是 多个不同数值 之间的最小值。这些数值可以都只针对当前K线,也可以包含之前K线上的值。例如,通过math.min()函数,我们可以得到当前K线开盘价和收盘价的较低者,或者三条不同移动平均线中的最小值。
在某些情况下,我们可以任选 ta.lowest() 或 math.min()。当 math.min() 用于获取一个变量在过去几根K线上的最小值时,其用法就和 ta.lowest() 的作用相同。
例如,下面这两行代码会返回相同的值:
// 获取最近3根K线的最低收盘价
lowestClose = math.min(close, close[1], close[2])
// 或等效的写法:
lowestClose = ta.lowest(close, 3)
虽然 math.min() 可以获取一个变量在过去K线上的最小值,但为了这个目的,使用 ta.lowest() 函数通常更普遍(也更省事)。
math.min() 的特性
math.min() 从变量或函数结果中返回最小值,但该函数不能用于处理数组。要获取数组中的最小值,我们应该改用 array.min() 函数。
在 Pine Script 版本4及更早的版本中,math.min() 函数的名称是 min() 。除了名称变化外,其行为并未改变。
使用 math.min() 替代 if/else 语句
math.min() 的作用是评估并返回一组数中的最低值。这个功能我们有时会用 if 语句或 if/else 语句来实现。但如果我们选择使用 math.min(),我们的代码会变得更短,而且通常更易于阅读。
让我们来看一个例子。假设我们想获取当前收盘价和前一根K线最低价的较小值。使用 math.min() 的代码是:
minimumValue = math.min(close, low[1])
要用 if 语句实现相同的行为,则需要:
minimumValue = close
if low[1] < minimumValue
minimumValue := low[1]
而要用 if/else 语句得到相同的结果,代码如下:
float minimumValue = na
if close < low[1]
minimumValue := close
else
minimumValue := low[1]
如上所示,math.min() 需要敲的代码少得多,并且也减少了出错的可能性。
脚本范例
让我们看看脚本如何使用 math.min() 函数。下方的指标会绘制两条简单移动平均线(SMA)。我们使用 math.min() 来获取这两条平均线中的较低者。这条最低值线也会被绘制在图表上,举例来说,我们可以将这个值用作止损水平。
该指标的完整代码如下:
//@version=5
indicator(title="math.min() example script", overlay=true)
// 计算两条移动平均线
fastSMA = ta.sma(close, 20)
slowSMA = ta.sma(close, 45)
// 获取两条平均值中的最低值
minAverage = math.min(fastSMA, slowSMA)
// 在图表上绘制两条平均线及其最小值
plot(series=fastSMA, color=color.fuchsia, title="Fast SMA")
plot(series=slowSMA, color=color.teal, title="Slow SMA")
plot(series=minAverage, color=color.orange, linewidth=3,
title="Lowest Average")
首先,我们使用 indicator() 函数来设置指标的属性,用于命名该脚本,并使其显示在与主图交易品种相同的图表区域内。
然后,ta.sma() 函数计算两条简单移动平均线。第一条的周期长度为20根K线,另一条则使用45为周期。两者都基于交易品种的收盘价(close)进行计算。我们将它们的值分别存储在 fastSMA 和 slowSMA 变量中。
接下来,我们将这两个变量传入 math.min() 函数,这会让我们得到两条平均线中的最低值。我们将这个最小值赋给 minAverage 变量。
之后,Pine Script 的 plot() 函数创建了三个绘图。前两个用于显示 fastSMA 和 slowSMA 变量。第一条以紫红色(color.fuchsia)显示,另一条则以青色(color.teal)出现。由于我们没有明确指定绘图类型,Pine Script 会默认将它们创建为常规的线图。
最后,我们用 plot() 绘制两条平均线的最小值(minAverage)。这同样会创建一个常规的线图,并以橙色(color.orange)显示。因为我们在每一根K线上都获取了最小值,所以最终会得到一条在每根K线上都有对应数值的连续线。
当该脚本在图表上运行时,它会绘制两条移动平均线以及它们的橙色最小值线。在一个苹果公司(Apple)的日线图上,它看起来是这样的:
总结
math.min()函数会从其接收的多个整数或浮点数参数中,返回数值最小的那个。- 如果所提供的参数中有一个是
na(不可用),那么math.min()的返回值也会是na。
math.max():取多个数值中的最大值
通过 Pine Script 的 math.max() 函数,我们可以从多个数值中获取最大值 。
该函数的标准语法格式如下 :
math.max(number1, number2, ...)
number1 和 number2 是我们希望从中找出最大值的整数或浮点数。
三个点(...)表示:可以有任意数量的参数。因此,number3、number4 和 number5 都是可以的,甚至更多也完全没问题。TradingView 并未指明参数的最大数量。在我测试 math.max() 时,我可以给函数传入75个不同的值,脚本依然能快速执行且不报错。
math.max() 会返回两种可能的值之一:
- 一个整数或浮点值,代表所提供参数中的最大值。
- 或者是
na值。当math.max()的参数中有一个(或多个)为na时,就会返回这个值。
快速范例
我们经常使用 math.max() 来获取两个值中的较大者。比方说,我们想得到当前K线的收盘价(close)和前一根K线开盘价(open[1])之间的最高值。要获取这个最大值,我们可以像这样使用 math.max():
// 获取当前K线收盘价与上一根K线开盘价的最大值
closeOpenMax = math.max(close, open[1])
math.max() 可以处理远不止两个数值。比方说,我们想要当前收盘价和最近4个开盘价的最高值。为此,我们可以这样使用该函数:
// 获取当前K线收盘价与
// 最近四个开盘价的最高值
highestCloseOpen = math.max(close, open, open[1], open[2], open[3])
math.max() 与 ta.highest() 的对比
有两个 Pine Script 函数可以返回最大值(最高值),它们是 math.max() 和 ta.highest()。它们的区别如下:
ta.highest()处理的是 单一变量或函数 的历史数据。它返回该数据在 最近指定数量的K线内 达到过的最高值。例如,通过ta.highest()函数,我们可以得到20周期内的最高价,或者过去10根K线内的最大成交量。math.max()返回的是 多个不同数值 之间的最大值。这些数值可以都只针对当前K线,也可以包含之前K线上的值。例如,通过math.max()函数,我们可以得到当前K线开盘价和收盘价的较高者,或者三条不同移动平均线中的最大值。
在某些情况下,我们可以任选 ta.highest() 或 math.max()。当 math.max() 用于获取一个变量在过去几根K线上的最大值时,其用法就和 ta.highest() 的作用相同。
例如,下面这两行代码会返回相同的值:
// 获取最近3根K线的最高收盘价
highestClose = math.max(close, close[1], close[2])
// 或等效的写法:
highestClose = ta.highest(close, 3)
尽管 math.max() 可以获取一个变量在过去K线上的最大值,但使用 ta.highest() 函数来替代通常更普遍,也更省事。
math.max() 的特性
math.max() 从多个变量或函数结果中返回最大值。然而,它不能用于处理 Pine Script 数组。要获取数组中的最大值,我们应该改用 array.max() 函数。
在 Pine Script 版本4及更早的版本中,math.max() 函数的名称是 max() 。除了名称变化外,其行为并未改变。
使用 math.max() 替代 if/else 语句
math.max() 的作用是评估并返回一组数中的最高值。这个功能 if 语句和 if/else 语句也能做到。但如果我们改用 math.max(),我们的代码会更短,而且通常更易于阅读。
让我们来看一个例子。假设我们想获取当前收盘价和前一根K线最高价的较大值。使用 math.max() 来实现的代码是:
maximumValue = math.max(close, high[1])
要用 if 语句实现相同的功能,则需要:
maximumValue = close
if high[1] > maximumValue
maximumValue := high[1]
而要用 if/else 语句得到相同的结果,代码如下:
float maximumValue = na
if close > high[1]
maximumValue := close
else
maximumValue := high[1]
如这些示例所示,math.max() 需要敲的代码少得多,该函数也减少了编程出错的可能性。
脚本范例
让我们来探究一个脚本如何使用 math.max() 函数。下方的指标会绘制两条指数移动平均线(EMA)。我们使用 math.max() 来获取这两条平均线中的较高者。这条最大值线也会被绘制在图表上,举例来说,我们可以将其用作买入触发条件或空头止损水平。
该指标的完整代码如下:
//@version=5
indicator(title="math.max() example script", overlay=true)
// 计算两条移动平均线
fastEMA = ta.ema(close, 12)
slowEMA = ta.ema(close, 24)
// 获取两条平均值中的最大值
maxAverage = math.max(fastEMA, slowEMA)
// 在图表上绘制两条平均线及其最大值
plot(series=fastEMA, color=color.fuchsia, title="Fast EMA")
plot(series=slowEMA, color=color.teal, title="Slow EMA")
plot(series=maxAverage, color=color.orange, linewidth=3,
title="Highest Average")
首先,我们使用 Pine Script 的 indicator() 函数来配置指标,用于命名该脚本并将其叠加显示在主图的交易品种上。
然后,ta.ema() 函数计算两条指数移动平均线。第一条的周期为12,另一条则使用24根K线。两者都基于交易品种的收盘价(close)进行计算。我们将它们的值分别存储在 fastEMA 和 slowEMA 变量中。
接下来,我们获取这两个变量中的最大值。因此我们将它们传入 math.max() 函数。返回的最大值被我们存储在 maxAverage 变量中。
之后,plot() 函数创建了三个绘图。第一个用于显示快速平均线(fastEMA),颜色为紫红色(color.fuchsia)。第二个显示慢速平均线(slowEMA),颜色为青色(color.teal)。由于我们没有设置绘图类型,Pine Script 会默认将它们创建为常规的线图。
第三个也是最后一个绘图是两条平均线的最大值(maxAverage)。这条线以橙色(color.orange)显示,并且比正常线更粗(linewidth=3)。
当我们将该脚本添加到图表时,它会绘制两条移动平均线以及它们的最大值。在一个苹果公司(Apple)的日线图上,它看起来是这样的:
总结
math.max()函数会从其接收的多个整数或浮点数参数中,返回数值最大的那个。- 如果所提供的参数中有一个是
na(不可用),那么math.max()的返回值也会是na。
将数值限制在指定范围内
TradingView 的指标和策略通过计算各种数值来分析图表。但我们并非总是希望一个数值可以取任何可能的值。有时,为一个数值设定一个范围限制会达到最佳效果。
在 Pine Script 中,有三种方法可以限制一个数值的范围:
- 设置一个最小值。
- 设置一个最大值。
- 设置一个从最小到最大的范围。
下面我们来看看如何用代码实现这些限制。
设置一个最小值
当我们为一个数值设定一个最小值时,我们实际上是为其值设定了一个下限。这样,该数值将永远等于或高于某个特定水平,而不能低于该最小值。
自定义函数
下面的这个自定义函数 ApplyMin() 可以为一个给定的数值应用一个最小值下限:
// ApplyMin() 为指定的值应用给定的最小值范围。
// 当值高于最小值时,返回原值不变。
ApplyMin(value, minimum) =>
math.max(minimum, value)
ApplyMin() 函数有两个参数。value 指的是我们希望限制其最小范围的数值,而 minimum 则用于设定可接受的最低值应该是多少。
在函数内部,math.max() 函数会返回 value 和其定义的 minimum 这两者中的较大值。这使得该函数返回的新数值永远不会小于我们所指定的最小值。
快速范例
让我们看看如何使用这个函数。比方说,我们想计算收盘价的变化,但不想得到负值。在这种情况下,我们可以像这样调用 ApplyMin():
// 计算单根K线的收盘价变化,最小值为0
closeChange = ApplyMin(0, close - close[1])
如果我们需要使用策略的净利润进行计算,但不希望使用低于250的值,我们可以这样使用 ApplyMin():
// 计算策略的净利润,最小值为250
netProfit = ApplyMin(250, strategy.netprofit)
我们也可以使用另一个变量或表达式作为最小值。
让我们假设我们使用平均真实波幅(ATR)来计算订单大小,但我们不希望使用小于15个 tick 的 ATR 值。在这种情况下,我们可以像这样调用 ApplyMin():
// 计算14周期的平均真实波幅(用于仓位大小),
// 但使用15个 tick 作为最小值
minimumAtr = ApplyMin(15 * syminfo.mintick, ta.atr(14))
脚本范例
下面的指标展示了我们如何在脚本中使用 ApplyMin() 函数。该代码计算单根K线的成交量变化,并通过自定义函数确保成交量变化值永远不会低于零。当我们绘制这些值时,便可以轻松识别出成交量有较大增长的K线。
该脚本的完整代码如下:
//@version=5
indicator(title="Minimum value example", format=format.volume)
// ApplyMin() 为指定的值应用给定的最小值范围。
// 当值高于最小值时,返回原值不变。
ApplyMin(value, minimum) =>
math.max(minimum, value)
// 计算单根K线的成交量差值,最小值为
// 0 (这样我们就不会绘制负的成交量变化)
volumeChange = ApplyMin(0, volume - volume[1])
// 用成交量变化值创建一个柱状图
plot(series=volumeChange, style=plot.style_columns, title="Volume change")
首先,我们使用 Pine Script 的 indicator() 函数来配置指标,用于命名该脚本,并将绘图值格式化为成交量数字,用 K 和 M 分别代表千和百万。
下一步,我们引入了上面讨论过的 ApplyMin() 函数。
然后,我们创建 volumeChange 变量,并使用 ApplyMin() 函数来限制其值。我们向该函数传入两个值:第一个是最小值(0),另一个是单根K线的成交量变化。为了得到这个变化值,我们用当前K线的成交量(volume)减去前一根K线的成交量(volume[1])。
plot() 函数随后在图表上显示成交量的变化。我们让 volumeChange 变量以柱状图(plot.style_columns)的形式显示。
当这个脚本在图表上运行时,它的绘图只显示成交量有正向变化的K线柱:
设置一个最大值
当我们为一个数值设定一个最大值时,我们实际上是为其值添加了一个上限。这使得该数值将永远等于或低于某个特定水平,其值再也不能超过给定的最大值。
自定义函数
下面的这个 ApplyMax() 自定义函数可以为一个给定的数值应用一个最大值上限:
// ApplyMax() 为指定的值应用给定的最大值范围。
// 当值低于最大值时,返回原值不变。
ApplyMax(value, maximum) =>
math.min(maximum, value)
这个 ApplyMax() 函数有两个参数。value 指的是我们希望限制其最大范围的数值,而 maximum 则用于设定可接受的最高值应该是多少。
在函数内部,math.min() 函数会返回 value 和其定义的 maximum 这两者中的较小值。这使得该函数返回的新数值永远不会多于我们所指定的最大值。
快速范例
让我们看看如何使用 ApplyMax() 函数。如果我们对单根K线的收盘价变化感兴趣,但又不要正值,我们可以像这样使用该函数:
// 计算单根K线的收盘价变化,最大值为0
// (这样,当绘制时,只会显示负值)
closeChange = ApplyMax(0, close - close[1])
再比如,我们通过一个输入来为一个动量震荡指标设定交叉水平,但不希望使用高于5的交叉水平。在这种情况下,我们可以这样使用 ApplyMax():
// 从一个输入选项决定动量指标的
// 上穿水平应该是多少,
// 并设置最大值为5
momCrossLevel = ApplyMax(5, crossLevelInput * 2)
当我们在计算仓位大小时,我们可能不希望交易超过500股。要实现交易1.5%的账户权益或不超过该限制,我们可以像这样调用 ApplyMax():
// 计算仓位大小,最大为500股
positionSize = ApplyMax(500, strategy.equity * 0.015)
最大值不必是一个字面值,我们也可以通过计算或使用一个变量来得到最大值。
比方说,我们的止损距离应该是前一根K线与当前K线低点之间的距离,但不能超过20个 tick。要实现这样的最大值限制,我们可以像这样使用 ApplyMax():
// 止损距离当前价的距离,
// 不使用超过20个 tick 的距离
stopDistance = ApplyMax(20 * syminfo.mintick, math.abs(low - low[1]))
脚本范例
让我们来探究一个脚本如何使用 ApplyMax() 函数。下方的指标计算单根K线的成交量变化,并通过 ApplyMax() 函数为其应用一个0的最大值。当绘图在图表上显示这些值时,它会凸显出那些成交量下降的K线。
该脚本的完整代码如下:
//@version=5
indicator(title="Maximum value example", format=format.volume)
// ApplyMax() 为指定的值应用给定的最大值范围。
// 当值低于最大值时,返回原值不变。
ApplyMax(value, maximum) =>
math.min(maximum, value)
// 计算单根K线的成交量差值,最大值为
// 0 (所以我们只对成交量下降的K线感兴趣)
volumeChange = ApplyMax(0, volume - volume[1])
// 用成交量变化值创建一个柱状图
plot(series=volumeChange, style=plot.style_columns, title="Volume change")
首先,我们调用 indicator() 函数来配置指标。这为脚本提供了一个名称,并使其绘图格式显示为成交量,用 K 代表千、M 代表百万。
然后,我们引入了上面讨论过的 ApplyMax() 函数。
接下来,我们计算单根K线的成交量变化,并使用 ApplyMax() 来限制其值。因此,在该函数内部,我们用当前K线的成交量(volume)减去上一根K线的成交量(volume[1])。我们传入 0 作为最大值,来告诉 ApplyMax() 不要返回高于零的值。我们将返回的值存入 volumeChange 变量。
然后,plot() 函数在图表上显示该变量。我们让单根K线的成交量差异以柱状图(plot.style_columns)的形式显示。
当该脚本在图表上运行时,没有任何成交量变化能够高于0这个最大值:
设置一个范围(从最小到最大值)
当我们为一个数值设定一个范围时,我们实际上是为其值同时添加了一个上限和一个下限。这样,该数值将永远等于或高于指定的最小值,但绝不会超过其最大值。
自定义函数
下面的这个自定义函数 ApplyRange() 可以为一个给定的数值应用一个最小值和最大值范围:
// ApplyRange() 为指定的值应用给定的最小值和最大值范围。
// 当值在最小-最大范围内时,返回原值不变。
ApplyRange(value, minimum, maximum) =>
math.min(math.max(value, minimum), maximum)
该函数有三个参数。value 是我们希望应用范围的数值。minimum 和 maximum 则定义了其可接受的最低和最高值应该是多少。
该函数的代码将 math.max() 函数嵌套在 math.min() 函数内部。让我们先看内层的 math.max()。这个函数会返回给定的数值或其最小值中的较大者,这就确保了结果不会低于我们设定的最小值。
然后,Pine Script 将 math.max() 的结果用于外层的 math.min() 函数。后者会返回给定的最大值或 math.max() 返回的结果中的较小值。通过这种方式,我们得到的值就不会高于设定的最大值。
由于这两层过滤,ApplyRange() 可能返回三种值:未经改变的原值、设定的最小值或设定的最大值。无论函数最终返回哪个值,这个数现在都被限制在了最小值和最大值之间。其结果是,我们从这个数值中移除了异常的离群值。
快速范例
让我们来探究一些例子。比方说,我们的脚本计算平均真实波幅(可能用于确定订单大小),但我们不希望 ATR 值过高或过低。要使用5的最小值和25的最大值,我们可以像这样调用 ApplyRange() 函数:
// 获取14周期的平均真实波幅 (ATR),最小值为
// 5个点,最大值为25个点。
atrValue = ApplyRange(ta.atr(14), 5, 25)
再假设,我们用账户权益的1%来计算仓位大小,但我们希望至少交易10股,且绝对不超过2,500股。要实现这个取值范围,我们可以这样使用 ApplyRange():
// 计算仓位大小,最小为10股
// 最大为2,500股。
positionSize = ApplyRange(0.01 * strategy.equity, 10, 2500)
我们也可以通过变量或计算来动态设定最小值和最大值。
比方说,我们想用最近的最高高点和最低低点来设定一个止盈目标的距离,但我们不希望目标距离小于20个 tick 或超过100个 tick。要得到该范围内的目标距离,我们可以这样做:
// 计算最近的价格范围
recentRange = ta.highest(high, 20) - ta.lowest(low, 20)
// 决定离当前价的盈利目标距离。但不要
// 将目标放置在超过100个 tick 或少于20个 tick 远的地方。
targetDistance = ApplyRange(recentRange, 20 * syminfo.mintick,
100 * syminfo.mintick)
脚本范例
让我们看看脚本如何使用 ApplyRange() 函数。下方的指标计算单根K线的成交量变化。为了不让异常的离群值扭曲图表,该脚本将成交量差异的范围限制在最小-10,000和最大10,000之间。
该脚本的完整代码如下:
//@version=5
indicator(title="Range (minimum-maximum) example", format=format.volume)
// ApplyRange() 为指定的值应用给定的最小值和最大值范围。
// 当值在最小-最大范围内时,返回原值不变。
ApplyRange(value, minimum, maximum) =>
math.min(math.max(value, minimum), maximum)
// 计算单根K线的成交量差值,但通过使用
// -10k 的最小值和 10k 的最大值来排除离群值
volumeChange = ApplyRange(volume - volume[1], -10000, 10000)
// 用一个柱状图显示有界的成交量变化
plot(series=volumeChange, style=plot.style_columns, title="Volume change")
首先,我们使用 indicator() 函数配置指标。它为脚本命名,并且 format.volume 值将绘图数值格式化为成交量,用 K 和 M 后缀分别代表千和百万。
然后,我们引入了上面讨论过的自定义 ApplyRange() 函数。
接下来,我们创建 volumeChange 变量,并使用 ApplyRange() 函数来限制其值。我们向该函数传入三个参数:第一个是单根K线的成交量变化,为此我们用当前K线的成交量(volume)减去前一根K线的成交量(volume[1]);第二个和第三个参数分别是-10000的最小值和10000的最大值。
然后,我们用 plot() 函数绘制该变量。这使得单根K线的成交量差异以柱状图(plot.style_columns)的形式显示。
当我们将该脚本添加到图表时,其成交量变化被整齐地限制在了-10k到10k的范围内:







