forked from Electrified-Trading/Libraries
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDataCleaner.pine
150 lines (130 loc) · 6.51 KB
/
DataCleaner.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
// 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 Functions for acquiring outlier levels and deriving a cleaned version of a series.
library("DataCleaner")
//////////////////////////////////////////////////
// @function Gets the (standard deviation) outlier level for a given series.
// @param src The series to average and add a multiple of the standard deviation to.
// @param len The The number of bars to measure.
// @param level The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
// @returns The average of the series plus the multiple of the standard deviation.
export outlierLevel(
series float src,
simple int len,
simple float level)=>
if level == 0
runtime.error('Passing a level of (0) zero to "level" is simply the average.')
avg = ta.sma(src, len)
std = ta.stdev(src, len)
avg + std * level
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// @function Returns only values that are within the maximum deviation.
// @param src The series to filter results from.
// @param len The The number of bars to measure.
// @param maxDeviation The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
export naOutliers(
series float src,
simple int len,
simple float maxDeviation = 4)=>
if maxDeviation == 0
runtime.error('Passing a level of (0) zero to "maxDeviation" is simply the average.')
avg = ta.sma(src, len)
dev = ta.stdev(src, len) * maxDeviation
src > avg + dev or src < avg - dev ? na : src
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// @function Returns an array representing the result series with (outliers provided by the source) removed.
// @param src The source series to read from.
// @param result The result series.
// @param len The maximum size of the resultant array.
// @param maxDeviation The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
// @returns An array containing the cleaned series.
export cleanUsing(
series float src,
series float result,
simple int len,
simple float maxDeviation) =>
var cleaned = array.new_float()
if maxDeviation == 0
runtime.error('Cannot clean a series with a "maxDeviation" of (0) zero.')
cleaned
else
// Hold the previous value so it's not included in the set yet.
var raw = array.new_float()
var level = outlierLevel(src, len, maxDeviation)
// Is the value in bounds? Add it to the series.
if(maxDeviation > 0 and src < level or maxDeviation < 0 and src > level)
array.push(cleaned, result)
// Maxed out results?
if(array.size(cleaned) > len)
array.shift(cleaned)
level := outlierLevel(src, len, maxDeviation)
cleaned
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// @function Returns an array representing the source series with outliers removed.
// @param src The source series to read from.
// @param len The maximum size of the resultant array.
// @param maxDeviation The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
// @returns An array containing the cleaned series.
export clean(
series float src,
simple int len,
simple float maxDeviation) =>
cleanUsing(src, src, len, maxDeviation)
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// @function Returns an array representing the source array with outliers removed.
// @param src The source series to read from.
// @param maxDeviation The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
// @returns An array containing the cleaned series.
export cleanArray(
float[] src,
simple float maxDeviation) =>
if array.size(src)==0
src
else
avg = array.avg(src)
stdev = array.stdev(src)
cleaned = array.new_float()
last = array.size(src) - 1
level = stdev * maxDeviation
hi = avg + level
lo = avg - level
for i = 0 to last
v = array.get(src, i)
if lo < v and v < hi
array.push(cleaned, v)
cleaned
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// @function Gets the (standard deviation) outlier level for a given series after a single pass of removing any outliers.
// @param src The series to average and add a multiple of the standard deviation to.
// @param len The The number of bars to measure.
// @param level The positive or negative multiple of the standard deviation to apply to the average. A positive number will be the upper boundary and a negative number will be the lower boundary.
// @param maxDeviation The optional standard deviation level to use when cleaning the series. The default is the value of the provided level.
// @returns The average of the series plus the multiple of the standard deviation.
export outlierLevelAdjusted(
series float src,
simple int len,
simple float level,
simple float maxDeviation = 0)=>
if level == 0
runtime.error('Passing a level of (0) zero to "level" is simply the average.')
cleaned = clean(src, len, maxDeviation==0 ? level : maxDeviation)
avg = array.avg(cleaned)
std = array.stdev(cleaned)
avg + std * level
//////////////////////////////////////////////////
len = input.int(200, "Length")
maxDev = input.float(2, "Max Deviation", minval=1)
level = input.float(4, "Max Deviation After Cleaning", minval=1)
//plot(ta.atr(len), "ATR", color.red)
candleHeight = high - low
plot(candleHeight, "Candle Height", color.yellow)
before = outlierLevel(candleHeight, len, maxDev)
plot(before, "Deviation Before Adjustment", color.orange)
after = outlierLevelAdjusted(candleHeight, len, level)
plot(after, "Deviation After Adjustment", color.green)