Adaptive Regression Breakout Map | GainzAlgo

GainzAlgo · study · 250 行 · 点赞 4,311 · 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/
// © GainzAlgo
 //    │    │     │     │   ██████╗  █████╗ ██╗███╗   ██╗███████╗
 //   ┌┴┐   │    ┌┴┐    │  ██╔════╝ ██╔══██╗██║████╗  ██║╚══███╔╝
 //   │ │   │    │ │    │  ██║  ███╗███████║██║██╔██╗ ██║  ███╔╝ 
 //   └┬┘  ┌┴┐   └┬┘   ┌┴┐ ██║   ██║██╔══██║██║██║╚██╗██║ ███╔╝  
 //    │   │ │    │    │ | ██████╔╝██║  ██║██║██║ ╚████║███████╗
 //    │   └┬┘         └┬┘  ╚═════╝ ╚═╝  ╚═╝╚═╝╚═╝  ╚═══╝╚══════╝
 //         │           │  
 //                            █████╗ ██╗      ██████╗  ██████╗         
 //                           ██╔══██╗██║     ██╔════╝ ██╔═══██╗        
 //                           ███████║██║     ██║  ███╗██║   ██║        
 //                           ██╔══██║██║     ██║   ██║██║   ██║        
 //                           ██║  ██║███████╗╚██████╔╝╚██████╔╝        
 //                           ╚═╝  ╚═╝╚══════╝ ╚═════╝  ╚═════╝    
//@version=6
indicator("Adaptive Regression Breakout Map | Gainz Algo", shorttitle="ARBM | Gainz Algo", overlay=true, max_lines_count=500, max_labels_count=500)
 
// UI inputs 
grp_model = "Regression Model"
length    = input.int(50, "Regression Length", group=grp_model)
devMult   = input.float(2.0, "Deviation Multiplier", group=grp_model)
 
grp_sqz   = "Contraction Metrics"
sqzLen    = input.int(100, "Lookback Period", group=grp_sqz)
sqzPct    = input.float(20.0, "Contraction Threshold %", group=grp_sqz)
 
grp_risk  = "Target Architecture"
tp1Mult   = input.float(1.0, "TP1 Multiplier (x Bandwidth)", group=grp_risk)
tp2Mult   = input.float(2.0, "TP2 Multiplier (x Bandwidth)", group=grp_risk)
tp3Mult   = input.float(3.0, "TP3 Multiplier (x Bandwidth)", group=grp_risk)
 
