Breakout Lines + TP/SL

Uncle_the_shooter · study · 376 行 · 点赞 3,975 · TradingView 原页

本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。

Pine Script

// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Uncle_the_shooter
 
//@version=6
indicator('Breakout Lines + TP/SL', overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500)
 
// INPUTS
left         = input.int(20,  'Pivot Left')
right        = input.int(20,  'Pivot Right')
maxBars      = input.int(500, 'Max extend bars from detection (from the moment the pivot is detected)', minval = 10, maxval = 500)
maxHigh      = input.int(5,   'Show maximum last N HIGH lines (0 = all)', minval = 0, group = 'Line Limits')
maxLow       = input.int(5,   'Show maximum last N LOW lines (0 = all)', minval = 0, group = 'Line Limits')
transp       = input.int(50,  'Transparency (0-100)', minval = 0, maxval = 100, group = 'Colors')
 
// TREND LINE COLORS (these inputs also control signals, TP/SL levels, and fills)
highTrendColor = input.color(#ef5350,   'High Trendline Color (Resistance)',   group = 'Colors')
lowTrendColor  = input.color(#26a69a, 'Low Trendline Color (Support)', group = 'Colors')
 
// Signal and TP/SL colors are automatically linked to trendline colors
buyLabelColor  = lowTrendColor
sellLabelColor = highTrendColor
 
buyColorLight  = color.new(buyLabelColor,  40)
sellColorLight = color.new(sellLabelColor, 40)
buyFill        = color.new(buyLabelColor,  70)
sellFill       = color.new(sellLabelColor, 70)
 
// TP/SL SETTINGS
show_buy_sell_labels = input.bool(false,  "Show BUY/SELL Labels",          group = "Signals")
show_triangles       = input.bool(true,  "Show Triangle Signals",         group = "Signals")
 
show_targets   = input.bool(true,  "Show TP/SL Targets", group = "Targets")
use_atr_sl     = input.bool(true,  "SL = ATR × instead of %", group = "Targets")
atr_period     = input.int(14,     "ATR Period", minval=1, group = "Targets")
sl_atr_mult    = input.float(1.5,  "SL ATR Multiplier", step=0.1, group = "Targets")
sl_percent     = input.float(1.0,  "SL % from Entry", step=0.1, group = "Targets")
 
rr_tp1         = input.float(1.0,  "TP1 Risk-Reward Ratio", step=0.1, group = "Targets")
rr_tp2         = input.float(2.0,  "TP2 Risk-Reward Ratio", step=0.1, group = "Targets")
rr_tp3         = input.float(3.0,  "TP3 Risk-Reward Ratio", step=0.1, group = "Targets")
 
// DISPLAY
show_sl_level  = input.bool(true,  "Show SL Level",  group = "Display")
show_tp1_level = input.bool(true,  "Show TP1 Level", group = "Display")
show_tp2_level = input.bool(true,  "Show TP2 Level", group = "Display")
show_tp3_level = input.bool(true,  "Show TP3 Level", group = "Display")
 
// CLEANUP FUNCTION
cleanupLines(array<line> linesArr, array<int> detArr, array<bool> activeArr, int maxShow) =>
    if maxShow > 0 and array.size(linesArr) > maxShow
        while array.size(linesArr) > maxShow
            oldLine = array.shift(linesArr)
            line.delete(oldLine)
            array.shift(detArr)
            array.shift(activeArr)
 
// PIVOTS
ph = ta.pivothigh(high, left, right)
pl = ta.pivotlow(low, left, right)
 
// PIVOT MEMORY
var float prevHighPrice = na
var int   prevHighBar   = na
var float prevLowPrice  = na
var int   prevLowBar    = na
 
// LINE ARRAYS
var array<line> highLines     = array.new_line()
var array<int>  highDetection = array.new_int()
var array<bool> highActive    = array.new_bool()
 
var array<line> lowLines      = array.new_line()
var array<int>  lowDetection  = array.new_int()
var array<bool> lowActive     = array.new_bool()
 
// NEW HIGH PIVOT
if not na(ph)
    pivotBar     = bar_index - right
    pivotPrice   = ph
    detectionBar = bar_index
 
    if not na(prevHighPrice)
        dx    = pivotBar - prevHighBar
        slope = dx != 0 ? (pivotPrice - prevHighPrice) / float(dx) : 0.0
 
        x2_ext = math.min(detectionBar + maxBars, bar_index + 500)
        y2_ext = prevHighPrice + slope * float(x2_ext - prevHighBar)
 
        newLine = line.new(prevHighBar, prevHighPrice, x2_ext, y2_ext, width = 2, color = color.new(highTrendColor, transp))
 
        array.push(highLines,    newLine)
        array.push(highDetection, detectionBar)
        array.push(highActive,    true)
 
    prevHighPrice := pivotPrice
    prevHighBar   := pivotBar
 
// NEW LOW PIVOT
if not na(pl)
    pivotBar     = bar_index - right
    pivotPrice   = pl
    detectionBar = bar_index
 
    if not na(prevLowPrice)
        dx    = pivotBar - prevLowBar
        slope = dx != 0 ? (pivotPrice - prevLowPrice) / float(dx) : 0.0
 
        x2_ext = math.min(detectionBar + maxBars, bar_index + 500)
        y2_ext = prevLowPrice + slope * float(x2_ext - prevLowBar)
 
        newLine = line.new(prevLowBar, prevLowPrice, x2_ext, y2_ext, width = 2, color = color.new(lowTrendColor, transp))
 
        array.push(lowLines,     newLine)
        array.push(lowDetection, detectionBar)
        array.push(lowActive,    true)
 
    prevLowPrice := pivotPrice
    prevLowBar   := pivotBar
 
// HIGH LINE CONTROL
breakUp = false
if array.size(highLines) > 0
    for i = 0 to array.size(highLines) - 1
        if array.get(highActive, i)
            l           = array.get(highLines, i)
            detectionBar = array.get(highDetection, i)
            linePrice   = line.get_price(l, bar_index)
 
            if close > linePrice or bar_index - detectionBar >= maxBars
                line.set_extend(l, extend.none)
                line.set_x2(l, bar_index)
                line.set_y2(l, linePrice)
                array.set(highActive, i, false)
                if close > linePrice
                    breakUp := true
 
// LOW LINE CONTROL
breakDown = false
if array.size(lowLines) > 0
    for i = 0 to array.size(lowLines) - 1
        if array.get(lowActive, i)
            l           = array.get(lowLines, i)
            detectionBar = array.get(lowDetection, i)
            linePrice   = line.get_price(l, bar_index)
 
            if close < linePrice or bar_index - detectionBar >= maxBars
                line.set_extend(l, extend.none)
                line.set_x2(l, bar_index)
                line.set_y2(l, linePrice)
                array.set(lowActive, i, false)
                if close < linePrice
                    breakDown := true
 
// CLEANUP ON EVERY BAR
if maxHigh > 0
    cleanupLines(highLines, highDetection, highActive, maxHigh)
if maxLow > 0
    cleanupLines(lowLines, lowDetection, lowActive, maxLow)
 
// ATR AND TP/SL VARIABLES
atr_val = ta.atr(atr_period)
 
var int   trade_dir       = 0
var float sl_level        = na
var float extreme_level   = na
var line  entry_line      = na
var label entry_label     = na
var line  sl_line         = na
var label sl_label        = na
var line  tp1_line        = na
var label tp1_label       = na
var line  tp2_line        = na
var label tp2_label       = na
var line  tp3_line        = na
var label tp3_label       = na
var line  extreme_line    = na
var linefill risk_fill    = na
var linefill reward_fill  = na
var int   entry_bar       = na
 
// TP/SL ON BREAKUP (BUY)
if breakUp
    if show_buy_sell_labels
        label.new(bar_index, low, 'BUY', style = label.style_label_up, color = color.new(buyLabelColor, 40), textcolor = color.white, size = size.small)
    
    if show_targets
        // Delete previous objects
        line.delete(entry_line)
        label.delete(entry_label)
        line.delete(sl_line)
        label.delete(sl_label)
        line.delete(tp1_line)
        label.delete(tp1_label)
        line.delete(tp2_line)
        label.delete(tp2_label)
        line.delete(tp3_line)
        label.delete(tp3_label)
        line.delete(extreme_line)
        linefill.delete(risk_fill)
        linefill.delete(reward_fill)
 
        trade_dir := 1
        entry_bar := bar_index
        float entry_price = close
        float risk_dist = use_atr_sl ? atr_val * sl_atr_mult : entry_price * (sl_percent / 100)
        sl_level := entry_price - risk_dist
 
        float tp1_p = entry_price + risk_dist * rr_tp1
        float tp2_p = entry_price + risk_dist * rr_tp2
        float tp3_p = entry_price + risk_dist * rr_tp3
 
        float max_tp = na
        if show_tp3_level
            max_tp := tp3_p
        if show_tp2_level
            max_tp := na(max_tp) ? tp2_p : math.max(max_tp, tp2_p)
        if show_tp1_level
            max_tp := na(max_tp) ? tp1_p : math.max(max_tp, tp1_p)
        extreme_level := max_tp
 
        entry_line := line.new(bar_index, entry_price, bar_index + 1, entry_price, color = buyLabelColor, width = 1, extend = extend.right)
        entry_label := label.new(bar_index, entry_price, "BUY " + str.tostring(entry_price, format.mintick), style = label.style_label_left, color = buyLabelColor, textcolor = color.white, size = size.small)
 
        if show_sl_level
            sl_line := line.new(bar_index, sl_level, bar_index + 1, sl_level, color = sellColorLight, width = 1, style = line.style_dashed, extend = extend.right)
            sl_label := label.new(bar_index, sl_level, "SL " + str.tostring(sl_level, format.mintick), style = label.style_label_left, color = sellColorLight, textcolor = color.white, size = size.small)
 
        if show_tp1_level
            tp1_line := line.new(bar_index, tp1_p, bar_index + 1, tp1_p, color = buyColorLight, width = 1, extend = extend.right)
            tp1_label := label.new(bar_index, tp1_p, "TP1 " + str.tostring(tp1_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_tp2_level
            tp2_line := line.new(bar_index, tp2_p, bar_index + 1, tp2_p, color = buyColorLight, width = 1, extend = extend.right)
            tp2_label := label.new(bar_index, tp2_p, "TP2 " + str.tostring(tp2_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_tp3_level
            tp3_line := line.new(bar_index, tp3_p, bar_index + 1, tp3_p, color = buyColorLight, width = 1, style = line.style_dotted, extend = extend.right)
            tp3_label := label.new(bar_index, tp3_p, "TP3 " + str.tostring(tp3_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_sl_level
            risk_fill := linefill.new(entry_line, sl_line, sellFill)
 
        float max_tp_for_fill = entry_price
        if show_tp1_level
            max_tp_for_fill := math.max(max_tp_for_fill, tp1_p)
        if show_tp2_level
            max_tp_for_fill := math.max(max_tp_for_fill, tp2_p)
        if show_tp3_level
            max_tp_for_fill := math.max(max_tp_for_fill, tp3_p)
 
        if max_tp_for_fill > entry_price
            extreme_line := line.new(bar_index, max_tp_for_fill, bar_index + 1, max_tp_for_fill, color = na, extend = extend.right)
            reward_fill := linefill.new(entry_line, extreme_line, buyFill)
 
// TP/SL ON BREAKDOWN (SELL)
if breakDown
    if show_buy_sell_labels
        label.new(bar_index, high, 'SELL', style = label.style_label_down, color = color.new(sellLabelColor, 40), textcolor = color.white, size = size.small)
    
    if show_targets
        // Delete previous objects
        line.delete(entry_line)
        label.delete(entry_label)
        line.delete(sl_line)
        label.delete(sl_label)
        line.delete(tp1_line)
        label.delete(tp1_label)
        line.delete(tp2_line)
        label.delete(tp2_label)
        line.delete(tp3_line)
        label.delete(tp3_label)
        line.delete(extreme_line)
        linefill.delete(risk_fill)
        linefill.delete(reward_fill)
 
        trade_dir := -1
        entry_bar := bar_index
        float entry_price = close
        float risk_dist = use_atr_sl ? atr_val * sl_atr_mult : entry_price * (sl_percent / 100)
        sl_level := entry_price + risk_dist
 
        float tp1_p = entry_price - risk_dist * rr_tp1
        float tp2_p = entry_price - risk_dist * rr_tp2
        float tp3_p = entry_price - risk_dist * rr_tp3
 
        float min_tp = na
        if show_tp3_level
            min_tp := tp3_p
        if show_tp2_level
            min_tp := na(min_tp) ? tp2_p : math.min(min_tp, tp2_p)
        if show_tp1_level
            min_tp := na(min_tp) ? tp1_p : math.min(min_tp, tp1_p)
        extreme_level := min_tp
 
        entry_line := line.new(bar_index, entry_price, bar_index + 1, entry_price, color = sellLabelColor, width = 1, extend = extend.right)
        entry_label := label.new(bar_index, entry_price, "SELL " + str.tostring(entry_price, format.mintick), style = label.style_label_left, color = sellLabelColor, textcolor = color.white, size = size.small)
 
        if show_sl_level
            sl_line := line.new(bar_index, sl_level, bar_index + 1, sl_level, color = sellColorLight, width = 1, style = line.style_dashed, extend = extend.right)
            sl_label := label.new(bar_index, sl_level, "SL " + str.tostring(sl_level, format.mintick), style = label.style_label_left, color = sellColorLight, textcolor = color.white, size = size.small)
 
        if show_tp1_level
            tp1_line := line.new(bar_index, tp1_p, bar_index + 1, tp1_p, color = buyColorLight, width = 1, extend = extend.right)
            tp1_label := label.new(bar_index, tp1_p, "TP1 " + str.tostring(tp1_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_tp2_level
            tp2_line := line.new(bar_index, tp2_p, bar_index + 1, tp2_p, color = buyColorLight, width = 1, extend = extend.right)
            tp2_label := label.new(bar_index, tp2_p, "TP2 " + str.tostring(tp2_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_tp3_level
            tp3_line := line.new(bar_index, tp3_p, bar_index + 1, tp3_p, color = buyColorLight, width = 1, style = line.style_dotted, extend = extend.right)
            tp3_label := label.new(bar_index, tp3_p, "TP3 " + str.tostring(tp3_p, format.mintick), style = label.style_label_left, color = buyColorLight, textcolor = color.white, size = size.small)
 
        if show_sl_level
            risk_fill := linefill.new(entry_line, sl_line, sellFill)
 
        float min_tp_for_fill = entry_price
        if show_tp1_level
            min_tp_for_fill := math.min(min_tp_for_fill, tp1_p)
        if show_tp2_level
            min_tp_for_fill := math.min(min_tp_for_fill, tp2_p)
        if show_tp3_level
            min_tp_for_fill := math.min(min_tp_for_fill, tp3_p)
 
        if min_tp_for_fill < entry_price
            extreme_line := line.new(bar_index, min_tp_for_fill, bar_index + 1, min_tp_for_fill, color = na, extend = extend.right)
            reward_fill := linefill.new(entry_line, extreme_line, buyFill)
 
// POSITION UPDATE + CLOSING ON SL/TP
if trade_dir != 0
    label.set_x(entry_label, bar_index)
    if not na(sl_label)
        label.set_x(sl_label, bar_index)
    if not na(tp1_label)
        label.set_x(tp1_label, bar_index)
    if not na(tp2_label)
        label.set_x(tp2_label, bar_index)
    if not na(tp3_label)
        label.set_x(tp3_label, bar_index)
 
    bool sl_hit = false
    bool tp_hit = false
    if trade_dir == 1
        sl_hit := low <= sl_level
        tp_hit := not na(extreme_level) and high >= extreme_level
    else if trade_dir == -1
        sl_hit := high >= sl_level
        tp_hit := not na(extreme_level) and low <= extreme_level
 
    if bar_index > entry_bar and (sl_hit or tp_hit)
        line.set_extend(entry_line, extend.none)
        line.set_x2(entry_line, bar_index)
        if not na(sl_line)
            line.set_extend(sl_line, extend.none)
            line.set_x2(sl_line, bar_index)
        if not na(tp1_line)
            line.set_extend(tp1_line, extend.none)
            line.set_x2(tp1_line, bar_index)
        if not na(tp2_line)
            line.set_extend(tp2_line, extend.none)
            line.set_x2(tp2_line, bar_index)
        if not na(tp3_line)
            line.set_extend(tp3_line, extend.none)
            line.set_x2(tp3_line, bar_index)
        if not na(extreme_line)
            line.set_extend(extreme_line, extend.none)
            line.set_x2(extreme_line, bar_index)
        trade_dir := 0
 
// VISUAL SIGNALS
plotshape(breakUp and show_triangles,   style = shape.triangleup,   location = location.belowbar, color = buyLabelColor, size = size.tiny, textcolor = color.white)
plotshape(breakDown and show_triangles, style = shape.triangledown, location = location.abovebar, color = sellLabelColor, size = size.tiny, textcolor = color.white)
 
// ALERTS
alertcondition(breakUp,   title = "Buy Breakout Signal",  message = "Pivot Trendlines BUY Breakout")
alertcondition(breakDown, title = "Sell Breakout Signal", message = "Pivot Trendlines SELL Breakout")

← 返回列表