Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //@version=6
- indicator(title="HTF Candles & Separators", shorttitle="HTF+Candles+Sep", overlay=true, max_boxes_count=500, max_lines_count=500, max_labels_count=500) // Increased labels count
- // --- HTF Settings ---
- timeframe1 = input.timeframe('D', 'Timeframe 1')
- timeframe2 = input.timeframe('W', 'Timeframe 2')
- timeframe3 = input.timeframe('M', 'Timeframe 3')
- numBoxes = input.int(3, 'Number of Boxes', minval=1, maxval=10)
- // Separator Timeframe Selection
- separatorTF = input.timeframe('D', 'Separator Timeframe')
- // Box Settings
- BoxShow = input.bool(true, 'Show HTF Boxes')
- BoxWidth = input.int(1, 'Box Border Width', minval=0)
- BoxLineStyle = input.bool(false, 'Box Border Dashed') ? line.style_dashed : line.style_solid
- // HTF mSpot Settings
- mSpotShow = input.bool(false, 'Show HTF mSpot')
- mSpotWidth = input.int(1, 'mSpot Line Width', minval=0)
- mSpotStyle = input.bool(true, 'mSpot Line Dashed') ? line.style_dashed : line.style_solid
- // HTF Open Line Settings
- OpenLineShow = input.bool(true, 'Show HTF Open Line')
- OpenLineWidth = input.int(1, 'Open Line Width', minval=0)
- OpenLineStyle = input.bool(false, 'Open Line Dashed') ? line.style_dashed : line.style_solid
- // --- Timeframe Label Settings ---
- showLabels = input.bool(true, "Show Timeframe Labels", group="Timeframe Labels")
- labelPosition = input.string("Top", "Label Position", options=["Top", "Middle", "Bottom"], group="Timeframe Labels")
- labelSize = input.string("small", "Label Size", options=["tiny", "small", "normal", "large"], group="Timeframe Labels")
- labelColor = input.color(color.white, "Label Color", group="Timeframe Labels")
- labelBgColor = input.color(color.new(color.black, 50), "Label Background Color", group="Timeframe Labels")
- // HTF Box Colors - Automated (no user selection)
- boxBullishColor = color.new(#66bb6a, 80) // Green for bullish
- boxBearishColor = color.new(#f7525f, 80) // Red for bearish
- boxBorderColor = color.new(#9598a1, 50) // Gray border
- mSpotColor = color.new(#9598a1, 50) // Gray mSpot
- openLineColor = color.new(#00ff00, 50) // Green open line
- // --- Period Separator Inputs ---
- showSeparators = input.bool(true, "Show Period Separators")
- sepColorInput = input.color(color.gray, "Separator Color", group="Period Separators")
- sepStyleInput = input.string("Dotted", "Separator Style", options=["Solid", "Dashed", "Dotted"], group="Period Separators")
- sepWidthInput = input.int(1, "Separator Width", minval=1, group="Period Separators")
- sepMode = input.string("Historical", options=["Historical", "Present"], title="Separator Mode", group="Period Separators")
- // --- HTF Variables Arrays ---
- var float[] htfHigh = array.new_float(3, na)
- var float[] htfLow = array.new_float(3, na)
- var float[] htfOpen = array.new_float(3, na)
- var float[] htfClose = array.new_float(3, na)
- var int[] htfBarIndex = array.new_int(3, na)
- var float[] prevmSpotValue = array.new_float(3, na)
- var float[] prevOpen = array.new_float(3, na)
- var box[] currentBoxes = array.new_box(3, na)
- var line[] currentLines = array.new_line(3, na)
- var line[] currentOpenLines = array.new_line(3, na)
- var label[] currentLabels = array.new_label(3, na) // Array to store current labels
- // Timeframes array
- timeframes = array.from(timeframe1, timeframe2, timeframe3)
- // --- Period Separator Variables ---
- var line[] separators = array.new_line()
- // Get line style function
- getLineStyle(string styleInput) =>
- switch styleInput
- "Solid" => line.style_solid
- "Dashed" => line.style_dashed
- "Dotted" => line.style_dotted
- => line.style_dotted
- // Pre-calculate HTF time changes outside the loop
- htfTime1 = request.security(syminfo.tickerid, timeframe1, time)
- htfTime2 = request.security(syminfo.tickerid, timeframe2, time)
- htfTime3 = request.security(syminfo.tickerid, timeframe3, time)
- changeHTF1 = ta.change(htfTime1) != 0
- changeHTF2 = ta.change(htfTime2) != 0
- changeHTF3 = ta.change(htfTime3) != 0
- // Pre-calculate separator time change
- separatorTime = request.security(syminfo.tickerid, separatorTF, time)
- changeSeparatorTF = ta.change(separatorTime) != 0
- // Helper function to determine label Y position
- getLabelYPos(float top, float bottom, string position) =>
- switch position
- "Top" => top
- "Middle" => (top + bottom) / 2
- "Bottom" => bottom
- => (top + bottom) / 2 // Default to middle
- // Main logic for each timeframe
- for i = 0 to numBoxes - 1
- if i < array.size(timeframes)
- tf = array.get(timeframes, i)
- // Get the pre-calculated change flag for this timeframe
- bool changeHTF = i == 0 ? changeHTF1 : i == 1 ? changeHTF2 : changeHTF3
- // Create security context for each timeframe
- htfOpenVal = request.security(syminfo.tickerid, tf, open)
- htfHighVal = request.security(syminfo.tickerid, tf, high)
- htfLowVal = request.security(syminfo.tickerid, tf, low)
- htfCloseVal = request.security(syminfo.tickerid, tf, close)
- barIndex = bar_index + 1
- if changeHTF
- // --- A new HTF bar has started ---
- highVal = array.get(htfHigh, i)
- lowVal = array.get(htfLow, i)
- openVal = array.get(htfOpen, i)
- closeVal = array.get(htfClose, i)
- barIdx = array.get(htfBarIndex, i) + 1
- prevMSpot = array.get(prevmSpotValue, i)
- prevOpn = array.get(prevOpen, i)
- if not na(highVal) and not na(lowVal)
- // Calculate current period's mSpot
- float currentmSpotValue = math.avg(highVal, lowVal)
- // Draw mSpot line using previous mSpot (shifted display)
- if not na(prevMSpot)
- if mSpotShow
- line.new(x1=barIdx, y1=prevMSpot, x2=barIndex, y2=prevMSpot, xloc=xloc.bar_index, color=mSpotColor, style=mSpotStyle, width=mSpotWidth)
- // Determine box color based on direction from previous open to previous mSpot
- bool boxBullish = false
- if not na(prevOpn) and not na(prevMSpot)
- boxBullish := prevOpn > prevMSpot // Upward = Bearish, Downward = Bullish
- BGColor = boxBullish ? boxBearishColor : boxBullishColor
- // Draw box using CURRENT open and PREVIOUS mSpot
- boxCreated = box(na)
- if BoxShow and not na(openVal) and not na(prevMSpot)
- boxCreated := box.new(left=barIdx, top=math.max(openVal, prevMSpot), right=barIndex, bottom=math.min(openVal, prevMSpot), border_width=BoxWidth, border_style=BoxLineStyle, border_color=boxBorderColor, bgcolor=BGColor)
- // --- Draw Timeframe Label for the *previous* HTF bar ---
- if showLabels and not na(boxCreated) and not na(tf)
- labelY = getLabelYPos(math.max(openVal, prevMSpot), math.min(openVal, prevMSpot), labelPosition)
- label.new(x=barIdx + (barIndex - barIdx) / 2, y=labelY, text=tf, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_center, textcolor=labelColor, size=labelSize, color=labelBgColor)
- // Draw open line using current open
- if OpenLineShow and not na(openVal)
- line.new(x1=barIdx, y1=openVal, x2=barIndex , y2=openVal, xloc=xloc.bar_index, color=openLineColor, style=OpenLineStyle, width=OpenLineWidth)
- // Store current values for next period
- array.set(prevmSpotValue, i, currentmSpotValue)
- array.set(prevOpen, i, openVal)
- // Store data points for the *new* HTF bar
- array.set(htfOpen, i, htfOpenVal)
- array.set(htfClose, i, htfCloseVal)
- array.set(htfBarIndex, i, bar_index)
- array.set(htfHigh, i, htfHighVal)
- array.set(htfLow, i, htfLowVal)
- else if bar_index > 0
- // --- The current HTF bar continues ---
- highVal = array.get(htfHigh, i)
- lowVal = array.get(htfLow, i)
- closeVal = array.get(htfClose, i)
- htfHighCurrent = request.security(syminfo.tickerid, tf, high)
- htfLowCurrent = request.security(syminfo.tickerid, tf, low)
- htfCloseCurrent = request.security(syminfo.tickerid, tf, close)
- array.set(htfHigh, i, math.max(highVal, htfHighCurrent))
- array.set(htfLow, i, math.min(lowVal, htfLowCurrent))
- array.set(htfClose, i, htfCloseCurrent)
- // Handle last bar updates
- if barstate.islast and bar_index > 0
- // Clean up temporary "current" objects from previous iterations
- boxToDelete = array.get(currentBoxes, i)
- lineToDelete1 = array.get(currentLines, i)
- lineToDelete2 = array.get(currentOpenLines, i)
- labelToDelete = array.get(currentLabels, i) // Get label to delete
- if not na(boxToDelete)
- box.delete(boxToDelete)
- if not na(lineToDelete1)
- line.delete(lineToDelete1)
- if not na(lineToDelete2)
- line.delete(lineToDelete2)
- if not na(labelToDelete) // Delete label
- label.delete(labelToDelete)
- // Redraw final elements for the *current* HTF bar on the last chart bar
- highVal = array.get(htfHigh, i)
- lowVal = array.get(htfLow, i)
- openVal = array.get(htfOpen, i)
- closeVal = array.get(htfClose, i)
- barIdx = array.get(htfBarIndex, i)
- prevMSpot = array.get(prevmSpotValue, i)
- prevOpn = array.get(prevOpen, i)
- if not na(highVal) and not na(lowVal)
- float currentmSpotValue = math.avg(highVal, lowVal)
- // Draw mSpot line using previous mSpot (shifted display)
- if not na(prevMSpot)
- if mSpotShow
- newLine = line.new(x1=barIdx, y1=prevMSpot, x2=barIndex, y2=prevMSpot, xloc=xloc.bar_index, color=mSpotColor, style=mSpotStyle, width=mSpotWidth)
- array.set(currentLines, i, newLine)
- // Determine box color based on direction from previous open to previous mSpot
- bool boxBullish = false
- if not na(prevOpn) and not na(prevMSpot)
- boxBullish := prevOpn > prevMSpot // Upward = Bearish, Downward = Bullish
- BGColor = boxBullish ? boxBearishColor : boxBullishColor
- // Draw box using CURRENT open and PREVIOUS mSpot
- newBoxCreated = box(na)
- if BoxShow and not na(openVal) and not na(prevMSpot)
- newBoxCreated := box.new(left=barIdx, top=math.max(openVal, prevMSpot), right=barIndex, bottom=math.min(openVal, prevMSpot), border_width=BoxWidth, border_style=BoxLineStyle, border_color=boxBorderColor, bgcolor=BGColor)
- array.set(currentBoxes, i, newBoxCreated)
- // --- Draw Timeframe Label for the *current* HTF bar ---
- newLabelCreated = label(na)
- if showLabels and not na(newBoxCreated) and not na(tf)
- labelY = getLabelYPos(math.max(openVal, prevMSpot), math.min(openVal, prevMSpot), labelPosition)
- newLabelCreated := label.new(x=barIdx + (barIndex - barIdx) / 2, y=labelY, text=tf, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_center, textcolor=labelColor, size=labelSize, color=labelBgColor)
- array.set(currentLabels, i, newLabelCreated) // Store the new label object
- // Draw open line using current open
- if OpenLineShow and not na(openVal)
- newOpenLine = line.new(x1=barIdx, y1=openVal, x2=barIndex, y2=openVal, xloc=xloc.bar_index, color=openLineColor, style=OpenLineStyle, width=OpenLineWidth)
- array.set(currentOpenLines, i, newOpenLine)
- // --- Period Separator Logic for Selected Timeframe ---
- if changeSeparatorTF and showSeparators
- new_separator = line.new(x1=bar_index, x2=bar_index, y1=high + syminfo.mintick, y2=low - syminfo.mintick, extend=extend.both, color=sepColorInput, style=getLineStyle(sepStyleInput), width=sepWidthInput)
- array.push(separators, new_separator)
- if sepMode == "Present" and array.size(separators) > 1
- line_to_delete = array.shift(separators)
- line.delete(line_to_delete)
Advertisement
Add Comment
Please, Sign In to add comment