Warning: Declaration of ElementorPro\Modules\Posts\Skins\Skin_Content_Base::register_controls(Elementor\Widget_Base $widget) should be compatible with Elementor\Controls_Stack::register_controls() in /home/customer/www/backtest-rookies.com/public_html/wp-content/plugins/elementor-pro/modules/theme-builder/widgets/post-content.php on line 17
Trend lines in pine script can be tricky to develop. Not only do they require a bit more mathematics than we would usually care to wrap our brains around, but they also require us to use some more advanced pine script techniques such as creating functions. This article will provide a complete working example of how to do that and explain how the code should be used. If you want to create a strategy that relies on trend lines for entry and exit triggers, then this article is for you!
Don’t worry, you don’t need to fully understand the mathematics behind how a trend line is determined to make use of the code. At a minimum, you just need to know what each line is doing and then copy and paste the code.
Having said that, for the sake of completeness, we should still discuss the mathematics in some detail. If you do not care for the mechanics you can skip straight to the code section. Then read the first part of the commentary to get a basic overview of what is happening. For the rest of you, here we go…
The main objective is to calculate the price of a trend line at any point in time. To do this, we need to calculate how fast the slope of the trend changes between two points in time. We then use that slope to calculate trend levels at any point in time. The two “points in time” are prices and dates that we will grab from the chart where price swings significantly.
The following equation is what you will find around the web to calculate the next value of a trend line.
y = price
m = slope
x = date / time
b = y-intercept
You may notice that just having the price and dates our two “points in time” do not give us the
y-intercept. This is where things can be a bit tricky. This equation and most tutorials online assume you can visually see the
y-intercept. To help you visualize this, the
y-intercept is the value of y when it crosses the y-axis at 0. Like this:
As you will no doubt be aware, on a price chart we never see the
y-intercept. So to get around this, we just need to calculate it! To do this you need to flip the equation around a bit.
b = y – m*x
You might think, “hang on! I don’t have Y yet, that is what I am trying to get! So how can I solve this?”. Well, when we try to calculate
b, we can use the
x values you already have from the most recent known swing point in the trend line! If that still does not make sense, don’t worry, you will see how this works in the code example below…
After we have the
bas it is known in the equation) the rest is straightforward.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © BacktestRookies //@version=4 study("Trendlines", shorttitle='BTL', overlay=true) leftbars = input(100, minval=1, title='Pivot Detection: Left Bars') rightbars = input(15, minval=1, title='Pivot Detection: Right Bars') plotpivots = input(true, title='Plot Pivots') // Pivots ph = pivothigh(high, leftbars, rightbars) pl = pivotlow(low, leftbars, rightbars) phv1 = valuewhen(ph, high[rightbars], 0) phb1 = valuewhen(ph, bar_index[rightbars], 0) phv2 = valuewhen(ph, high[rightbars], 1) phb2 = valuewhen(ph, bar_index[rightbars], 1) plv1 = valuewhen(pl, low[rightbars], 0) plb1 = valuewhen(pl, bar_index[rightbars], 0) plv2 = valuewhen(pl, low[rightbars], 1) plb2 = valuewhen(pl, bar_index[rightbars], 1) plotshape(ph, style=shape.circle, location=location.abovebar, color=color.orange, title='Pivot High', offset=-rightbars) plotshape(pl, style=shape.circle, location=location.belowbar, color=color.blue, title='Pivot Low', offset=-rightbars) plot(ph ? high[rightbars] : na, color=color.orange, offset=-rightbars) plot(pl ? low[rightbars] : na, color=color.purple, offset=-rightbars) // TRENDLINE CODE // -------------- get_slope(x1,x2,y1,y2)=> m = (y2-y1)/(x2-x1) get_y_intercept(m, x1, y1)=> b=y1-m*x1 get_y(m, b, ts)=> Y = m * ts + b int res_x1 = na float res_y1 = na int res_x2 = na float res_y2 = na int sup_x1 = na float sup_y1 = na int sup_x2 = na float sup_y2 = na // Resistance res_x1 := ph ? phb1 : res_x1 res_y1 := ph ? phv1 : res_y1 res_x2 := ph ? phb2 : res_x2 res_y2 := ph ? phv2 : res_y2 res_m = get_slope(res_x1,res_x2,res_y1,res_y2) res_b = get_y_intercept(res_m, res_x1, res_y1) res_y = get_y(res_m, res_b, bar_index) // Support sup_x1 := pl ? plb1 : sup_x1 sup_y1 := pl ? plv1 : sup_y1 sup_x2 := pl ? plb2 : sup_x2 sup_y2 := pl ? plv2 : sup_y2 sup_m = get_slope(sup_x1,sup_x2,sup_y1,sup_y2) sup_b = get_y_intercept(sup_m, sup_x1, sup_y1) sup_y = get_y(sup_m, sup_b, bar_index) // plot(line.get_y2(line1)) plot(res_y, color=color.red, title='Resistance Trendline', linewidth=2, style=plot.style_circles) plot(sup_y, color=color.lime, title='Support Trendline', linewidth=2, style=plot.style_circles) if ph line.new(phb1,phv1, bar_index, res_y, style=line.style_dashed, color=color.blue) if pl line.new(plb1,plv1, bar_index, sup_y, style=line.style_dashed, color=color.blue) // Breaks long_break = crossover(close, res_y) short_break = crossunder(close, sup_y) plotshape(long_break, style=shape.triangleup, color=color.green, size=size.tiny, location=location.belowbar, title='Long Break') plotshape(short_break, style=shape.triangledown, color=color.red, size=size.tiny, location=location.abovebar, title='Short Break') alertcondition(long_break, title='Long Breakout') alertcondition(short_break, title='Short Breakout')
A general explanation of the indicator would be a good place to start. In it, we plot two trend lines at any given time. A resistance trend line and a support trend line. The resistance trend is shown with red circles and is created by joining swing highs together. The second is a support trend which is created by joining swing lows.
Since we need swings to make the trend, the trend line code contains code for the swing detection. You can play around with the swing detection to alter how frequently new trend lines are detected. Relying on swings also means that there will be some delay in trend detection depending on how you configure the swing detection. The higher you set
rightbars, the more lag you will have before a trend is detected. However, at the same time the quality of the pivots found will increase. So it is a trade-off you need to come to terms with and decide what the best settings are for you.
Trend line Anatomy
A single trend line is made up of several components.
- Pivot Points: Marked as blue or orange circles. There will be two pivots per trend.
- Orange/Purple Lines: Connecting all pivot points. You will see these lines change direction slightly each time a new pivot is detected (new circles appear).
- Green/Red Circle lines: Showing the trend line from the earliest moment a new trend is detected.
- Blue Dashed lines: Joining the purple and green/red circle lines so the full trend line can be seen.
Note: The blue dashed lines use pine-scripts drawing functions. As such, there is a limit to how many of these can be placed on a chart. When the limit is reached, the oldest line will be removed so the newest can be drawn. This means that if you detect enough trends and scroll back in time, the blue dashed lines will disappear at some point!
Trend Line Functions
Taking a closer look at the code, we have 3 core functions which we just need to provide the right values to generate the trend lines. These are:
// TRENDLINE CODE // -------------- get_slope(x1,x2,y1,y2)=> m = (y2-y1)/(x2-x1) get_y_intercept(m, x1, y1)=> b=y1-m*x1 get_y(m, b, ts)=> Y = m * ts + b
We then just need to get the pivot prices and bar numbers and plumb them in. We start with
get_slope()and provide the details for the last two pivots. This will then return
m(the slope) that can be used to get the
y-intercept. From there we now have
y-intercept) that can be used to get the
yvalue on the chart of the next expected trend line value. This calculated by providing
b along with the current bar number using
bar_index. In fact, you could use this function to calculate where the line would be at any given point in time by replacing
bar_index with any bar number past or future.
This code can be picked up and played with. Readers may want to try replacing the pivot detection with another method to detect some reasonable anchor points for the trend. Alternatively, readers may wish to incorporate part of all of it into a strategy for backtest.
Find This Post Useful?
If this post saved you time and effort, please consider support the site! There are many ways to support us and some won’t even cost you a penny.