外观
方法
约 4243 字大约 14 分钟
高级
注意
本页面包含高级内容。如果您是 Mine Script® 编程初学者,建议先熟悉其他更基础的 Mine Script 功能,再学习本部分内容。
简介
Mine Script 方法是与特定内置类型、用户自定义类型或枚举类型值关联的专用函数。它们在大多数场景下与常规函数行为相同,但提供了更简洁便捷的语法。用户可通过点符号语法在对应类型的变量上调用方法,其访问方式类似于访问 Mine Script 对象的字段。
内置方法
Mine Script 为所有特殊类型提供了内置方法,包括(array, matrix, map, line, linefill, box, polyline, label, 和 table)。这些方法为用户提供了一种更简洁的方式来调用针对这些类型的专用功能。
在脚本中使用这些特殊类型时,以下表达式:
<namespace>.<functionName>([paramName =] <objectName>, …)和:
<objectName>.<functionName>(…)这两种调用方式是等效的。例如,相比使用:
Mine Script®
已复制
要获取数组中指定索引的值,可以直接使用以下简洁语法:
Mine Script®
已复制
即可达到相同的效果。这种写法消除了用户引用函数命名空间的需要,因为在此上下文中get()是id的方法。
下面编写一个实际示例来演示如何使用内置方法代替函数:
以下脚本计算布林带,基于每n根K线采样一次指定数量的价格。它调用array.push()和array.shift()将sourceInput值排队通过sourceArray,然后调用array.avg()和array.stdev()计算sampleMean和sampleDev。接着脚本使用这些值计算highBand和lowBand,并将其与sampleMean一起绘制在图表上:

Mine Script®
已复制
让我们重写这段代码,改用方法(methods)而非内置函数。在这个版本中,我们将脚本中所有的array.*内置函数替换为等效的方法调用:
Mine Script®
已复制
请注意:
- 我们调用数组方法时使用的是
sourceArray.*而非引用数组命名空间 array - 调用方法时无需包含
sourceArray作为参数,因为这些方法已隐含引用该对象
用户自定义方法
Mine Script允许用户为任何内置类型或用户自定义类型的对象定义自定义方法。定义方法本质上与定义函数相同,但存在两个关键区别:
必须在函数名称前包含method关键字 必须显式声明签名中第一个参数的类型,因为它表示该方法将关联的对象类型
[export] method <functionName>(<paramType> <paramName> [= <defaultValue>], …) =>
<functionBlock>让我们将用户自定义方法应用到之前的布林带示例中,将操作封装到全局作用域之外,从而简化代码并提高复用性。参考示例中的以下部分:
Mine Script®
已复制
我们首先定义一个简单的方法,通过单次调用在数组中实现值排队操作。
该maintainQueue()方法在takeSample条件为真时,对srcArray调用push()和shift()方法,并返回处理后的数组对象:
Mine Script®
已复制
请注意:
- 正如用户自定义函数一样,我们使用
@function编译器注解来记录方法描述。
现在,我们可以在示例中用sourceArray.maintainQueue()替换sourceArray.push()和sourceArray.shift()调用:
Mine Script®
已复制
从此处开始,我们将通过定义一个方法进一步简化代码,该方法在其范围内处理所有布林带计算:
该 calcBB() 方法在 calculate 条件为真时,调用 srcArray 的 avg() 和 stdev() 方法来更新均值(mean)和标准差(dev)值。此方法使用这些值返回一个包含基础值(basis)、上轨(upper band)和下轨(lower band)的元组:
Mine Script®
已复制
通过这个方法,我们现在可以从全局作用域中移除布林带计算逻辑,显著提升代码的可读性和可维护性:
Mine Script®
已复制
请注意:
- 我们没有在全局作用域使用
if代码块,而是定义了newSample变量,该变量仅在每n根K线上为真。maintainQueue()和calcBB()方法分别使用此值作为它们的takeSample和calculate参数。 - 由于
maintainQueue()方法返回其引用的对象,因此我们能够在同一行代码中调用calcBB()方法,因为这两个方法都适用于array<float>类型的实例。
以下是应用了用户自定义方法后完整脚本示例的呈现:
Mine Script®
已复制
方法重载
用户定义的方法可以覆盖和重载具有相同标识符的现有内置方法和用户定义方法。此功能允许用户在同一方法名下定义与不同参数签名相关联的多个例程。
作为一个简单示例,假设我们想定义一个方法来识别变量的类型。由于我们必须显式指定与用户定义方法关联的对象类型,因此需要为我们希望它识别的每种类型定义重载。
下面,我们定义了一个getType()方法,该方法返回变量类型的字符串表示,并为五种基本类型定义了重载:
Mine Script®
已复制
现在我们可以使用这些重载方法来检查变量类型。该脚本使用str.format()将五个不同变量调用getType()方法的结果格式化为单个字符串,然后通过内置的set_text()方法在标签lbl中显示结果:

Mine Script®
已复制
请注意:
每个变量的基础类型决定了编译器将使用哪个getType()重载方法。 当变量为na时,该方法会在输出字符串后追加"(na)"以标记其为空值。
高级应用示例
让我们运用所学知识构建一个脚本,用于估算数组中元素的累积分布(即数组中小于等于任意给定值的元素比例)。
实现这一目标有多种方法。在本示例中,我们将首先定义一个替换数组元素的方法,这将帮助我们统计特定值范围内元素的出现频率。
以下是针对array<float>实例重载的内置fill()方法。该重载方法将srcArray中处于lowerBound和upperBound之间的元素替换为innerValue,并将范围外的所有元素替换为outerValue:
Mine Script®
已复制
通过这个方法,我们可以按数值范围过滤数组,生成一个统计出现次数的数组。例如以下表达式:
Mine Script®
已复制
将 srcArray 对象复制后,将 min 和 val 之间的所有元素替换为 1.0,然后将所有大于 val 的元素替换为 0.0。这样,就很容易估算出在 val 处的累积分布函数输出值,因为它就是结果数组的平均值:
Mine Script®
已复制
请注意以下几点:
- 编译器仅当用户在调用时提供了
innerValue、outerValue、lowerBound和upperBound参数时,才会使用此fill()重载方法,而非内置方法。 - 如果
lowerBound或upperBound为na(无效值),则在填充范围过滤时,该值会被忽略。 - 之所以能在同一行代码中连续调用
copy()、fill()和avg(),是因为前两个方法返回的是array<float>实例(支持链式调用)。
现在,我们可以利用这一点来定义一个计算经验分布值的方法。以下 eCDF() 方法会从 srcArray 的累积分布函数中估算出一系列均匀间隔的递增阶梯值,并将结果存入 cdfArray:
Mine Script®
已复制
最后,为了确保我们的 eCDF() 方法能够正确处理包含极小值和极大值的数组,我们将定义一个用于数组归一化的方法。
这个 featureScale() 方法利用数组的 min() 和 range() 方法,生成 srcArray 的归一化副本。我们将在调用 eCDF() 方法之前,使用该方法对数组进行归一化处理:
Mine Script®
已复制
需要注意的是:
- 除以零处理:此方法未对除以零的情况进行特殊处理。如果
rng为0,数组元素的值将被设为na(无效值)。
下面的完整示例使用之前定义的 maintainQueue() 方法,将 sourceInput 值存入大小为 length 的 sourceArray 队列中,然后使用 featureScale() 方法对数组元素进行归一化处理,接着调用 eCDF() 方法获取分布在 n 个均匀间隔点上的估计值数组。最后,脚本调用用户自定义的 makeLabel() 函数,在图表右侧以标签形式显示估计值和价格:

Mine Script®
已复制