forked from Electrified-Trading/Libraries
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMomentumSignals.pine
215 lines (189 loc) · 8.06 KB
/
MomentumSignals.pine
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Electrified (electrifiedtrading)
// @version=5
// @description Contains utilities varying algorithms for detecting key changes in momentum. Note: Momentum is not velocity and should be used in conjunction with other indicators. A change in momentum does not mean a reversal of velocity or trend.
library('MomentumSignals')
import Electrified/Momentum/5
quantize(float value, simple int up = 1, simple int dn = -1) =>
na(value) ? na : value > 0 ? up : value < 0 ? dn : 0
signalOnly(
series float s) =>
quantize(ta.change(s))
// Changes in direction at the key.
reverseSignalOnly(
series float s,
simple int len = 2) =>
c = ta.change(s, len)
if c > 0 and s < 0
+1
else if c < 0 and s > 0
-1
else
0
// Simplified super-trend algo
trend(series float h, series float d, int len, float m = 1) =>
var lo = h
var hi = h
var direction = 0
if na(lo)
lo := h
if na(hi)
hi := h
std = ta.stdev(d, len)
if h > hi
direction := +1
hi := h
lo := h - std * m
else if h < lo
direction := -1
lo := h
hi := h + std * m
[direction, std]
////
///////////////////////////////////////////////////
// @function Compares two series for changes in momentum to derive signal values.
// @param primary The primary series (typically a moving average) to look for changes in momentum.
// @param secondary The secondary series (typically derived moving average of the primary) to use as a comparison value.
// @param len The number of bars to measure the change in momentum.
export simple(
series float primary,
series float secondary) =>
p = signalOnly(primary)
s = signalOnly(secondary)
h = primary - secondary // similar to the histogram in MACD.
d = ta.change(h)
x = quantize(d)
p + s + x
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Compares two series for changes in momentum to derive signal values. Uses statistics to filter out changes in momentum.
// @param primary The primary series (typically a moving average) to look for changes in momentum.
// @param secondary The secondary series (typically derived moving average of the primary) to use as a comparison value.
// @param len The number of bars to measure the change in momentum.
// @param stdlen The number of bars to measure the change in momentum for filtering.
// @param stdMultiple The multiple of the change in momentum to use before reversiing.
export filtered(
series float primary,
series float secondary,
simple int stdlen = 200,
simple float stdMultiple = 3.5) =>
p = signalOnly(primary)
s = signalOnly(secondary)
h = primary - secondary // similar to the histogram in MACD.
d = ta.change(h)
[t, std] = trend(h, d, stdlen, stdMultiple)
x = t > 0 and d < 0 or t < 0 and d > 0 ? 0 : quantize(d)
p + s + x
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Compares two series for changes in momentum to derive signal values. Uses statistics to filter out changes in momentum. Does not signal when likely overbought or oversold.
// @param primary The primary series (typically a moving average) to look for changes in momentum.
// @param secondary The secondary series (typically derived moving average of the primary) to use as a comparison value.
// @param stdlen The number of bars to measure the change in momentum for filtering.
// @param stdMultiple The multiple of the change in momentum to use before reversiing.
export special(
series float primary,
series float secondary,
simple int stdlen = 200,
simple float stdMultiple = 3.5) =>
p = signalOnly(primary)
s = signalOnly(secondary)
h = primary - secondary // similar to the histogram in MACD.
d = ta.change(h)
[t, std] = trend(h, d, stdlen, stdMultiple)
sm = std * stdMultiple / 2
x = t > 0 and d < 0 or t < 0 and d > 0 ? 0 : quantize(d)
r = p + s + x
// When the signal level has exceeded the histogram, signals become more risky.
r := primary > secondary and secondary > h or primary < secondary and secondary < h ? x : r
// Filter out noise.
r > 0 and primary > 0 and primary < secondary or r < 0 and primary < 0 and primary > secondary ? 0 : r
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Returns a signal value representing the stage of where the RSI is in its cycle.
// @param smoothK The length to average the stochastic.
// @param smoothD The length to smooth out K and produce D.
// @param rsiLen The length of the RSI.
// @param stochLen The length of stochastic.
// @param src The series to measure from. Default is 'close'.
// @param kmode The type of moving average to generate. Values allowed are: SMA, EMA, WMA, VWMA and VAWMA.
// @param upper The upper band of the range.
// @param lower The lower band of the range.
// @returns [signal, stage] Where stage is: +1 is oversold and rising, +2 rising above lower bound but less than mid. +3 rising above mid. +4 is overbought. Negative numbers are the reverse.
export stochRSI(
simple int smoothK = 3,
simple int smoothD = 3,
simple int rsiLen = 14,
simple int stochLen = 14,
series float src = close,
simple string kmode = "SMA",
simple float upper = 80,
simple float lower = 20,
simple float mid = 50) =>
[k, d] = Momentum.stochRSI(smoothK, smoothD, rsiLen, stochLen, src, kmode)
k_c = quantize(ta.change(k))
d_c = quantize(ta.change(d))
// Where are we?
var stage = 0
if stage != -1 and k > d and k > upper
stage := +4 // overbought
if stage != +1 and k < d and k < lower
stage := -4 // oversold
if stage == +4 and k < d and d_c < 0
stage := -1 // overbought and falling
if stage == -4 and k > d and d_c > 0
stage := +1 // oversold and rising
if stage == +1 and k > lower
stage := +2 // rising up
if stage == -1 and k < upper
stage := -2 // falling down
if stage == +2 and k > mid
stage := +3 // rising up high
if stage == -2 and k < mid
stage := -3 // falling down low
if stage == +3 and k < d and d < mid or stage == -3 and k > d and d > mid
stage := 0 // indeterminate
stage_c = ta.change(stage)
// Avoid noisy alignment...
signal = if k_c != d_c or k_c != quantize(k - d)
0
else
if stage == +2
(k_c + 1) * (stage_c > 0 ? 2 : 1)
else if stage == -2
(k_c - 1) * (stage_c < 0 ? 2 : 1)
else if d < lower
k_c < 0 ? 0 : k_c
else if d > upper
k_c > 0 ? 0 : k_c
else
k_c
[signal, stage]
///////////////////////////////////////////////////
// Example:
SMA = 'SMA', EMA = 'EMA', WMA = 'WMA', VWMA = 'VWMA', VAWMA = 'VAWMA'
[m, s, h] = Momentum.macd(
input.int(24, "MACD Length", minval=1),
input.int(52, "Signal Length", minval=1),
input.int(12, "Signal Smoothing", minval=1),
input.source(hlc3, "Source"),
input.string(WMA, "MACD MA Type", options=[SMA,EMA,WMA,VWMA,VAWMA]),
input.string(WMA, "Signal MA Type", options=[SMA,EMA,WMA,VWMA,VAWMA]))
stdLen = input.int(200, "StdDev Length", minval=1, tooltip="Length of standard deviation measurement of historgram change")
stdM = input.float(3.5, "StdDev Multiple", minval=0, step=0.5, tooltip="The number of standard deviations before momentum may have reversed")
plot(m, "MACD", color.blue)
plot(s, "Signal", color.yellow)
plot(h, "Histogram", color.gray, style=plot.style_columns)
signal = special(m, s, stdLen, stdM)
//plot(signal, "Signal", color.orange)
color signalColor = switch signal
+4 => color.new(color.green, 20)
+3 => color.new(color.green, 40)
+2 => color.new(color.green, 60)
+1 => color.new(color.green, 80)
-1 => color.new(color.red, 80)
-2 => color.new(color.red, 60)
-3 => color.new(color.red, 40)
-4 => color.new(color.red, 20)
=> na
bgcolor(signalColor)