Skip to content

Latest commit

 

History

History
309 lines (221 loc) · 13.7 KB

Objects.md

File metadata and controls

309 lines (221 loc) · 13.7 KB

对象

提示:

此页面包含高级材料。如果您是一名初级 Pine Script™ 程序员,我们建议您在冒险之前熟悉其他更易于使用的 Pine Script™ 功能。

Pine Script™ 对象是用户定义类型(UDT) 的实例。它们相当于包含称为fields的部分的变量,每个变量都能够保存各种类型的独立值。

有经验的程序员可以将 UDT 视为无方法类。它们允许用户创建自定义类型,在一个逻辑实体下组织不同的值。

在创建对象之前,必须定义其类型。类型系统页面的用户定义类型部分 解释了如何执行此操作。

让我们定义一个pivotPoint类型来保存枢轴信息:

type pivotPoint
    int x
    float y
    string xloc = xloc.bar_time

注意:

  • 我们使用type关键字来声明 UDT 的创建。
  • 我们将新的 UDT 命名为pivotPoint
  • 在第一行之后,我们创建一个包含每个字段的类型和名称的本地块。
  • x字段将保存枢轴的 x 坐标。它被声明为“int”,因为它将保存“int”类型的时间戳或条形索引。
  • y是一个“浮动”,因为它将保持枢轴的价格。
  • xloc``x是一个字段,用于指定xloc.bar_index 或 xloc.bar_time单位。我们 使用运算符将其默认值设置为xloc.bar_time。当从该 UDT 创建对象时,其字段将设置为该值。=``xloc

现在我们的pivotPointUDT 已定义,我们可以继续从中创建对象。我们使用 UDT 的new()内置方法创建对象。要从 UDT 创建新foundPoint对象pivotPoint,我们使用:

foundPoint = pivotPoint.new()

我们还可以使用以下命令为创建的对象指定字段值:

foundPoint = pivotPoint.new(time, high)

或者等价的:

foundPoint = pivotPoint.new(x = time, y = high)

此时,该foundPoint对象的字段将包含创建时内置的 时间x值 ,将包含high值 ,并且该字段将包含其默认值 xloc.bar_time ,因为创建时没有为其定义值。目的。y``xloc

还可以通过使用以下内容声明对象名称创建对象占位符 :

pivotPoint foundPoint = na

此示例显示检测到高枢轴的标签。枢轴legsInput在出现后会被检测到,因此我们必须绘制过去的标签,以便它出现在枢轴上:

//@version=5
indicator("Pivot labels", overlay = true)
int legsInput = input(10)

// Define the `pivotPoint` UDT.
type pivotPoint
    int x
    float y
    string xloc = xloc.bar_time

// Detect high pivots.
pivotHighPrice = ta.pivothigh(legsInput, legsInput)
if not na(pivotHighPrice)
    // A new high pivot was found; display a label where it occurred `legsInput` bars back.
    foundPoint = pivotPoint.new(time[legsInput], pivotHighPrice)
    label.new(
      foundPoint.x,
      foundPoint.y,
      str.tostring(foundPoint.y, format.mintick),
      foundPoint.xloc,
      textcolor = color.white)

请注意上面示例中的这一行:

foundPoint = pivotPoint.new(time[legsInput], pivotHighPrice)

也可以使用以下形式编写:

pivotPoint foundPoint = na
foundPoint := pivotPoint.new(time[legsInput], pivotHighPrice)

当使用varvarip创建对象时,这些关键字适用于该对象的所有字段:

//@version=5
indicator("")
type barInfo
    int i = bar_index
    int t = time
    float c = close

// Created on bar zero.
var firstBar = barInfo.new()
// Created on every bar.
currentBar = barInfo.new()

plot(firstBar.i)
plot(currentBar.i)

可以使用:=重新赋值运算符更改对象字段的值 。

我们前面的例子中的这一行:

foundPoint = pivotPoint.new(time[legsInput], pivotHighPrice)

可以使用以下方式编写:

foundPoint = pivotPoint.new()
foundPoint.x := time[legsInput]
foundPoint.y := pivotHighPrice

Pine Script™ 集合(数组矩阵映射)可以包含对象,允许用户向其数据结构添加虚拟维度。要声明对象集合,请将 UDT 名称传递到其类型模板中。

此示例声明一个空数组,该数组将保存pivotPoint用户定义类型的对象:

pivotHighArray = array.new<pivotPoint>()

要将变量的类型显式声明为用户定义类型数组矩阵映射,请使用集合的 type 关键字,后跟其类型模板。例如:

var array<pivotPoint> pivotHighArray = na
pivotHighArray := array.new<pivotPoint>()

让我们利用所学到的知识来创建一个检测高枢轴点的脚本。该脚本首先将历史数据透视表信息收集到一个 数组中。然后,它循环遍历最后一个历史柱上的数组,为每个枢轴创建一个标签,并用线连接枢轴:

../_images/Objects-CollectingObjects-1.png

//@version=5
indicator("Pivot Points High", overlay = true)

int legsInput = input(10)

// Define the `pivotPoint` UDT containing the time and price of pivots.
type pivotPoint
    int openTime
    float level

