Как условно удалить строку в Pine Script

Я пытаюсь создать исследование TradingView, которое рисует линию от пересечения на текущем баре до пересечения на предыдущем баре, где предыдущий бар меньше установленного максимального количества баров назад.

Я хочу рисовать только линии с отрицательным наклоном (т. е. предыдущее пересечение происходит с более высоким значением), и мне также не нужно несколько линий с одной и той же начальной точкой (без перекрывающихся линий).

Я могу правильно рисовать линии, но я не знаю, как удалить линии, когда они перекрываются (имеют одну и ту же начальную точку).

При рисовании новой линии, которая будет перекрывать старую, как мне получить ссылку на старую линию, чтобы я мог ее удалить?

Следующее кажется невозможным в сосновом сценарии:

  • Итерация по предыдущим значениям в серии строк для проверки их значений x, y
  • Доступ к ряду строк по индексу, например bar_index
  • Доступ к предыдущему значению строки без создания новой строки
//@version=4
study(title='MACD trend')
src = input(close)
fast = input(12)
slow = input(26)
smooth = input(9)
numBarsBack = input(50)

fast_ma = wma(src, fast)
slow_ma = wma(src, slow)
macd = fast_ma-slow_ma
signal = wma(macd, smooth)
hist = macd - signal

if (crossunder(macd, signal))
// cross under happened on previous bar
    for i = 1 to numBarsBack
    // inspect previous bars up to 'numBarsBack'
        if (crossunder(macd,signal)[i])
            if (macd - macd[i] < 0)
            // located a previous cross under with a higher macd value
                l = line.new(bar_index[1], macd[1], bar_index[i+1], macd[i+1], width=1, color=color.red)
                // drew line from previous cross under to current cross under, 
                // offset x's by 1 bar since crossunder returns true based on previous bar's cross under
                for k = 1 to i
                // inspect previous bars up to the starting point of drawn line
                    if (crossunder(macd, signal)[k] and macd > macd[k])
                    // if the previous cross under value is less than the current one
                        line.delete(l[1])
                        // not sure what the 1 here indexes???

plot(title='MACD', series=macd,transp=0,linewidth=2, color=color.yellow)
plot(title='SIGNAL', series=signal,transp=0,linewidth=2, color=color.red)

person ughpines    schedule 24.01.2020    source источник


Ответы (1)


Смотрите комментарии в коде. Сделал линии толще, чтобы их было легче увидеть, и добавил графики отладки в конце скрипта.

Основная идея заключается в распространении идентификатора ранее созданной строки с помощью очень удобного var при инициализации переменной l. Таким образом, перед созданием новой линии мы извлекаем y2, использованный для создания предыдущей линии, поэтому линию можно удалить, если ее y2 совпадает с той, которую мы собираемся создать (поэтому она была нарисована с той же вершины).

Обнаружение перекрестного пика использует встроенные функции Pine вместо петли for. Так код будет работать быстрее.

//@version=4
study(title='MACD trend2')
src = input(close)
fast = input(12)
slow = input(26)
smooth = input(9)
numBarsBack = input(50)

fast_ma = wma(src, fast)
slow_ma = wma(src, slow)
macd = fast_ma-slow_ma
signal = wma(macd, smooth)
hist = macd - signal

xDn = crossunder(macd, signal)
// Get macd at at highest xDn in last numBarsBack bars. If no Xdn found, set value to -10e10.
highestXDnMacd = highest(xDn ? macd : -10e10, numBarsBack)
// Get offset to that point.
highestXDnOffset = - highestbars(xDn ? macd : -10e10, numBarsBack)

// Detect if previous xDn meets all criteria.
lastXDnWasHigher = xDn and macd < highestXDnMacd
// Make l persistent, so that it always contains the line id of the last line created.
var line l = na
if lastXDnWasHigher
    // Retrieve y2 used to draw previous line.
    if line.get_y2(l) == highestXDnMacd
        // Last line drawn used same y2 as the one we are about to use; delete it.
        // No more than one line back can have same peak since previous ones have already been deleted.
        line.delete(l)
    // The line id we assign to l here will persist through future bars,
    // which is what will allow us to delete the corresponding line using the line.delete() above, if needed.
    l := line.new(bar_index[1], macd[1], bar_index - highestXDnOffset, macd[highestXDnOffset], width=3, color=color.black)

plot(title='MACD', series=macd,transp=0,linewidth=2, color=color.yellow)
plot(title='SIGNAL', series=signal,transp=0,linewidth=2, color=color.red)

// Debugging.
plot(highestXDnMacd != -10e10 ? highestXDnMacd : na, "highestXDnMacd", color.silver, 2, plot.style_circles)
plotchar(highestXDnOffset, "highestXDnOffset", "", location.top)    // For Data Window display.
bgcolor(lastXDnWasHigher ? color.green : xDn ? color.silver : na, 60)

введите здесь описание изображения

person PineCoders-LucF    schedule 25.01.2020
comment
Ах, это решает проблему для меня, спасибо за совет! Синтаксис var line l - это то, чего мне не хватало, я не знал, что вы можете определить тип для переменной без ее инициализации в скрипте pine. - person ughpines; 31.01.2020
comment
Рад, что был вам полезен. var фактически инициализирует переменную, но только на первом баре, что имеет вторичный эффект распространения ее значения по барам, без необходимости, как в версии 3, постоянно получать ее значение из последнего бара, когда вы не хотите его потерять . Таким образом, несмотря на то, что поведение var может быть воспроизведено в версии 3, его использование упрощает код, облегчает его чтение, поскольку оно явно объявляет наше намерение, и немного быстрее, чем инициализация на каждом такте. - person PineCoders-LucF; 01.02.2020