-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathautotrendline.pine
More file actions
133 lines (118 loc) · 5.18 KB
/
autotrendline.pine
File metadata and controls
133 lines (118 loc) · 5.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// © radinansari
//@version=4
study("Auto trend line", overlay=true, max_bars_back=4000)
// === User settings ===
s_year = input(defval=2020, title="Start Year")
s_month = input(defval=1, title="Start Month")
s_day = input(defval=1, title="Start Day")
pivotLen = input(defval=20, title="Pivot Period", minval=10, maxval=50)
checkCount = input(defval=3, title="Pivot points to track", minval=2, maxval=6)
color_up = input(defval=color.lime, title="Uptrend color", inline="cols")
color_down = input(defval=color.red, title="Downtrend color", inline="cols")
// === Pivot detection ===
float ph = pivothigh(pivotLen, pivotLen)
float pl = pivotlow(pivotLen, pivotLen)
// storage for recent pivot values + indices (most recent at index 0)
var float[] highsArr = array.new_float(checkCount)
var int[] highsIdx = array.new_int(checkCount)
var float[] lowsArr = array.new_float(checkCount)
var int[] lowsIdx = array.new_int(checkCount)
// helper: push a value to head and drop the last element (keeps fixed size)
push_head_shift(arrVal, arrIdx, v) =>
array.unshift(arrVal, v)
array.unshift(arrIdx, bar_index)
array.pop(arrVal)
array.pop(arrIdx)
// when pivots appear, push them into arrays
if ph
push_head_shift(highsArr, highsIdx, ph)
if pl
push_head_shift(lowsArr, lowsIdx, pl)
// === lines: fixed-size pools to reuse/destroy each tick ===
maxLines = 3
var line[] upLines = array.new_line(maxLines, na)
var line[] dnLines = array.new_line(maxLines, na)
// prepare timestamp cutoff
tStart = timestamp(s_year, s_month, s_day, 0, 0)
if time < tStart
// nothing drawn before start date
na
// remove and (re)compute lines only after start date
if time >= tStart
// clean old lines each bar
for i = 0 to maxLines - 1
line.delete(array.get(upLines, i))
line.delete(array.get(dnLines, i))
usedUp = 0
usedDn = 0
// iterate candidate pivots as first point (older) against later pivot (newer)
for a = 0 to checkCount - 2
// ---------- lower trend (rising support) ----------
ux1 = 0.0
ux2 = 0.0
up1 = 0
up2 = 0
if usedUp < maxLines
for b = checkCount - 1 to a + 1
v1 = array.get(lowsArr, a)
v2 = array.get(lowsArr, b)
i1 = array.get(lowsIdx, a)
i2 = array.get(lowsIdx, b)
// want an ascending line from older (i2) to newer (i1)
if v1 > v2
slope = (v1 - v2) / float(i1 - i2)
// simulate progressive line from pivot2 forward
testPrice = v2 + slope
valid = true
lastBarIdx = bar_index
// check that price doesn't break below the projected line between pivots+some range
for idx = i2 + 1 - pivotLen to bar_index
// convert relative index to array-like access
if close[bar_index - idx] < testPrice
valid := false
break
lastBarIdx := idx
testPrice := testPrice + slope
if valid
ux1 := testPrice - slope // value at lastBarIdx
ux2 := v2 // value at i2 - start of line
up1 := lastBarIdx
up2 := i2
break
// ---------- upper trend (falling resistance) ----------
dx1 = 0.0
dx2 = 0.0
dp1 = 0
dp2 = 0
if usedDn < maxLines
for b = checkCount - 1 to a + 1
v1 = array.get(highsArr, a)
v2 = array.get(highsArr, b)
i1 = array.get(highsIdx, a)
i2 = array.get(highsIdx, b)
// for descending resistance line we need v1 < v2 (newer lower than older)
if v1 < v2
slope = (v2 - v1) / float(i1 - i2)
testPrice = v2 - slope
valid = true
lastBarIdx = bar_index
for idx = i2 + 1 - pivotLen to bar_index
if close[bar_index - idx] > testPrice
valid := false
break
lastBarIdx := idx
testPrice := testPrice - slope
if valid
dx1 := testPrice + slope
dx2 := v2
dp1 := lastBarIdx
dp2 := i2
break
// draw lower (support) if found and pool not full
if up1 != 0 and up2 != 0 and usedUp < maxLines
array.set(upLines, usedUp, line.new(up2 - pivotLen, ux2, up1, ux1, color=color_up))
usedUp := usedUp + 1
// draw upper (resistance) if found and pool not full
if dp1 != 0 and dp2 != 0 and usedDn < maxLines
array.set(dnLines, usedDn, line.new(dp2 - pivotLen, dx2, dp1, dx1, color=color_down))
usedDn := usedDn + 1