表格
介绍
表格是一种可用于将信息定位在脚本可视空间中的特定固定位置的对象。与 Pine Script™ 中绘制的所有其他图表或对象相反,表格并不锚定在特定的条形图上;它们漂浮在脚本的空间中,无论是在覆盖模式还是窗格模式中,在研究或策略中,与所查看的图表条形图或使用的缩放系数无关。
表格包含按列和行排列的单元格,与电子表格非常相似。表格的创建和填充分为两个不同的步骤:
- 表的结构和关键属性是使用 table.new()定义的,它返回一个表 ID,该 ID 充当指向表的指针,就像标签、行或数组 ID 一样。table.new () 调用将创建表对象,但不会显示它。
- 创建表格后,为了显示表格,必须对每个单元格使用一次 table.cell() 调用来填充表格。表格单元格可以包含文本,也可以不包含文本。第二步是定义单元格的宽度和高度。
可以使用设置函数更改先前创建的表的大多数属性
table.set_*()
。可以使用函数修改先前填充的单元格的属性table.cell_set_*()
。
通过将表格锚定到九个参考点之一,表格可以定位到指示器空间中:四个角或中点,包括中心。表格的定位是通过从其锚点扩展表格来实现的,因此锚定到 position.middle_right 参考点的表格 将通过从该锚点向上、向下和向左扩展来绘制。
有两种模式可用于确定表格单元格的宽度/高度:
- 默认自动模式使用列/行中最宽/最高的文本来计算单元格的宽度/高度。
- 显式模式允许程序员使用指标可用 x/y 空间的百分比来定义单元格的宽度/高度。
显示的表格内容始终代表表格的最后状态,因为它是在脚本最后一次执行时在数据集的最后一条柱上绘制的。与数据窗口或指标值中显示的值相反,表格中显示的变量内容不会随着脚本用户将光标移动到特定图表柱上而改变。因此,强烈建议始终将所有
table.*()
调用的执行限制在数据集的第一个或最后一个柱上。因此:
- 使用 var 关键字来声明表。
- 将所有其他调用都放在 if barstate.islast 块内。
一个脚本中可以使用多个表格,只要它们各自锚定在不同的位置即可。每个表格对象都通过其自己的 ID 进行标识。所有表格中单元格数量的限制取决于一个脚本中使用的单元格总数。
创建表
使用table.new()创建表格时 ,三个参数是必需的:表格的位置以及表格的列数和行数。另外五个参数是可选的:表格的背景颜色、表格外框的颜色和宽度以及所有单元格(外框除外)周围边框的颜色和宽度。除列数和行数之外的所有表格属性都可以使用设置函数进行修改: table.set_position()、 table.set_bgcolor()、 table.set_frame_color()、 table.set_frame_width()、 table.set_border_color() 和 table.set_border_width()。
可以使用 table.delete()删除表,并且可以使用 table.clear()有选择地删除其内容。
使用 table.cell()填充单元格时,必须为四个必需参数提供实参:单元格所属的表 ID、其列和行索引(使用从零开始的索引)以及单元格包含的文本字符串(可以为 null)。其他七个参数是可选的:单元格的宽度和高度、文本的属性(颜色、水平和垂直对齐、大小)以及单元格的背景颜色。可以使用 setter 函数修改所有单元格属性: table.cell_set_text()、 table.cell_set_width()、 table.cell_set_height()、 table.cell_set_text_color()、 table.cell_set_text_halign()、 table.cell_set_text_valign()、 table.cell_set_text_size() 和 table.cell_set_bgcolor()。
请记住,每次连续调用 table.cell() 都会重新定义所有单元格的属性,并删除 同一单元格上先前 调用table.cell()设置的所有属性。
将单个值放置在固定位置
让我们创建第一个表格,它将 ATR 的值放在图表的右上角。我们首先创建一个单元格表格,然后填充该单元格:
//@version=5
indicator("ATR", "", true)
// We use `var` to only initialize the table on the first bar.
var table atrDisplay = table.new(position.top_right, 1, 1)
// We call `ta.atr()` outside the `if` block so it executes on each bar.
myAtr = ta.atr(14)
if barstate.islast
// We only populate the table on the last bar.
table.cell(atrDisplay, 0, 0, str.tostring(myAtr))
注意:
- 我们 在使用table.new() 创建表时 使用var关键字。
- 我们使用 table.cell()填充if barstate.islast块内的单元格 。
- 填充单元格时,我们不指定
width
或height
。因此,单元格的宽度和高度将自动调整为其包含的文本。 - 我们在if
ta.atr(14)
块中输入之前 调用 ,以便它在每个柱上进行评估。如果我们 在if块内部 使用 ,该函数将无法正确评估,因为它将在数据集的最后一根柱上调用,而没有从之前的柱计算出必要的值。str.tostring(ta.atr(14))
让我们提高脚本的可用性和美观性:
//@version=5
indicator("ATR", "", true)
atrPeriodInput = input.int(14, "ATR period", minval = 1, tooltip = "Using a period of 1 yields True Range.")
var table atrDisplay = table.new(position.top_right, 1, 1, bgcolor = color.gray, frame_width = 2, frame_color = color.black)
myAtr = ta.atr(atrPeriodInput)
if barstate.islast
table.cell(atrDisplay, 0, 0, str.tostring(myAtr, format.mintick), text_color = color.white)
注意:
- 我们使用 table.new() 来定义背景颜色、框架颜色及其宽度。
- 当使用table.cell()填充单元格时 ,我们将文本设置为以白色显示。
- 我们将 format.mintick 作为第二个参数传递给 str.tostring() 函数,以将 ATR 的精度限制为图表的刻度精度。
- 我们现在使用输入来允许脚本用户指定 ATR 的周期。输入还包括一个工具提示,用户将鼠标悬停在脚本的“设置/输入”选项卡中的“i”图标上时可以看到该提示。
为图表背景着色
此示例使用单元格表格根据 RSI 的牛市/熊市状态为图表背景着色:
//@version=5
indicator("Chart background", "", true)
bullColorInput = input.color(color.new(color.green, 95), "Bull", inline = "1")
bearColorInput = input.color(color.new(color.red, 95), "Bear", inline = "1")
// ————— Function colors chart bg on RSI bull/bear state.
colorChartBg(bullColor, bearColor) =>
var table bgTable = table.new(position.middle_center, 1, 1)
float r = ta.rsi(close, 20)
color bgColor = r > 50 ? bullColor : r < 50 ? bearColor : na
if barstate.islast
table.cell(bgTable, 0, 0, width = 100, height = 100, bgcolor = bgColor)
colorChartBg(bullColorInput, bearColorInput)
注意:
- 我们为用户提供输入,允许他们指定用于背景的牛市/熊市颜色,并将这些输入颜色作为参数发送给我们的
colorChartBg()
函数。 - 我们只创建一次新表,使用 var 关键字来声明该表。
- 我们仅在最后一个柱上使用 table.cell() 来指定单元格的属性。我们使单元格的宽度和高度与指标的空间相同,因此它覆盖整个图表。
创建显示面板
表格是创建复杂显示面板的理想选择。它们不仅使显示面板始终在固定位置可见,而且还提供更灵活的格式,因为每个单元格的属性都是单独控制的:背景、文本颜色、大小和对齐方式等。
在这里,我们创建一个基本的显示面板,显示用户选择的 MA 值数量。我们在第一列显示它们的周期,然后用绿色/红色/灰色背景显示它们的值,背景会随着价格相对于每个 MA 的位置而变化。当价格高于/低于 MA 时,单元格的背景会变成牛市/熊市的颜色。当 MA 位于当前条形图的开盘价 和 收盘 价之间时,单元格的背景为中性色:
//@version=5
indicator("Price vs MA", "", true)
var string GP1 = "Moving averages"
int masQtyInput = input.int(20, "Quantity", minval = 1, maxval = 40, group = GP1, tooltip = "1-40")
int masStartInput = input.int(20, "Periods begin at", minval = 2, maxval = 200, group = GP1, tooltip = "2-200")
int masStepInput = input.int(20, "Periods increase by", minval = 1, maxval = 100, group = GP1, tooltip = "1-100")
var string GP2 = "Display"
string tableYposInput = input.string("top", "Panel position", inline = "11", options = ["top", "middle", "bottom"], group = GP2)
string tableXposInput = input.string("right", "", inline = "11", options = ["left", "center", "right"], group = GP2)
color bullColorInput = input.color(color.new(color.green, 30), "Bull", inline = "12", group = GP2)
color bearColorInput = input.color(color.new(color.red, 30), "Bear", inline = "12", group = GP2)
color neutColorInput = input.color(color.new(color.gray, 30), "Neutral", inline = "12", group = GP2)
var table panel = table.new(tableYposInput + "_" + tableXposInput, 2, masQtyInput + 1)
if barstate.islast
// Table header.
table.cell(panel, 0, 0, "MA", bgcolor = neutColorInput)
table.cell(panel, 1, 0, "Value", bgcolor = neutColorInput)
int period = masStartInput
for i = 1 to masQtyInput
// ————— Call MAs on each bar.
float ma = ta.sma(close, period)
// ————— Only execute table code on last bar.
if barstate.islast
// Period in left column.
table.cell(panel, 0, i, str.tostring(period), bgcolor = neutColorInput)
// If MA is between the open and close, use neutral color. If close is lower/higher than MA, use bull/bear color.
bgColor = close > ma ? open < ma ? neutColorInput : bullColorInput : open > ma ? neutColorInput : bearColorInput
// MA value in right column.
table.cell(panel, 1, i, str.tostring(ma, format.mintick), text_color = color.black, bgcolor = bgColor)
period += masStepInput
注意:
- 用户可以从输入中选择表格的位置,以及用于右列单元格背景的牛市/熊市/中性颜色。
- 表格的行数由用户选择显示的 MA 数量决定。我们为列标题添加一行。
- 尽管我们只在最后一个柱上填充表格单元格,但我们仍需要在每个柱上执行对ta.sma()的调用, 以便它们产生正确的结果。编译代码时出现的编译器警告可以安全地忽略。
- 我们使用 将输入分为两部分
group
,并使用 将相关部分合并到同一行inline
。我们使用 提供工具提示来记录某些字段的限制tooltip
。
显示热图
我们的下一个项目是热图,它将指示当前价格相对于其过去值的牛市/熊市关系。为此,我们将使用位于图表底部的表格。我们将仅显示颜色,因此我们的表格将不包含任何文本;我们只会为其单元格的背景着色以生成热图。热图使用用户可选择的回顾期。它循环遍历该时间段以确定价格是高于/低于过去的每个条形图,并随着我们进一步回顾过去,显示牛市/熊市颜色的强度逐渐变浅:
//@version=5
indicator("Price vs Past", "", true)
var int MAX_LOOKBACK = 300
int lookBackInput = input.int(150, minval = 1, maxval = MAX_LOOKBACK, step = 10)
color bullColorInput = input.color(#00FF00ff, "Bull", inline = "11")
color bearColorInput = input.color(#FF0080ff, "Bear", inline = "11")
// ————— Function draws a heatmap showing the position of the current `_src` relative to its past `_lookBack` values.
drawHeatmap(src, lookBack) =>
// float src : evaluated price series.
// int lookBack: number of past bars evaluated.
// Dependency: MAX_LOOKBACK
// Force historical buffer to a sufficient size.
max_bars_back(src, MAX_LOOKBACK)
// Only run table code on last bar.
if barstate.islast
var heatmap = table.new(position.bottom_center, lookBack, 1)
for i = 1 to lookBackInput
float transp = 100. * i / lookBack
if src > src[i]
table.cell(heatmap, lookBack - i, 0, bgcolor = color.new(bullColorInput, transp))
else
table.cell(heatmap, lookBack - i, 0, bgcolor = color.new(bearColorInput, transp))
drawHeatmap(high, lookBackInput)
注意:
- 我们将最大回溯期定义为
MAX_LOOKBACK
常数。这是一个重要的值,我们将其用于两个目的:指定我们将在单行表中创建的列数,以及指定函数中参数所需的回溯期,以便我们强制 Pine Script™ 创建历史缓冲区大小,使我们能够在for循环中_src
引用所需的过去值数量 。_src
- 我们为用户提供在输入中配置牛市/熊市颜色的可能性,并且我们将
inline
颜色选择放在同一行上。 - 在我们的函数内部,我们将表创建代码放在 if barstate.islast 结构中,以便它仅在图表的最后一条上运行。
- 表格的初始化是在 if 语句中完成的。由于这一点以及它使用 var 关键字的事实,初始化仅在脚本第一次在最后一个柱上执行时发生。请注意,此行为不同于脚本全局范围内的常规 var 声明,其中初始化发生在数据集的第一个柱上,即 bar_index 为零。
- 我们没有
text
在 table.cell() 调用中为参数指定参数,因此使用空字符串。 - 我们以这样一种方式计算透明度:随着历史的进一步发展,颜色的强度会降低。
- 我们使用动态颜色生成来根据需要创建基色的不同透明度。
- 与 Pine 脚本中显示的其他对象相反,此热图的单元格未链接到图表条。配置的回溯期决定了热图包含多少个表格单元格,并且热图不会随着图表水平平移或缩放而改变。
- 脚本的可视空间中可显示的最大单元格数取决于查看设备的分辨率和图表使用的显示部分。屏幕分辨率越高、窗口越宽,可显示越多的表格单元格。
提示
- 在策略脚本中创建表时,请记住,除非策略使用,否则if barstate.islast
calc_on_every_tick = true
块中包含的表代码 将不会在每次实时更新时执行,因此表将不会按您预期的方式显示。 - 请记住,对 table.cell()的连续调用将覆盖先前table.cell()调用 指定的单元格属性 。使用 setter 函数来修改单元格的属性。
- 请记住要明智地控制表格代码的执行,将其限制在必要的条形图上。这样可以节省服务器资源,并且您的图表将更快地显示,因此每个人都是赢家。