Reputation: 1
I've tried to modify the code below Swing Points By:tufedtm in term of my desired conditions. Since I'm not familiar with arrays and I am rookie in coding, may I write what I'm expect may be you can guide me if it's possible?
The complete code customized a little bit be myself:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © tufedtm
//@version=5
indicator(title='Swing Points', shorttitle='Swing H/L', overlay=true, max_lines_count=500, max_labels_count=500)
len = input.int(title='swingSize Length', defval=1, minval=1) //Allows users to specify the lookback period for identifying swing highs/lows.
point_max = input.int(title='Maximum Points Displayed', defval=50, minval=0, maxval=250) //Sets a cap on the number of swing points displayed
show_high = input.bool(title='Swing High', defval=true, inline='show', group='Show pivots?')
show_low = input.bool(title='Swing Low', defval=true, inline='show', group='Show pivots?')
show_lines = input.bool(title='Horizontal Lines', defval=true, inline='show', group='Show pivots?')
//Decide whether to delete pivot labels once the price crosses them.
del_high = input.bool(title='Crossed Swing Highs', defval=true, inline='del', group='Delete crossed pivot Lines?')
del_low = input.bool(title='Crossed Swing Lows', defval=true, inline='del', group='Delete crossed pivot Lines?')
//Users can specify the color and shape for swing high/low markers.
color_high = input.color(title='MSH Label Color', defval=#42af03bf, inline='Line style', group='Label style')
style_high_option = input.string(title='MSH Labels Style', defval='Triangle down (▼)', options=['Triangle up (▲)', 'Triangle down (▼)', 'Arrow up (↑)', 'Arrow down (↓)', 'Label up (⬆)', 'Label down (⬇)', 'Plus (+)', 'Cross (⨯)', 'Circle (●)', 'Diamond (◆)', 'Flag (⚑)', 'Square (■)', 'None'], inline='Label style', group='Label style')
color_low = input.color(title='MSL Label Color', defval=#b60303bf, inline='Line style', group='Label style')
style_low_option = input.string(title='MSL Labels Style', defval='Triangle up (▲)', options=['Triangle up (▲)', 'Triangle down (▼)', 'Arrow up (↑)', 'Arrow down (↓)', 'Label up (⬆)', 'Label down (⬇)', 'Plus (+)', 'Cross (⨯)', 'Circle (●)', 'Diamond (◆)', 'Flag (⚑)', 'Square (■)', 'None'], inline='Label style', group='Label style')
//Define color and style for lines connecting swing points.
line_high_color = input.color(title='MSH Line Color', defval=#42af03bf, inline='line style', group='Line style')
line_high_style_option = input.string(title='MSH Lines Style', defval='solid (─)', options=['solid (─)', 'dotted (┈)', 'dashed (╌)', 'arrow left (←)', 'arrow right (→)', 'arrows both (↔)'], inline='line style', group='Line style')
line_low_color = input.color(title='MSL Line Color', defval=#b60303bf, inline='line style', group='Line style')
line_low_style_option = input.string(title='MSL Lines Style', defval='solid (─)', options=['solid (─)', 'dotted (┈)', 'dashed (╌)', 'arrow left (←)', 'arrow right (→)', 'arrows both (↔)'], inline='line style', group='Line style')
lineWid = input.int(1, 'All Lines Width', inline='line style', group='Line style')
//Specifies how lines are styled when they are crossed by price.
line_crossed_style_option = input.string(title='Crossed Line Style', defval='dotted (┈)', options=['solid (─)', 'dotted (┈)', 'dashed (╌)', 'arrow left (←)', 'arrow right (→)', 'arrows both (↔)'], inline='line style', group='Line style')
//Detects swing highs and lows based on the len lookback period using ta.pivothigh and ta.pivotlow.
pivhi = ta.pivothigh(high, len, len)
pivlo = ta.pivotlow(low, len, len)
//Maps user-selected options (e.g., "Triangle down (▼)") to corresponding built-in label/line styles.
var style_high = (style_high_option == 'Triangle up (▲)') ? label.style_triangleup :
(style_high_option == 'Triangle down (▼)') ? label.style_triangledown :
(style_high_option == 'Arrow up (↑)') ? label.style_arrowup :
(style_high_option == 'Arrow down (↓)') ? label.style_arrowdown :
(style_high_option == 'Label up (⬆)') ? label.style_label_up :
(style_high_option == 'Label down (⬇)') ? label.style_label_down :
(style_high_option == 'Plus (+)') ? label.style_cross:
(style_high_option == 'Cross (⨯)') ? label.style_xcross :
(style_high_option == 'Circle (●)') ? label.style_circle :
(style_high_option == 'Diamond (◆)') ? label.style_diamond :
(style_high_option == 'Flag (⚑)') ? label.style_flag :
(style_high_option == 'Square (■)') ? label.style_square :
(style_high_option == 'None') ? label.style_none :
label.style_triangledown
var style_low = (style_low_option == 'Triangle up (▲)') ? label.style_triangleup :
(style_low_option == 'Triangle down (▼)') ? label.style_triangledown :
(style_low_option == 'Arrow up (↑)') ? label.style_arrowup :
(style_low_option == 'Arrow down (↓)') ? label.style_arrowdown :
(style_low_option == 'Label up (⬆)') ? label.style_label_up :
(style_low_option == 'Label down (⬇)') ? label.style_label_down :
(style_low_option == 'Plus (+)') ? label.style_cross:
(style_low_option == 'Cross (⨯)') ? label.style_xcross :
(style_low_option == 'Circle (●)') ? label.style_circle :
(style_low_option == 'Diamond (◆)') ? label.style_diamond :
(style_low_option == 'Flag (⚑)') ? label.style_flag :
(style_low_option == 'Square (■)') ? label.style_square :
(style_low_option == 'None') ? label.style_none :
label.style_triangleup
var line_high_style = (line_high_style_option == 'dotted (┈)') ? line.style_dotted :
(line_high_style_option == 'dashed (╌)') ? line.style_dashed :
(line_high_style_option == 'arrow left (←)') ? line.style_arrow_left :
(line_high_style_option == 'arrow right (→)') ? line.style_arrow_right :
(line_high_style_option == 'arrows both (↔)') ? line.style_arrow_both :
line.style_solid
var line_low_style = (line_low_style_option == 'dotted (┈)') ? line.style_dotted :
(line_low_style_option == 'dashed (╌)') ? line.style_dashed :
(line_low_style_option == 'arrow left (←)') ? line.style_arrow_left :
(line_low_style_option == 'arrow right (→)') ? line.style_arrow_right :
(line_low_style_option == 'arrows both (↔)') ? line.style_arrow_both :
line.style_solid
var line_crossed_style = (line_crossed_style_option == 'solid (─)') ? line.style_solid :
(line_crossed_style_option == 'dashed (╌)') ? line.style_dashed :
(line_crossed_style_option == 'arrow left (←)') ? line.style_arrow_left :
(line_crossed_style_option == 'arrow right (→)') ? line.style_arrow_right :
(line_crossed_style_option == 'arrows both (↔)') ? line.style_arrow_both :
line.style_dotted
//Store references to all created labels and lines for later manipulation.
var label[] high_labels = array.new_label()
var label[] low_labels = array.new_label()
var line[] high_lines = array.new_line()
var line[] low_lines = array.new_line()
//Updates lines to extend dynamically as new bars appear, or change their style if crossed by price.
replot_line(lines) => //This function dynamically updates lines in the lines array. It extends the line to the current bar (bar_index) or changes its style if the price has crossed the line. (lines) Accepts an array of line objects that represent plotted lines on the chart.
if array.size(lines) > 0 //Ensures the function only processes if there are lines in the lines array. If the array is empty, there is nothing to update, and the function will exit.
for i = array.size(lines) - 1 to 0 by 1 //Starts from the most recently added line (highest index) and iterates backward to the oldest line. This ensures any deletions or modifications do not disrupt the loop (as modifying an array can change its size).
line_ = array.get(lines, i) //Retrieves the line object at index i from the lines array.
y1 = line.get_y1(line_) //Gets the first Y-coordinate (y1) of the line, which represents the price level where the line starts.
if bar_index == line.get_x2(line_) and not( close > y1 and open < y1 ) //Verifies if the line currently ends at the current bar (bar_index). This ensures that only lines actively extending with price are processed. //not( close > y1 and open < y1 ): Ensures the price does not cross the line. If the line's Y-coordinate (y1) lies between the current close and open(not wicks), the line has been crossed.
line.set_x2(line_, bar_index + 1) //If the price has not crossed the line and the line is still active, it extends the line to one bar beyond the current bar (bar_index + 1). //Why: Keeps the line updated with new price bars dynamically.
else
line.set_style(line_, line_crossed_style) //If the price crosses the line, it changes the line's style to the user-specified. Visually marks the line as "crossed" to differentiate it from active lines.
if show_high and not na(pivhi) //Checks if the user enabled display of swing highs/lows and if the pivot is valid (not na).
array.push(high_labels, label.new(bar_index - len, high[len], yloc=yloc.abovebar, color=color_high, style=style_high, size=size.auto))
if show_lines
array.push(high_lines, line.new(x1=bar_index - len, y1=high[len], x2=bar_index, y2=high[len], extend = extend.right, color=line_high_color, style=line_high_style, width = lineWid))
if show_low and not na(pivlo) //Checks if the user enabled display of swing highs/lows and if the pivot is valid (not na).
array.push(low_labels, label.new(bar_index - len, low[len], yloc=yloc.belowbar, color=color_low, style=style_low, size=size.auto))
if show_lines
array.push(low_lines, line.new(x1=bar_index - len, y1=low[len], x2=bar_index, y2=low[len], extend = extend.right, color=line_low_color, style=line_low_style, width = lineWid))
////Deletes labels and lines when price crosses swing points if deletion is enabled.
if array.size(high_labels) > 0 //Ensures there are labels in the high_labels array before proceeding. If the array is empty, the deletion logic is skipped. Avoids unnecessary computations and prevents errors when trying to access elements in an empty array.
for i = array.size(high_labels) - 1 to 0 //The loop starts from the last (most recently added) label and iterates backward. This is crucial because deleting elements from an array reduces its size, and reverse iteration avoids index shifting issues.
if del_high and high > label.get_y(array.get(high_labels, i)) //(del_high) Ensures the deletion of labels is enabled via user input. high > label.get_y(...): Checks if the current high price exceeds the Y-coordinate of the label. If true, the price has crossed the swing high.
label.delete(array.get(high_labels, i)) //Deletes the label from the chart. Once the price crosses the label's level, it is no longer relevant, so it is removed to keep the chart clean.
array.remove(high_labels, i) //Removes the label reference from the high_labels array. Keeps the array in sync with the actual labels displayed on the chart.
if show_lines //Only executes if the user has enabled line display for swing points.
line.delete(array.get(high_lines, i)) // Removes the line corresponding to the deleted label from the chart.
array.remove(high_lines, i) //Removes the line reference from the high_lines array to maintain consistency.
////Deletes labels and lines when price crosses swing points if deletion is enabled.
if array.size(low_labels) > 0 //Ensures there are labels in the low_labels array before proceeding. If the array is empty, the deletion logic is skipped. Avoids unnecessary computations and prevents errors when trying to access elements in an empty array.
for i = array.size(low_labels) - 1 to 0 //The loop starts from the last (most recently added) label and iterates backward. This is crucial because deleting elements from an array reduces its size, and reverse iteration avoids index shifting issues.
if del_low and low < label.get_y(array.get(low_labels, i)) //(del_low) Ensures the deletion of labels is enabled via user input. low > label.get_y(...): Checks if the current low price exceeds the Y-coordinate of the label. If true, the price has crossed the swing low.
label.delete(array.get(low_labels, i)) //Deletes the label from the chart. Once the price crosses the label's level, it is no longer relevant, so it is removed to keep the chart clean.
array.remove(low_labels, i) ////Removes the label reference from the low_labels array. Keeps the array in sync with the actual labels displayed on the chart.
if show_lines //Only executes if the user has enabled line display for swing points.
line.delete(array.get(low_lines, i)) // Removes the line corresponding to the deleted label from the chart.
array.remove(low_lines, i) //Removes the line reference from the low_lines array to maintain consistency.
//Removes the oldest labels/lines if the count exceeds point_max.
if array.size(high_labels) > point_max
label.delete(array.shift(high_labels))
if show_lines
line.delete(array.shift(high_lines))
if array.size(low_labels) > point_max
label.delete(array.shift(low_labels))
if show_lines
line.delete(array.shift(low_lines))
//Ensures all lines remain dynamic and reflect current price action.
if show_lines
replot_line(high_lines)
replot_line(low_lines)
The code works good and shows number of Swing highs/lows =Point_max
as shown in the screenshot below:
As it can be seen, several last Swing highs (Green lines) and Swing lows (Red lines) based on 3 candles are being plotted. What I'm expecting is something like this:
"Imagine there are arrays that keep horizontal lines for Swing highs and lows with length=1 (swing in 3 candles patern) and for max 500 bars ago, but wait and do not plot lines. when a candle closed above the swing high, then, for the first and next confirmed swing high, after that specific closing candle bar, a green line will be plotted, previous broken swing high will be deleted and also a red line for the previous and nearest swing low before that closing candle will be plotted. Same, if a candle closed below the swing low, then, for the next confirmed swing low after that crossing candle, a red line will be plotted, the previous broken swing low will be deleted, and also a green line for the previous and nearest congirmed swing high before that candle will be plotted. This process is being continued to the current time and that means everytime we only have two lines, one swing high and one swing low but according to mentioned conditions."
Since I'm not a code developer, I've tried several codes and tried to modify them in term of my circumstances, finally I found out Arrays are what I need but I was not successful in that.
Images below illustrate almost what I'm expecting.
Image 1:
Image 2:
Image 3:
Image 4:
Image 5:
I'll be very appreciated for your attention and guides.
Upvotes: 0
Views: 79