forked from Electrified-Trading/Libraries
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMovingAverages.pine
205 lines (188 loc) · 7.18 KB
/
MovingAverages.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
// 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 for generating moving average values including getting a moving average by name and a function for generating a Volume-Adjusted WMA.
library('MovingAverages', true)
isLenInvalid(simple int len, simple string name = 'len') =>
if na(len)
runtime.error("The '"+name+"' param cannot be NA.")
true
else if len < 0
runtime.error("The '"+name+"' param cannot be negative.")
true
else if len == 0
true
else
false
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VAWMA = VWMA and WMA combined.
// Simply put, this attempts to determine the average price per share over time weighted heavier for recent values.
// Uses triangular algorithm to taper off values in the past (same as WMA does).
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function VAWMA = VWMA and WMA combined. Simply put, this attempts to determine the average price per share over time weighted heavier for recent values. Uses a triangular algorithm to taper off values in the past (same as WMA does).
// @param len The number of bars to measure with.
// @param src The series to measure from. Default is 'hlc3'.
// @param volumeDefault The default value to use when a chart has no (N/A) volume.
// @returns The volume adjusted triangular weighted moving average of the series.
export vawma(
simple int len,
series float src = hlc3,
simple float volumeDefault = na,
simple int startingWeight = 1) =>
var float notAvailable = na
if isLenInvalid(len)
notAvailable
else
sum = 0.0
vol = 0.0
last = len - 1
for i = 0 to last
s = src[i]
v = volume[i]
if na(v) and not na(volumeDefault)
v := volumeDefault
if not na(s) and not na(v)
m = last - i + startingWeight
v *= m
vol += v
sum += s * v
vol == 0 ? na : sum/vol
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Coefficient Moving Avereage (CMA) is a variation of a moving average that can simulate SMA or WMA with the advantage of previous data.
// @param n The number of bars to measure with.
// @param D The series to measure from. Default is 'close'.
// @param C The coefficient to use when averaging. 0 behaves like SMA, 1 behaves like WMA.
// @param compound When true (default is false) will use a compounding method for weighting the average.
export cma(
simple int n,
series float D = close,
simple float C = 1,
simple bool compound = false) =>
var float notAvailable = na
if isLenInvalid(n, 'n')
notAvailable
else
var float result = na
sum = 0.0
weight = 1.0
weightTotal = 0.0
for m = 1 to n
s = D[n - m]
if not na(s)
sum := sum + s * weight
weightTotal += weight
if compound
weight *= 1 + C
else
weight += C
prev = result[n]
if na(prev)
result := sum / weightTotal
else
result := (prev + sum) / (weightTotal + 1)
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Same as ta.ema(src,len) but properly ignores NA values.
// @param len The number of samples to derive the average from.
// @param src The series to measure from. Default is 'close'.
export ema(
simple int len,
series float src = close) =>
var float notAvailable = na
if isLenInvalid(len)
notAvailable
else
var float alpha = 2 / (len + 1)
var float a1 = 1 - alpha
var float s = na
var float ema = na
if not na(src)
s := src
ema := alpha * s + a1 * nz(ema)
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Same as ta.wma(src,len) but properly ignores NA values.
// @param len The number of samples to derive the average from.
// @param src The series to measure from. Default is 'close'.
// @param startingWeight The weight to begin with when calculating the average. Higher numbers will decrease the bias.
export wma(
simple int len,
series float src = close,
simple int startingWeight = 1) =>
var float notAvailable = na
if isLenInvalid(len)
notAvailable
else
sum = 0.0
total = 0
last = len - 1
for i = 0 to last
s = src[i]
if not na(s)
m = last - i + startingWeight // triangular multiple
total += m
sum += s * m
total == 0 ? na : sum/total
///////////////////////////////////////////////////
///////////////////////////////////////////////////
// @function Same as ta.vwma(src,len) but properly ignores NA values.
// @param len The number of bars to measure with.
// @param src The series to measure from. Default is 'hlc3'.
// @param volumeDefault The default value to use when a chart has no (N/A) volume.
export vwma(
simple int len,
series float src = close,
simple float volumeDefault = na) =>
var float notAvailable = na
if isLenInvalid(len)
notAvailable
else
var sum = 0.0
var vol = 0.0
float datum = na
v = volume
if na(v) and not na(volumeDefault)
v := volumeDefault
if not na(src) and not na(v)
vol += v
datum := src * v
sum += datum
else
v := na
vStart = v[len]
dStart = datum[len]
if not na(vStart)
vol -= vStart
if not na(dStart)
sum -= dStart
vol == 0 ? na : sum/vol
///////////////////////////////////////////////////
SMA = 'SMA', EMA = 'EMA', WMA = 'WMA', CMA = 'CMA', VWMA = 'VWMA', VAWMA = 'VAWMA'
///////////////////////////////////////////////////
// @function Generates a moving average based upon a 'type'.
// @param type The type of moving average to generate. Values allowed are: SMA, EMA, WMA, VWMA and VAWMA.
// @param len The number of bars to measure with.
// @param src The series to measure from. Default is 'close'.
// @returns The moving average series requested.
export get(
simple string type,
simple int len,
series float src = close) =>
switch type
WMA => wma(len, src)
EMA => ema(len, src)
VWMA => vwma(len, src)
VAWMA => vawma(len, src)
CMA => cma(len, src)
SMA => ta.sma(src, len)
=>
runtime.error("No matching MA type found.")
ta.sma(src, len)
///////////////////////////////////////////////////
// Demo
plot(ema(20), 'ema(20)', color.red)
plot(wma(20), 'wma(20)', color.yellow)
plot(vwma(20), 'vwma(20)', color.blue)
plot(vawma(20), 'vawma(20)', color.purple)