本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © nsadeghi
//@version=5
indicator("RSI Trendlines with Breakouts", precision = 2, max_labels_count = 500, max_lines_count = 500)
g_trendlines = 'Trendline Settings', g_styling = 'Styling'
input_pLen = input.int(defval = 4, title = 'Lookback Range', minval = 1, group = g_trendlines, tooltip = 'How many bars to determine when a swing high/low is detected.')
input_rLen = input.int(defval = 14, title = 'RSI Length' , minval = 1, group = g_trendlines)
input_rSrc = input.source(defval = close, title = 'RSI Source', group = g_trendlines)
input_repaint = input.string(defval = 'On', title = 'Repainting', group = g_trendlines, options = ['On', 'Off: Bar Confirmation'], tooltip = 'Bar Confirmation: Generates alerts when candle closes. (1 Candle Later)')
input_rsiCol = input.color(defval = color.blue, title = 'RSI Color', group = g_styling)
input_style = input.string(defval = line.style_solid, title = 'Line Style', group = g_styling, options = [line.style_solid, line.style_dotted, line.style_dashed, line.style_arrow_left, line.style_arrow_right, line.style_arrow_both])
input_width = input.int(defval = 2, title = 'Line Width', minval = 1, group = g_styling)
input_lblType = input.string(defval = 'Simple', title = 'Label Type', group = g_styling, options = ['Full', 'Simple'])
input_lblSize = input.string(defval = size.small, title = 'Label Size', group = g_styling, options = [size.huge, size.large, size.normal, size.small, size.tiny])
input_pLowCol = input.color(defval = color.red, title = 'Pivot Low', inline = 'col', group = g_styling)
input_pHighCol = input.color(defval = #089981, title = 'Pivot High', inline = 'col', group = g_styling)
input_override = input.bool(defval = false, title = 'Override Text Color', group = g_styling, inline = 'override')
input_overCol = input.color(defval = color.white, title = ' ', group = g_styling, inline = 'override')
rsi = ta.rsi(input_rSrc, input_rLen)
lblText = switch input_lblType
'Simple' => 'Br'
'Full' => 'Break'
repaint = switch input_repaint
'On' => true
'Off: Bar Confirmation' => false
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
since(cond) =>
var savedValue = 0
var count = 0, count += 1
if cond
savedValue := count
count := 0
[savedValue]
pivot(len, typeof) =>
t = typeof == 'pl'
var pArr = array.new<float>()
for i = 0 to len + 1
pArr.push(rsi[i])
if pArr.size() == len + 3
pArr.shift()
index = pArr.get(pArr.size() - 2)
pivot = index == (t ? pArr.min() : pArr.max()) and (t ? pArr.last() > index : pArr.last() < index)
[sincePivot] = since(pivot)
prevPivot = ta.valuewhen(pivot, rsi[input_pLen], 1)
currPivot = ta.valuewhen(pivot, rsi[input_pLen], 0)
validPivot = pivot and (t ? currPivot > prevPivot : currPivot < prevPivot)
[pivot, prevPivot, currPivot, validPivot, sincePivot]
roc(cond, y2, y1, len, typeof) =>
t = typeof == 'pl'
var sArr = array.new<float>(input_pLen)
slope = math.round(math.abs(y2 - y1) / len, 2)
var invalidTrend = 0
if cond
sArr.clear(), invalidTrend := 0
for i = 1 to input_pLen
sArr.push(t ? y1 + (slope * i) : y1 - (slope * i))
sArr.reverse()
for [i, j] in sArr
if t ? rsi[i] < j : rsi[i] > j
invalidTrend += 1
[sArr, slope, invalidTrend]
breakout(typeof) =>
t = typeof == 'pl'
[pivot, prevPivotValue, pivotValue, pivotCheck, pivotSince] = pivot(input_pLen, typeof)
[pivotSlopeArr, pivotSlope, invalidPivot] = roc(pivot, prevPivotValue, pivotValue, pivotSince, typeof)
var newPivotSlopeArr = array.new<float>(pivotSlopeArr.size())
var bool pendingBreak = na
var float savedSlope = na
var pivotLine = line.new(na, na, na, na, color = t ? input_pLowCol : input_pHighCol, width = input_width, style = input_style)
condition = ta.change(pivot) and pivot and invalidPivot < 1 and pivotCheck
if condition
newPivotSlopeArr.clear(), pendingBreak := true
savedSlope := pivotSlope
for i in pivotSlopeArr
newPivotSlopeArr.push(i)
pivotLine.set_xy1(bar_index - (input_pLen + pivotSince), prevPivotValue)
pivotLine.set_xy2(bar_index, newPivotSlopeArr.first())
condition2 = (t ? rsi < newPivotSlopeArr.first() : rsi > newPivotSlopeArr.first()) and pendingBreak
breakout = repaint ? condition2 : condition2 and barstate.isconfirmed
if breakout
pendingBreak := na
pivotLine.copy()
label.new(
bar_index,
newPivotSlopeArr.first(),
text = lblText,
color = color.new(t ? input_pLowCol : input_pHighCol, 50),
textcolor = t ? (input_override ? input_overCol : input_pLowCol) : input_override ? input_overCol : input_pHighCol,
size = input_lblSize,
style = t ? label.style_label_lower_left : label.style_label_upper_left
)
if barstate.isconfirmed and pendingBreak
newPivotSlopeArr.unshift(t ? newPivotSlopeArr.first() + savedSlope : newPivotSlopeArr.first() - savedSlope)
pivotLine.set_xy2(bar_index + 1, newPivotSlopeArr.first())
[condition, breakout]
//------------------------------------------------------------------------------
// Breakout Instance & Plot
//------------------------------------------------------------------------------
[pl, plBreak] = breakout('pl')
[ph, phBreak] = breakout('ph')
plot(rsi, title = 'Relative Strength Index', color = input_rsiCol, linewidth = 2)
//------------------------------------------------------------------------------
// Alerts
//------------------------------------------------------------------------------
alertcondition(pl, 'New Pivot Low Trendline')
alertcondition(plBreak, 'Pivot Low Breakout')
alertcondition(ph, 'New Pivot High Trendline')
alertcondition(phBreak, 'Pivot High Breakout')