pine-script - 尝试用数组和循环替换重复的代码
问题描述
我正在尝试用数组和循环替换以下代码行。原因是它们几乎相同。
float f0 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.000)
float f236 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.236)
...
f_drawLabel(bar_index, f0, "0" + " (" + + tostring(f0, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
f_drawLine(fibStartIndex, f0, bar_index, f0, extend.none, C_GREEN, line.style_solid, 2)
f_drawLabel(bar_index, f236, "0.236" + " (" + + tostring(f236, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
f_drawLine(fibStartIndex, f236, bar_index, f236, extend.none, C_GREEN, line.style_solid, 2)
问题
下面的代码被注释掉了。问题是循环仅显示 1.000 斐波那契水平。原因是因为f_drawLabel
并且f_drawLine
正在更新一个标签/行。它应该创建 9 条线/标签(9 个斐波那契水平),并且当图表上出现新蜡烛时,它们中的每一个都应该自我更新。我正在使用 BINANCE:BTCUSDT 1 分钟时间范围进行测试。
我想得到一个不做line.delete
/的解决方案label.delete
。它应该更新数据,以免使脚本不堪重负。问题是for
循环的行为很奇怪,它不会创建 9 行,而只会创建 1 行。
片段
//@version=4
study("Auto Fibonacci Retracement v2 arrays", overlay = true, max_bars_back = 5000)
max_bars_back(time, 5000)
// ————— Color constants
var color C_BULL = color.blue
var color C_BEAR = color.red
var color C_BLACK = color.black
var color C_GRAY = color.gray
var color C_GREEN = color.green
var color C_RED = color.red
var color C_INVISIBLE = color.new(color.black, 100)
// }
// —————————— Inputs {
int i_lookback = input(500, "Lookback")
// }
// —————————— Functions {
// ————— Function which calculates Fibonacci Retracement levels
f_fibonacci(_isReversed, _highest, _lowest, _n) =>
_isReversed ? (_highest - _lowest) * _n + _lowest : _highest - (_highest - _lowest) * _n
// ————— Function which is drawing labels
f_drawLabel(_x, _y, _text, _color, _style, _textcolor, _size, _textalign, _tooltip) =>
var label _lbl = label.new(na, na, na, xloc.bar_index, yloc.price, color(na), _style, na, _size, _textalign, _tooltip)
// If I uncomment these, it will work, but then the labels and the lines will stack on every next candle
// var label _lbl = na
// _lbl := label.new(na, na, na, xloc.bar_index, yloc.price, color(na), _style, na, _size, _textalign, _tooltip)
if barstate.islast and not na(_x) and not na(_y)
label.set_xy(_lbl, _x, _y)
label.set_text(_lbl, _text)
label.set_color(_lbl, _color)
label.set_style(_lbl, _style)
label.set_textcolor(_lbl, _textcolor)
label.set_size(_lbl, _size)
label.set_textalign(_lbl, _textalign)
label.set_tooltip(_lbl, _tooltip)
int(na)
// ————— Function which is drawing lines
f_drawLine(_x1, _y1, _x2, _y2, _extend, _color, _style, _width) =>
var line _ln = line.new(na, na, na, na, xloc.bar_index, _extend, color(na), _style, _width)
if barstate.islast and not na(_x1) and not na(_y1) and not na(_x2) and not na(_y2)
line.set_xy1(_ln, _x1, _y1)
line.set_xy2(_ln, _x2, _y2)
line.set_extend(_ln, _extend)
line.set_color(_ln, _color)
line.set_style(_ln, _style)
line.set_width(_ln, _width)
int(na)
// }
// —————————— Calculations {
fibHighest = highest(i_lookback)
fibLowest = lowest(i_lookback)
fibHighestBars = highestbars(high, i_lookback)
fibLowestBars = lowestbars(low, i_lookback)
fibIsReversed = fibHighestBars < fibLowestBars
fibStartIndex = (fibLowestBars < fibHighestBars ? bar_index[-fibLowestBars] : bar_index[-fibHighestBars])
float f0 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.000)
float f236 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.236)
float f382 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.382)
float f500 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.500)
float f618 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.618)
float f786 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.786)
float f886 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 0.886)
float f1000 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 1.000)
float f1618 = f_fibonacci(fibIsReversed, fibHighest, fibLowest, 1.618)
// }
// —————————— Plots {
// ————— Draw Fibonacci Retracement levels
float[] fibRatios = array.from(0.000, 0.236, 0.382, 0.500, 0.618, 0.786, 0.886, 1.000)
// f_drawLabel(bar_index, fibHighest, "Array size: " + tostring(array.size(fibRatios)) + "\nbar_index: " + tostring(bar_index), C_GREEN, label.style_label_center, color.black, size.large, text.align_center, "")
float fX = 0.0
color fXColor = na
if barstate.islast
for int i = 0 to array.size(fibRatios) - 1
float ratio = array.get(fibRatios, i)
fX := f_fibonacci(fibIsReversed, fibHighest, fibLowest, ratio)
fXColor := color.blue // f_fibonacciColor(fibIsReversed, fX, fX, retraceY)
f_drawLabel(bar_index, fX, tostring(ratio, "#.###") + " (" + tostring(fX, "#.########") + ")", C_INVISIBLE, label.style_label_left, fXColor, size.normal, text.align_center, "")
f_drawLine(fibStartIndex, fX, bar_index, fX, extend.none, fXColor, line.style_solid, 2)
//==================================
// // This example works, because f_lineLoop is working unlike f_drawLine
// f_lineLoop(_x1, _y1, _x2, _y2) =>
// var line _line = na
// line.new(_x1, _y1, _x2, _y2, xloc.bar_index, extend.none, color.blue, line.style_solid, 1)
// if barstate.islast
// for int i = 0 to 9
// f_lineLoop(fibStartIndex, f1000 + i * 100, bar_index, f1000 + i * 100)
// // f_drawLine(fibStartIndex, f1000 + i * 100, bar_index, f1000 + i * 100, extend.none, C_GREEN, line.style_solid, 2)
//==================================
// THIS IS WHAT I'M TRYING TO REFACTOR. IT WORKS, BUT THE LINES ARE REPEATED ALL OVER AGAIN FOR EACH FIBO LEVEL
// f_drawLabel(bar_index, f0, "0" + " (" + + tostring(f0, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f0, bar_index, f0, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f236, "0.236" + " (" + + tostring(f236, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f236, bar_index, f236, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f382, "0.382" + " (" + + tostring(f382, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f382, bar_index, f382, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f500, "0.5" + " (" + + tostring(f500, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f500, bar_index, f500, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f618, "0.618" + " (" + + tostring(f618, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f618, bar_index, f618, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f786, "0.786" + " (" + + tostring(f786, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f786, bar_index, f786, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f886, "0.886" + " (" + + tostring(f886, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f886, bar_index, f886, extend.none, C_GREEN, line.style_solid, 2)
// f_drawLabel(bar_index, f1000, "1" + " (" + + tostring(f1000, "#.########") + ")", C_INVISIBLE, label.style_label_left, C_GREEN, size.normal, text.align_center, "")
// f_drawLine(fibStartIndex, f1000, bar_index, f1000, extend.none, C_GREEN, line.style_solid, 2)
// }
解决方案
Pine 函数不是“纯”(无状态)函数,而是具有状态的函数对象。函数作用域中的var
变量是该状态的一部分。每个函数调用都是单独的函数对象。当您制作“重复行”时,您声明了 f_drawLabel 的几个功能对象,每个对象都有自己的var label _lbl
和var line _ln
实例。当您尝试在循环中调用时,会使用单个实例f_drawLine
创建一个功能对象。var line _ln
您需要制作行数组var line[] _lns = array.new...
并制作附加参数:
// ————— Function which is drawing lines
f_drawLine(_x1, _y1, _x2, _y2, _extend, _color, _style, _width) =>
var line[] _lns = array.new_line(0)
if array.size(_lns) <= i
array.push(_lns, line.new(na, na, na, na, xloc.bar_index, _extend, color(na), _style, _width))
_ln = array.get(_lns, i)
if barstate.islast and not na(_x1) and not na(_y1) and not na(_x2) and not na(_y2)
line.set_xy1(_ln, _x1, _y1)
line.set_xy2(_ln, _x2, _y2)
line.set_extend(_ln, _extend)
line.set_color(_ln, _color)
line.set_style(_ln, _style)
line.set_width(_ln, _width)
...
for i = 0 to 1111
f_drawLabel(bar_index, ..., i)
我希望解决方案的想法很清楚。