Ultimate Opening Range Breakout [LuxAlgo]

LuxAlgo · study · 485 行 · 点赞 9,895 · TradingView 原页

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

Pine Script

// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
// © LuxAlgo
//@version=6
indicator("Ultimate Opening Range Breakout [LuxAlgo]", shorttitle = "LuxAlgo - Ult ORB", overlay = true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
 
//---------------------------------------------------------------------------------------------------------------------}
// Constants
//---------------------------------------------------------------------------------------------------------------------{
DATA                    = #DBDBDB
HEADERS                 = #808080
BACKGROUND              = #161616
BORDERS                 = #2E2E2E
 
TOP_RIGHT               = 'Top Right'
BOTTOM_RIGHT            = 'Bottom Right'
BOTTOM_LEFT             = 'Bottom Left'
 
TINY                    = 'Tiny'
SMALL                   = 'Small'
NORMAL                  = 'Normal'
LARGE                   = 'Large'
HUGE                    = 'Huge'
 
DASHBOARD_GROUP         = 'Dashboard'
 
dashboardTooltip        = 'Enable or disable the dashboard.'
dashboardPositionTooltip= 'Select the dashboard location.'
dashboardSizeTooltip    = 'Select the dashboard size.'
 
//---------------------------------------------------------------------------------------------------------------------}
// Inputs
//---------------------------------------------------------------------------------------------------------------------{
sessionInput            = input.session("0930-1000", "Opening Range Session", tooltip = "Define the time range for the opening range calculation. Format: HHMM-HHMM")
sessionDays             = input.string("1234567", "Days of Week", tooltip = "Select days to apply the opening range (1=Sunday, 7=Saturday)")
timezoneInput           = input.string("UTC-5", "Timezone", options = ["UTC-12", "UTC-11", "UTC-10", "UTC-9", "UTC-8", "UTC-7", "UTC-6", "UTC-5", "UTC-4", "UTC-3", "UTC-2", "UTC-1", "UTC+0", "UTC+1", "UTC+2", "UTC+3", "UTC+4", "UTC+5", "UTC+6", "UTC+7", "UTC+8", "UTC+9", "UTC+10", "UTC+11", "UTC+12"], tooltip = "Adjust the timezone for the session input.")
 
srcInput                = input.string("High/Low", "Range Source", options = ["High/Low", "Close"], tooltip = "Use the high/low of the session or the closing prices to define the range.")
showExtensions          = input.bool(true, "Show Extension Levels", group = "Extensions")
extType                 = input.string("Multiples", "Extension Type", options = ["Multiples", "Fibonacci"], group = "Extensions")
mult1                   = input.float(1.0, "Multiplier 1", minval = 0, group = "Extensions")
mult2                   = input.float(2.0, "Multiplier 2", minval = 0, group = "Extensions")
mult3                   = input.float(3.0, "Multiplier 3", minval = 0, group = "Extensions")
 
bullColor               = input.color(#089981, "Bullish Color", group = "Style", inline = "Colors")
bearColor               = input.color(#f23645, "Bearish Color", group = "Style", inline = "Colors")
neutralColor            = input.color(#5b9cf6, "Range Color", group = "Style", inline = "Colors")
bgTransp                = input.int(85, "Background Transparency", minval = 0, maxval = 100, group = "Style")
showLabels              = input.bool(true, "Show Level Labels", group = "Style")
sigLabelSize            = input.string("Small", "Signal Label Size", options = ["Tiny", "Small", "Normal", "Large"], group = "Style")
 
showVP                  = input.bool(true, "Show Volume Profile", group = "Volume Profile")
vpRowsInput             = input.int(14, "Number of Rows", minval = 5, maxval = 50, group = "Volume Profile", tooltip = "Number of blocks to divide the opening range into. Lower values make the profile more 'blocky'.")
vpWidth                 = input.int(30, "Profile Width (%)", minval = 1, maxval = 100, group = "Volume Profile", tooltip = "Width of the volume profile relative to the session length.")
vpColor                 = input.color(color.new(#5b9cf6, 60), "Profile Color", group = "Volume Profile")
 
stopPlotting            = input.bool(true, "Limit Plotting Duration", group = "Plotting Duration")
stopTimeType            = input.string("New York Close", "End Plotting At", options = ["New York Close", "London Close", "Manual Time", "End of Day"], group = "Plotting Duration", tooltip = "Choose when to stop drawing the levels on the chart.")
manualEndTime           = input.string("16:00", "Manual End Time (HH:MM)", group = "Plotting Duration", tooltip = "Format: HH:MM. Used if 'Manual Time' is selected.")
 
showTrail               = input.bool(false, "Show Trailing Stop", group = "Trailing Stop")
trailMult               = input.float(2.0, "ATR Multiplier", minval = 0.1, step = 0.1, group = "Trailing Stop", tooltip = "Multiplier for the ATR-based trailing stop.")
trailAtrLen             = input.int(14, "ATR Length", minval = 1, group = "Trailing Stop")
 
dashboardInput          = input.bool(true, 'Show Hit Rate Dashboard', group = DASHBOARD_GROUP, tooltip = dashboardTooltip)
showOptimizer           = input.bool(false, 'Show Stop Optimizer', group = DASHBOARD_GROUP, tooltip = "Simulates different ATR multipliers to find the most profitable distance.")
dashboardPositionInput  = input.string(TOP_RIGHT, 'Position', group = DASHBOARD_GROUP, tooltip = dashboardPositionTooltip, options = [TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT])
dashboardSizeInput      = input.string(SMALL, 'Size', group = DASHBOARD_GROUP, tooltip = dashboardSizeTooltip, options = [TINY, SMALL, NORMAL, LARGE, HUGE])
 
//---------------------------------------------------------------------------------------------------------------------}
// Variables
//---------------------------------------------------------------------------------------------------------------------{
var parsedDashboardPosition = switch dashboardPositionInput
    TOP_RIGHT       => position.top_right
    BOTTOM_RIGHT    => position.bottom_right
    BOTTOM_LEFT     => position.bottom_left
 
var parsedDashboardSize     = switch dashboardSizeInput
    TINY            => size.tiny
    SMALL           => size.small
    NORMAL          => size.normal
    LARGE           => size.large
    HUGE            => size.huge
 
atrVal = ta.atr(200)
var float dynamicTickSize = na
 
inSession = not na(time(timeframe.period, sessionInput + ":" + sessionDays, timezoneInput))
isNewDay  = ta.change(time("D", "", timezoneInput)) != 0
 
var float orHigh = na
var float orLow  = na
var bool  sessionEnded = false
 
var int totalSessions = 0
var int countU1 = 0
var int countU2 = 0
var int countU3 = 0
var int countD1 = 0
var int countD2 = 0
var int countD3 = 0
 
var bool dayReachedU1 = false
var bool dayReachedU2 = false
var bool dayReachedU3 = false
var bool dayReachedD1 = false
var bool dayReachedD2 = false
var bool dayReachedD3 = false
 
var map<float, float> volMap = map.new<float, float>()
var int sessionStartBar = 0
var int profileAnchor = 0
var box[] activeVPBoxes = array.new_box()
 
var float totalProfit = 0.0
var float entryPrice  = na
 
var float[] optProfits = array.from(0.0, 0.0, 0.0, 0.0, 0.0)
var float[] optMults   = array.from(1.0, 1.5, 2.0, 2.5, 3.0)
var float[] optStops   = array.new_float(5, na)
var int[] optActive    = array.new_int(5, 0) // 0: Idle, 1: Active Bull, -1: Active Bear
 
var float trailStop = na
var int activeDir = 0 // 1: Bull, -1: Bear, 0: None
 
var bool canSignalUp = true
var bool canSignalDn = true
 
//---------------------------------------------------------------------------------------------------------------------}
// Helper Functions
//---------------------------------------------------------------------------------------------------------------------{
cell(table t_able, int column, int row, string data, color = #FFFFFF, align = text.align_right, color background = na, float height = 0) => 
    t_able.cell(column, row, data, text_color = color, text_size = parsedDashboardSize, text_halign = align, bgcolor = background, height = height)
 
divider(table t_able, int row, int lastColumn) =>    
    string rowDivider = '━━━━━━━━━━━━━━'
    t_able.merge_cells(0, row, lastColumn, row)
    cell(t_able, 0, row, rowDivider, align = text.align_center, height = 0.5, color = BORDERS)
 
getExt(float multVal, float rangeVal, float highLvl, float lowLvl) =>
    float up = highLvl + rangeVal * multVal
    float dn = lowLvl - rangeVal * multVal
    [up, dn]
 
//---------------------------------------------------------------------------------------------------------------------}
// Core Logic
//---------------------------------------------------------------------------------------------------------------------{
if isNewDay or (inSession and not inSession[1])
    orHigh := na
    orLow  := na
    sessionEnded := false
    dayReachedU1 := false
    dayReachedU2 := false
    dayReachedU3 := false
    dayReachedD1 := false
    dayReachedD2 := false
    dayReachedD3 := false
    volMap.clear()
    sessionStartBar := bar_index
    profileAnchor := bar_index
    activeVPBoxes.clear()
    entryPrice := na
    optStops.fill(na)
    optActive.fill(0)
    dynamicTickSize := math.max(syminfo.mintick, nz(atrVal, high - low) / vpRowsInput)
 
if inSession
    float currentHigh = srcInput == "High/Low" ? high : math.max(open, close)
    float currentLow  = srcInput == "High/Low" ? low  : math.min(open, close)
    
    orHigh := na(orHigh) ? currentHigh : math.max(orHigh, currentHigh)
    orLow  := na(orLow) ? currentLow  : math.min(orLow, currentLow)
    profileAnchor := bar_index
 
    float currentRange = orHigh - orLow
    if currentRange > 0
        dynamicTickSize := math.max(syminfo.mintick, currentRange / vpRowsInput)
 
    float priceLevel = math.round(close / dynamicTickSize) * dynamicTickSize
    volMap.put(priceLevel, (volMap.contains(priceLevel) ? volMap.get(priceLevel) : 0) + volume)
 
if not inSession and inSession[1]
    sessionEnded := true
    totalSessions += 1
 
float orRange = orHigh - orLow
 
float f1 = extType == "Fibonacci" ? 0.382 : mult1
float f2 = extType == "Fibonacci" ? 0.618 : mult2
float f3 = extType == "Fibonacci" ? 1.0   : mult3
 
[u1, d1] = getExt(f1, orRange, orHigh, orLow)
[u2, d2] = getExt(f2, orRange, orHigh, orLow)
[u3, d3] = getExt(f3, orRange, orHigh, orLow)
 
if sessionEnded
    if not na(u1) and high >= u1 and not dayReachedU1
        countU1 += 1
        dayReachedU1 := true
    if not na(u2) and high >= u2 and not dayReachedU2
        countU2 += 1
        dayReachedU2 := true
    if not na(u3) and high >= u3 and not dayReachedU3
        countU3 += 1
        dayReachedU3 := true
        
    if not na(d1) and low <= d1 and not dayReachedD1
        countD1 += 1
        dayReachedD1 := true
    if not na(d2) and low <= d2 and not dayReachedD2
        countD2 += 1
        dayReachedD2 := true
    if not na(d3) and low <= d3 and not dayReachedD3
        countD3 += 1
        dayReachedD3 := true
 
orStartTime = str.substring(sessionInput, 0, 4)
 
string targetEndTime = switch stopTimeType
    "New York Close" => "1700"
    "London Close"   => "1130"
    "Manual Time"    => str.replace(manualEndTime, ":", "")
    => "2359"
 
plottingSession = orStartTime + "-" + targetEndTime
bool displayAllowed = not stopPlotting or not na(time(timeframe.period, plottingSession + ":" + sessionDays, timezoneInput))
 
plotHigh = displayAllowed ? orHigh : na
plotLow  = displayAllowed ? orLow  : na
plotU1   = displayAllowed and showExtensions ? u1 : na
plotU2   = displayAllowed and showExtensions ? u2 : na
plotU3   = displayAllowed and showExtensions ? u3 : na
plotD1   = displayAllowed and showExtensions ? d1 : na
plotD2   = displayAllowed and showExtensions ? d2 : na
plotD3   = displayAllowed and showExtensions ? d3 : na
 
atrTrail = ta.atr(trailAtrLen)
 
volSMA = ta.sma(volume, 20)
isHV = volume > volSMA
volSuffix = isHV ? " (HV)" : " (LV)"
szSignal = sigLabelSize == "Tiny" ? size.tiny : sigLabelSize == "Small" ? size.small : sigLabelSize == "Normal" ? size.normal : size.large
 
bool breakoutUp = ta.crossover(close, orHigh) and not inSession and sessionEnded
bool breakoutDn = ta.crossunder(close, orLow) and not inSession and sessionEnded
 
if isNewDay or inSession
    canSignalUp := true
    canSignalDn := true
    activeDir   := 0
    trailStop   := na
 
if breakoutUp and canSignalUp and displayAllowed
    label.new(bar_index, high, "BULL BREAK" + volSuffix, color = bullColor, style = label.style_label_down, textcolor = color.white, size = szSignal)
    canSignalUp := false
    if activeDir == 0
        activeDir  := 1
        entryPrice := orHigh
        trailStop  := low - (atrTrail * trailMult)
        for i = 0 to 4
            optActive.set(i, 1)
            optStops.set(i, low - (atrTrail * optMults.get(i)))
 
if breakoutDn and canSignalDn and displayAllowed
    label.new(bar_index, low, "BEAR BREAK" + volSuffix, color = bearColor, style = label.style_label_up, textcolor = color.white, size = szSignal)
    canSignalDn := false
    if activeDir == 0
        activeDir  := -1
        entryPrice := orLow
        trailStop  := high + (atrTrail * trailMult)
        for i = 0 to 4
            optActive.set(i, -1)
            optStops.set(i, high + (atrTrail * optMults.get(i)))
 
if activeDir == 1
    trailStop := math.max(nz(trailStop[1], low - (atrTrail * trailMult)), low - (atrTrail * trailMult))
    if close < trailStop or not displayAllowed
        totalProfit += (close - entryPrice)
        activeDir := 0
        trailStop := na
 
if activeDir == -1
    trailStop := math.min(nz(trailStop[1], high + (atrTrail * trailMult)), high + (atrTrail * trailMult))
    if close > trailStop or not displayAllowed
        totalProfit += (entryPrice - close)
        activeDir := 0
        trailStop := na
 
if showOptimizer
    for i = 0 to 4
        m = optMults.get(i)
        a = optActive.get(i)
        s = optStops.get(i)
        if a == 1
            newStop = math.max(nz(s, low - (atrTrail * m)), low - (atrTrail * m))
            optStops.set(i, newStop)
            if close < newStop or not displayAllowed
                optProfits.set(i, optProfits.get(i) + (close - entryPrice))
                optActive.set(i, 0)
        else if a == -1
            newStop = math.min(nz(s, high + (atrTrail * m)), high + (atrTrail * m))
            optStops.set(i, newStop)
            if close > newStop or not displayAllowed
                optProfits.set(i, optProfits.get(i) + (entryPrice - close))
                optActive.set(i, 0)
 
//---------------------------------------------------------------------------------------------------------------------}
// Visuals
//---------------------------------------------------------------------------------------------------------------------{
bgcolor(inSession ? color.new(neutralColor, 90) : na, title = "Session Background")
 
pHigh = plot(plotHigh, "OR High", color.new(neutralColor, 20), 2, plot.style_linebr)
pLow  = plot(plotLow, "OR Low", color.new(neutralColor, 20), 2, plot.style_linebr)
 
fill(pHigh, pLow, plotHigh, plotLow, color.new(neutralColor, bgTransp), color.new(neutralColor, bgTransp), "Range Fill")
 
pu1 = plot(plotU1, "Upper Ext 1", color.new(bullColor, 40), 1, plot.style_linebr)
pu2 = plot(plotU2, "Upper Ext 2", color.new(bullColor, 40), 1, plot.style_linebr)
pu3 = plot(plotU3, "Upper Ext 3", color.new(bullColor, 40), 1, plot.style_linebr)
 
pd1 = plot(plotD1, "Lower Ext 1", color.new(bearColor, 40), 1, plot.style_linebr)
pd2 = plot(plotD2, "Lower Ext 2", color.new(bearColor, 40), 1, plot.style_linebr)
pd3 = plot(plotD3, "Lower Ext 3", color.new(bearColor, 40), 1, plot.style_linebr)
 
fill(pHigh, pu1, plotU1, plotHigh, color.new(bullColor, bgTransp + 10), color.new(bullColor, bgTransp), "Bull Zone 1")
fill(pu1, pu2, plotU2, plotU1, color.new(bullColor, bgTransp + 5), color.new(bullColor, bgTransp + 10), "Bull Zone 2")
fill(pu2, pu3, plotU3, plotU2, color.new(bullColor, bgTransp), color.new(bullColor, bgTransp + 5), "Bull Zone 3")
 
fill(pLow, pd1, plotLow, plotD1, color.new(bearColor, bgTransp), color.new(bearColor, bgTransp + 10), "Bear Zone 1")
fill(pd1, pd2, plotD1, plotD2, color.new(bearColor, bgTransp + 10), color.new(bearColor, bgTransp + 5), "Bear Zone 2")
fill(pd2, pd3, plotD2, plotD3, color.new(bearColor, bgTransp + 5), color.new(bearColor, bgTransp), "Bear Zone 3")
 
pTrail = plot(showTrail ? trailStop : na, "Trailing Stop", activeDir == 1 ? bullColor : bearColor, 2, plot.style_linebr)
pPrice = plot(showTrail ? close : na, "Trail Price Ref", color.new(chart.fg_color, 100))
fill(pTrail, pPrice, 
     top_value = activeDir == 1 ? close : trailStop, 
     bottom_value = activeDir == 1 ? trailStop : close, 
     top_color = activeDir == 1 ? color.new(bullColor, 50) : color.new(bearColor, 100), 
     bottom_color = activeDir == 1 ? color.new(bullColor, 100) : color.new(bearColor, 50), 
     title = "Trailing Stop Fill")
 
if barstate.islast
    if showVP and volMap.size() > 0
        if activeVPBoxes.size() > 0
            for b in activeVPBoxes
                b.delete()
            activeVPBoxes.clear()
 
        float maxVol = 0.0
        float[] prices = volMap.keys()
        for p in prices
            maxVol := math.max(maxVol, volMap.get(p))
        
        if prices.size() > 0
            prices.sort()
            int profileMaxBars = 15 
            float levelHeight = dynamicTickSize
            int startX = bar_index + 25
            
            for i = 0 to prices.size() - 1
                float p = prices.get(i)
                if p >= (orLow - levelHeight / 2) and p <= (orHigh + levelHeight / 2)
                    float vol = volMap.get(p)
                    bool  isPOC = vol == maxVol
                    int bars = math.max(1, math.round((vol / math.max(1e-10, maxVol)) * profileMaxBars))
                    color cellColor = isPOC ? color.new(vpColor, 0) : color.new(vpColor, 40)
                    box nb = box.new(startX, p + levelHeight / 2, startX + bars, p - levelHeight / 2, 
                                     border_color = color.new(vpColor, 100), bgcolor = cellColor)
                    activeVPBoxes.push(nb)
 
    if showLabels
        label.delete(label.new(bar_index + 2, orHigh, "OR High", color = neutralColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
        label.delete(label.new(bar_index + 2, orLow, "OR Low", color = neutralColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
        if showExtensions
            string lblU1 = "Target 1 (" + str.tostring(totalSessions > 0 ? math.round((countU1 / totalSessions) * 100) : 0) + "%)"
            string lblD1 = "Target 1 (" + str.tostring(totalSessions > 0 ? math.round((countD1 / totalSessions) * 100) : 0) + "%)"
            string lblU2 = "Target 2 (" + str.tostring(totalSessions > 0 ? math.round((countU2 / totalSessions) * 100) : 0) + "%)"
            string lblD2 = "Target 2 (" + str.tostring(totalSessions > 0 ? math.round((countD2 / totalSessions) * 100) : 0) + "%)"
            string lblU3 = "Target 3 (" + str.tostring(totalSessions > 0 ? math.round((countU3 / totalSessions) * 100) : 0) + "%)"
            string lblD3 = "Target 3 (" + str.tostring(totalSessions > 0 ? math.round((countD3 / totalSessions) * 100) : 0) + "%)"
 
            label.delete(label.new(bar_index + 2, u1, lblU1, color = bullColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
            label.delete(label.new(bar_index + 2, d1, lblD1, color = bearColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
            label.delete(label.new(bar_index + 2, u2, lblU2, color = bullColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
            label.delete(label.new(bar_index + 2, d2, lblD2, color = bearColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
            label.delete(label.new(bar_index + 2, u3, lblU3, color = bullColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
            label.delete(label.new(bar_index + 2, d3, lblD3, color = bearColor, style = label.style_label_left, textcolor = color.white, size = size.small)[1])
 
//---------------------------------------------------------------------------------------------------------------------}
// Dashboard
//---------------------------------------------------------------------------------------------------------------------{
if dashboardInput
    int rowsTotal = 13 + (showTrail ? 2 : 0) + (showOptimizer ? 2 : 0)
    var table dash = table.new(parsedDashboardPosition, 4, rowsTotal, bgcolor = BACKGROUND, border_width = 0, frame_color = BORDERS, frame_width = 1, force_overlay = false)
    
    if barstate.isfirst
        dash.merge_cells(0, 0, 3, 0)
        cell(dash, 0, 0, 'ORB Hit Rate', color = DATA, align = text.align_center)
        
        divider(dash, 1, 3)
 
        cell(dash, 0, 2, "Level", color = HEADERS, align = text.align_left)
        cell(dash, 1, 2, "Hits", color = HEADERS)
        cell(dash, 2, 2, "Total", color = HEADERS)
        cell(dash, 3, 2, "Rate", color = HEADERS)
 
        divider(dash, 3, 3)
        divider(dash, 7, 3)
        divider(dash, 11, 3)
 
        dash.merge_cells(0, 12, 3, 12)
        
        int nextRow = 13
        if showTrail
            divider(dash, nextRow, 3)
            nextRow += 1
            dash.merge_cells(0, nextRow, 3, nextRow)
            nextRow += 1
            
        if showOptimizer
            divider(dash, nextRow, 3)
            nextRow += 1
            dash.merge_cells(0, nextRow, 3, nextRow)
 
    if barstate.islast
        totalHits = math.max(1, totalSessions)
        
        cell(dash, 0, 4, "Bull T1", color = HEADERS, align = text.align_left)
        cell(dash, 1, 4, str.tostring(countU1), color = bullColor)
        cell(dash, 2, 4, str.tostring(totalSessions), color = bullColor)
        cell(dash, 3, 4, str.tostring(math.round((countU1 / totalHits) * 100)) + "%", color = bullColor)
 
        cell(dash, 0, 5, "Bull T2", color = HEADERS, align = text.align_left)
        cell(dash, 1, 5, str.tostring(countU2), color = bullColor)
        cell(dash, 2, 5, str.tostring(totalSessions), color = bullColor)
        cell(dash, 3, 5, str.tostring(math.round((countU2 / totalHits) * 100)) + "%", color = bullColor)
 
        cell(dash, 0, 6, "Bull T3", color = HEADERS, align = text.align_left)
        cell(dash, 1, 6, str.tostring(countU3), color = bullColor)
        cell(dash, 2, 6, str.tostring(totalSessions), color = bullColor)
        cell(dash, 3, 6, str.tostring(math.round((countU3 / totalHits) * 100)) + "%", color = bullColor)
 
        cell(dash, 0, 8, "Bear T1", color = HEADERS, align = text.align_left)
        cell(dash, 1, 8, str.tostring(countD1), color = bearColor)
        cell(dash, 2, 8, str.tostring(totalSessions), color = bearColor)
        cell(dash, 3, 8, str.tostring(math.round((countD1 / totalHits) * 100)) + "%", color = bearColor)
 
        cell(dash, 0, 9, "Bear T2", color = HEADERS, align = text.align_left)
        cell(dash, 1, 9, str.tostring(countD2), color = bearColor)
        cell(dash, 2, 9, str.tostring(totalSessions), color = bearColor)
        cell(dash, 3, 9, str.tostring(math.round((countD2 / totalHits) * 100)) + "%", color = bearColor)
 
        cell(dash, 0, 10, "Bear T3", color = HEADERS, align = text.align_left)
        cell(dash, 1, 10, str.tostring(countD3), color = bearColor)
        cell(dash, 2, 10, str.tostring(totalSessions), color = bearColor)
        cell(dash, 3, 10, str.tostring(math.round((countD3 / totalHits) * 100)) + "%", color = bearColor)
 
        cell(dash, 0, 12, "Tracked: " + str.tostring(totalSessions) + " (" + sessionInput + ")", color = DATA, align = text.align_center)
        
        int nextRow = 13
        if showTrail
            nextRow += 1
            cell(dash, 0, nextRow, "Cumulative Trail Profit: " + str.tostring(totalProfit, "#.##"), color = DATA, align = text.align_center)
            nextRow += 1
            
        if showOptimizer
            nextRow += 1
            int bestIdx = 0
            float maxP = -1e10
            for i = 0 to 4
                p = optProfits.get(i)
                if p > maxP
                    maxP := p
                    bestIdx := i
            bestMult = optMults.get(bestIdx)
            cell(dash, 0, nextRow, "Best ATR Mult: " + str.tostring(bestMult) + " (Profit: " + str.tostring(maxP, "#.##") + ")", color = color.new(#FFD700, 0), align = text.align_center)
 
//---------------------------------------------------------------------------------------------------------------------}
// Alerts
//---------------------------------------------------------------------------------------------------------------------{
alertcondition(breakoutUp, "Bullish ORB", "Price broke above the opening range.")
alertcondition(breakoutDn, "Bearish ORB", "Price broke below the opening range.")
alertcondition(ta.cross(close, u3), "Target 3 Reached", "Price reached the final bullish target.")
alertcondition(ta.cross(close, d3), "Target 3 Reached", "Price reached the final bearish target.")
 
//---------------------------------------------------------------------------------------------------------------------}

← 返回列表