首页 > 解决方案 > 尝试用数组和循环替换重复的代码

问题描述

我正在尝试用数组和循环替换以下代码行。原因是它们几乎相同。

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-script

解决方案


Pine 函数不是“纯”(无状态)函数,而是具有状态的函数对象。函数作用域中的var变量是该状态的一部分。每个函数调用都是单独的函数对象。当您制作“重复行”时,您声明了 f_drawLabel 的几个功能对象,每个对象都有自己的var label _lblvar 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)

我希望解决方案的想法很清楚。


推荐阅读