grp_trend = "Holographic Trendlines Overlay"
showTrend = input.bool(true, "Show Holographic Trendlines", group=grp_trend)
pivLen    = input.int(10, "Pivot Length", group=grp_trend)
 
 
regBasis  = ta.linreg(close, length, 0)
stdDev    = ta.stdev(close, length)
upperBand = regBasis + (stdDev * devMult)
lowerBand = regBasis - (stdDev * devMult)
bandWidth = upperBand - lowerBand
minWidth  = ta.lowest(bandWidth, sqzLen)
maxWidth  = ta.highest(bandWidth, sqzLen)
widthPct  = (bandWidth - minWidth) / math.max(maxWidth - minWidth, 0.000001) * 100
isSqueeze = widthPct <= sqzPct
 
 
var float ph1_y = na, var int ph1_x = na
var float ph2_y = na, var int ph2_x = na
var float pl1_y = na, var int pl1_x = na
var float pl2_y = na, var int pl2_x = na
 
 
var line line_ph_core  = line.new(na, na, na, na, color=color.new(#00FFFF, 0), style=line.style_solid, width=1)
var line line_ph_glow1 = line.new(na, na, na, na, color=color.new(#00FFFF, 60), style=line.style_solid, width=3)
var line line_ph_glow2 = line.new(na, na, na, na, color=color.new(#00FFFF, 85), style=line.style_solid, width=6)
 
var line line_pl_core  = line.new(na, na, na, na, color=color.new(#FF00FF, 0), style=line.style_solid, width=1)
var line line_pl_glow1 = line.new(na, na, na, na, color=color.new(#FF00FF, 60), style=line.style_solid, width=3)
var line line_pl_glow2 = line.new(na, na, na, na, color=color.new(#FF00FF, 85), style=line.style_solid, width=6)
 
ph = ta.pivothigh(high, pivLen, pivLen)
pl = ta.pivotlow(low, pivLen, pivLen)
 
if not na(ph)
    ph2_y := ph1_y, ph2_x := ph1_x
    ph1_y := ph, ph1_x := bar_index - pivLen
    if showTrend and not na(ph2_x)
        line.set_xy1(line_ph_core, ph2_x, ph2_y)
        line.set_xy2(line_ph_core, ph1_x, ph1_y)
        line.set_extend(line_ph_core, extend.right)
        
 
        line.set_xy1(line_ph_glow1, ph2_x, ph2_y)
        line.set_xy2(line_ph_glow1, ph1_x, ph1_y)
        line.set_extend(line_ph_glow1, extend.right)
        
        line.set_xy1(line_ph_glow2, ph2_x, ph2_y)
        line.set_xy2(line_ph_glow2, ph1_x, ph1_y)
        line.set_extend(line_ph_glow2, extend.right)
 
if not na(pl)
    pl2_y := pl1_y, pl2_x := pl1_x
    pl1_y := pl, pl1_x := bar_index - pivLen
    if showTrend and not na(pl2_x)
 
        line.set_xy1(line_pl_core, pl2_x, pl2_y)
        line.set_xy2(line_pl_core, pl1_x, pl1_y)
        line.set_extend(line_pl_core, extend.right)
 
        line.set_xy1(line_pl_glow1, pl2_x, pl2_y)
        line.set_xy2(line_pl_glow1, pl1_x, pl1_y)
        line.set_extend(line_pl_glow1, extend.right)
        
  
        line.set_xy1(line_pl_glow2, pl2_x, pl2_y)
        line.set_xy2(line_pl_glow2, pl1_x, pl1_y)
        line.set_extend(line_pl_glow2, extend.right)
 
 
bullTrigger = close > upperBand and close[1] <= upperBand[1] and isSqueeze[1]
bearTrigger = close < lowerBand and close[1] >= lowerBand[1] and isSqueeze[1]
 
 
var int   tradeDir = 0
var float entryPx  = na
var float slPx     = na
var float tp1Px    = na
var float tp2Px    = na
var float tp3Px    = na
 
var bool  tp1Hit   = false
var bool  tp2Hit   = false
var bool  tp3Hit   = false
 
var float[] tradeReturns = array.new<float>()
var int     totalTrades  = 0
var int     winTrades    = 0
 
var line  lineEp   = na
var line  lineSl   = na
var line  lineTp1  = na
var line  lineTp2  = na
var line  lineTp3  = na
 
var label lblTp1   = na
var label lblTp2   = na
var label lblTp3   = na
 
if tradeDir == 0
    if bullTrigger
        tradeDir := 1
        entryPx  := close
        slPx     := lowerBand[1] 
        tp1Px    := entryPx + (bandWidth[1] * tp1Mult)
        tp2Px    := entryPx + (bandWidth[1] * tp2Mult)
        tp3Px    := entryPx + (bandWidth[1] * tp3Mult)
        tp1Hit   := false
        tp2Hit   := false
        tp3Hit   := false
        
        label.new(bar_index, low, "Breakout, Long", style=label.style_label_up, color=color.new(color.green, 20), textcolor=color.white, size=size.small)
        
    else if bearTrigger
        tradeDir := -1
        entryPx  := close
        slPx     := upperBand[1]
        tp1Px    := entryPx - (bandWidth[1] * tp1Mult)
        tp2Px    := entryPx - (bandWidth[1] * tp2Mult)
        tp3Px    := entryPx - (bandWidth[1] * tp3Mult)
        tp1Hit   := false
        tp2Hit   := false
        tp3Hit   := false
 
        label.new(bar_index, high, "Breakout, Short", style=label.style_label_down, color=color.new(color.red, 20), textcolor=color.white, size=size.small)
 
    if tradeDir != 0
        lineEp  := line.new(bar_index, entryPx, bar_index + 10, entryPx, color=color.new(color.blue, 50), width=2)
        lineSl  := line.new(bar_index, slPx, bar_index + 10, slPx, color=color.new(color.red, 50), width=2)
        lineTp1 := line.new(bar_index, tp1Px, bar_index + 10, tp1Px, color=color.new(color.green, 50), style=line.style_dashed)
        lineTp2 := line.new(bar_index, tp2Px, bar_index + 10, tp2Px, color=color.new(color.green, 50), style=line.style_dashed)
        lineTp3 := line.new(bar_index, tp3Px, bar_index + 10, tp3Px, color=color.new(color.green, 50), style=line.style_dashed)
        
        lblTp1  := label.new(bar_index + 10, tp1Px, "TP1", style=label.style_none, textcolor=color.green, size=size.small)
        lblTp2  := label.new(bar_index + 10, tp2Px, "TP2", style=label.style_none, textcolor=color.green, size=size.small)
        lblTp3  := label.new(bar_index + 10, tp3Px, "TP3", style=label.style_none, textcolor=color.green, size=size.small)
 
if tradeDir != 0
 
    line.set_x2(lineEp, bar_index + 5)
    line.set_x2(lineSl, bar_index + 5)
    line.set_x2(lineTp1, bar_index + 5)
    line.set_x2(lineTp2, bar_index + 5)
    line.set_x2(lineTp3, bar_index + 5)
    
    label.set_x(lblTp1, bar_index + 5)
    label.set_x(lblTp2, bar_index + 5)
    label.set_x(lblTp3, bar_index + 5)
 
 
    bool hitSl  = (tradeDir == 1 and low <= slPx) or (tradeDir == -1 and high >= slPx)
    bool hitTp1 = (tradeDir == 1 and high >= tp1Px) or (tradeDir == -1 and low <= tp1Px)
    bool hitTp2 = (tradeDir == 1 and high >= tp2Px) or (tradeDir == -1 and low <= tp2Px)
    bool hitTp3 = (tradeDir == 1 and high >= tp3Px) or (tradeDir == -1 and low <= tp3Px)
 
    if hitTp1 and not tp1Hit
        tp1Hit := true
        slPx   := entryPx 
        line.set_y1(lineSl, slPx)
        line.set_y2(lineSl, slPx)
        label.new(bar_index, tradeDir == 1 ? high : low, "TP1 Hit, Set Trail stop", style=tradeDir == 1 ? label.style_label_down : label.style_label_up, color=color.blue, textcolor=color.white, size=size.small)
 
    if hitTp2 and not tp2Hit
        tp2Hit := true
        slPx   := tp1Px 
        line.set_y1(lineSl, slPx)
        line.set_y2(lineSl, slPx)
        label.new(bar_index, tradeDir == 1 ? high : low, "TP2 Hit", style=tradeDir == 1 ? label.style_label_down : label.style_label_up, color=color.blue, textcolor=color.white, size=size.small)
 
  
    if hitTp3
        tradeReturn = ((tp3Px - entryPx) / entryPx) * tradeDir * 100
        array.push(tradeReturns, tradeReturn)
        
        totalTrades += 1
        winTrades   += 1
        tradeDir    := 0 
        
        label.new(bar_index, tradeDir == 1 ? high : low, "TP3 Hit (Closed)", style=tradeDir == 1 ? label.style_label_down : label.style_label_up, color=color.green, textcolor=color.white, size=size.small)
        
    else if hitSl
        tradeReturn = ((slPx - entryPx) / entryPx) * tradeDir * 100
        array.push(tradeReturns, tradeReturn)
        
        totalTrades += 1
        
        if tp1Hit
            winTrades += 1
            tradeDir  := 0
        else
            label.new(bar_index, tradeDir == 1 ? low : high, "Stop Loss Hit", style=tradeDir == 1 ? label.style_label_up : label.style_label_down, color=color.red, textcolor=color.white, size=size.small)
            tradeDir  := 0
 
// Visuals and mapping 
bandColor = isSqueeze ? color.new(color.gray, 60) : color.new(color.navy, 80)
pUpper    = plot(upperBand, color=bandColor, title="Upper Deviation")
pLower    = plot(lowerBand, color=bandColor, title="Lower Deviation")
fill(pUpper, pLower, color=color.new(bandColor, 90), title="Regression Channel")
 
// Stats table 
if barstate.islast
    var tbl = table.new(position.top_right, 2, 4, bgcolor=color.new(color.navy, 10), border_color=color.new(color.gray, 50), border_width=1, frame_color=color.new(color.gray, 50), frame_width=1)
    
    float avgRet   = array.size(tradeReturns) > 0 ? array.avg(tradeReturns) : 0.0
    float stdevRet = array.size(tradeReturns) > 1 ? array.stdev(tradeReturns) : 0.0
    float sharpe   = stdevRet > 0 ? (avgRet / stdevRet) : 0.0
    float winRate  = totalTrades > 0 ? (winTrades / totalTrades) * 100 : 0.0
    
    table.cell(tbl, 0, 0, "Map Performance", text_halign=text.align_center, text_color=color.white, bgcolor=color.new(color.navy, 20))
    table.merge_cells(tbl, 0, 0, 1, 0)
    
    table.cell(tbl, 0, 1, "Total Signals", text_color=color.gray, text_halign=text.align_left)
    table.cell(tbl, 1, 1, str.tostring(totalTrades), text_color=color.white, text_halign=text.align_right)
    
    table.cell(tbl, 0, 2, "Win Rate", text_color=color.gray, text_halign=text.align_left)
    table.cell(tbl, 1, 2, str.tostring(winRate, "#.##") + "%", text_color=winRate >= 50 ? color.green : color.red, text_halign=text.align_right)
    
    table.cell(tbl, 0, 3, "Trade Sharpe", text_color=color.gray, text_halign=text.align_left)
    table.cell(tbl, 1, 3, str.tostring(sharpe, "#.##"), text_color=sharpe >= 1 ? color.green : color.white, text_halign=text.align_right)

← 返回列表