// Create an empty `pivotPoint` array.
var pivotHighArray = array.new<pivotPoint>()

// Detect new pivots (`na` is returned when no pivot is found).
pivotHighPrice = ta.pivothigh(legsInput, legsInput)

// Add a new `pivotPoint` object to the end of the array for each detected pivot.
if not na(pivotHighPrice)
    // A new pivot is found; create a new object of `pivotPoint` type, setting its `openTime` and `level` fields.
    newPivot = pivotPoint.new(time[legsInput], pivotHighPrice)
    // Add the new pivot object to the array.
    array.push(pivotHighArray, newPivot)

// On the last historical bar, draw pivot labels and connecting lines.
if barstate.islastconfirmedhistory
    var pivotPoint previousPoint = na
    for eachPivot in pivotHighArray
        // Display a label at the pivot point.
        label.new(eachPivot.openTime, eachPivot.level, str.tostring(eachPivot.level, format.mintick), xloc.bar_time, textcolor = color.white)
        // Create a line between pivots.
        if not na(previousPoint)
            // Only create a line starting at the loop's second iteration because lines connect two pivots.
            line.new(previousPoint.openTime, previousPoint.level, eachPivot.openTime, eachPivot.level, xloc = xloc.bar_time)
        // Save the pivot for use in the next iteration.
        previousPoint := eachPivot

在 Pine 中,对象是通过引用分配的。当现有对象分配给新变量时,两者都指向同一个对象。

在下面的示例中,我们创建一个pivot1对象并将其x字段设置为 1000。然后,我们声明一个pivot2包含对该pivot1对象的引用的变量,因此两者都指向同一个实例。因此,更改pivot2.x也会更改pivot1.x,因为两者都引用x同一对象的字段:

//@version=5
indicator("")
type pivotPoint
    int x
    float y
pivot1 = pivotPoint.new()
pivot1.x := 1000
pivot2 = pivot1
pivot2.x := 2000
// Both plot the value 2000.
plot(pivot1.x)
plot(pivot2.x)

要创建独立于原始对象的副本,在这种情况下我们可以使用内置copy()方法。

在此示例中,我们声明pivot2引用pivot1对象的复制实例的变量。现在,改变pivot2.x不会改变pivot1.x,因为它指的是x一个单独对象的字段:

//@version=5
indicator("")
type pivotPoint
    int x
    float y
pivot1 = pivotPoint.new()
pivot1.x := 1000
pivot2 = pivotPoint.copy(pivot1)
pivot2.x := 2000
// Plots 1000 and 2000.
plot(pivot1.x)
plot(pivot2.x)

需要注意的是,内置copy()方法会生成对象的浅表副本。如果对象具有特殊类型的字段 (arraymatrixmaplinelinefillboxpolylinelabeltableChart.point),则该对象的浅拷贝中的这些字段将指向与该对象相同的实例。原来的。

在下面的示例中,我们定义了一个InfoLabel类型,其中一个字段为标签。该脚本实例化对象shallow的副本parent,然后调用用户定义的 set() 方法来更新每个对象的infolbl字段。由于lbl两个对象的字段都指向同一标签实例,因此任一对象中此字段的更改都会影响另一个对象:

//@version=5
indicator("Shallow Copy")

type InfoLabel
    string info
    label  lbl

method set(InfoLabel this, int x = na, int y = na, string info = na) =>
    if not na(x)
        this.lbl.set_x(x)
    if not na(y)
        this.lbl.set_y(y)
    if not na(info)
        this.info := info
        this.lbl.set_text(this.info)

var parent  = InfoLabel.new("", label.new(0, 0))
var shallow = parent.copy()

parent.set(bar_index, 0, "Parent")
shallow.set(bar_index, 1, "Shallow Copy")

要生成对象的深层副本,并使其所有特殊类型字段都指向独立实例,我们还必须显式复制这些字段。

在这个例子中,我们定义了一个deepCopy()方法来实例化一个新InfoLabel对象,其lbl字段指向原始字段的副本。对deep副本字段的更改lbl 不会影响该parent对象,因为它指向一个单独的实例:

//@version=5
indicator("Deep Copy")

type InfoLabel
    string info
    label  lbl

method set(InfoLabel this, int x = na, int y = na, string info = na) =>
    if not na(x)
        this.lbl.set_x(x)
    if not na(y)
        this.lbl.set_y(y)
    if not na(info)
        this.info := info
        this.lbl.set_text(this.info)

method deepCopy(InfoLabel this) =>
    InfoLabel.new(this.info, this.lbl.copy())

var parent = InfoLabel.new("", label.new(0, 0))
var deep   = parent.deepCopy()

parent.set(bar_index, 0, "Parent")
deep.set(bar_index, 1, "Deep Copy")

避免未来添加到 Pine Script™ 的命名空间与现有脚本中的 UDT 或对象名称发生冲突的潜在冲突;通常,UDT 和对象名称会影响语言的命名空间。例如,UDT 或对象可以使用内置类型的名称,例如 linetable

只有该语言的五种基本类型不能用于命名 UDT 或对象: intfloatstringboolcolor