daru_lite 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/ISSUE_TEMPLATE.md +18 -0
- data/.github/workflows/ci.yml +33 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +27 -0
- data/.rubocop_todo.yml +137 -0
- data/CONTRIBUTING.md +47 -0
- data/Gemfile +2 -0
- data/History.md +4 -0
- data/LICENSE +24 -0
- data/README.md +218 -0
- data/Rakefile +69 -0
- data/ReleasePolicy.md +20 -0
- data/benchmarks/TradeoffData.csv +65 -0
- data/benchmarks/csv_reading.rb +22 -0
- data/benchmarks/dataframe_creation.rb +39 -0
- data/benchmarks/db_loading.rb +34 -0
- data/benchmarks/duplicating.rb +45 -0
- data/benchmarks/group_by.rb +32 -0
- data/benchmarks/joining.rb +52 -0
- data/benchmarks/row_access.rb +41 -0
- data/benchmarks/row_assign.rb +36 -0
- data/benchmarks/sorting.rb +51 -0
- data/benchmarks/statistics.rb +28 -0
- data/benchmarks/vector_access.rb +31 -0
- data/benchmarks/vector_assign.rb +42 -0
- data/benchmarks/where_clause.rb +48 -0
- data/benchmarks/where_vs_filter.rb +28 -0
- data/daru_lite.gemspec +55 -0
- data/images/README.md +5 -0
- data/images/con0.png +0 -0
- data/images/con1.png +0 -0
- data/images/init0.png +0 -0
- data/images/init1.png +0 -0
- data/images/man0.png +0 -0
- data/images/man1.png +0 -0
- data/images/man2.png +0 -0
- data/images/man3.png +0 -0
- data/images/man4.png +0 -0
- data/images/man5.png +0 -0
- data/images/man6.png +0 -0
- data/lib/daru_lite/accessors/array_wrapper.rb +109 -0
- data/lib/daru_lite/accessors/dataframe_by_row.rb +25 -0
- data/lib/daru_lite/accessors/mdarray_wrapper.rb +7 -0
- data/lib/daru_lite/category.rb +929 -0
- data/lib/daru_lite/configuration.rb +34 -0
- data/lib/daru_lite/core/group_by.rb +403 -0
- data/lib/daru_lite/core/merge.rb +270 -0
- data/lib/daru_lite/core/query.rb +109 -0
- data/lib/daru_lite/dataframe.rb +3080 -0
- data/lib/daru_lite/date_time/index.rb +569 -0
- data/lib/daru_lite/date_time/offsets.rb +397 -0
- data/lib/daru_lite/exceptions.rb +2 -0
- data/lib/daru_lite/extensions/which_dsl.rb +53 -0
- data/lib/daru_lite/formatters/table.rb +52 -0
- data/lib/daru_lite/helpers/array.rb +53 -0
- data/lib/daru_lite/index/categorical_index.rb +201 -0
- data/lib/daru_lite/index/index.rb +374 -0
- data/lib/daru_lite/index/multi_index.rb +374 -0
- data/lib/daru_lite/io/csv/converters.rb +21 -0
- data/lib/daru_lite/io/io.rb +294 -0
- data/lib/daru_lite/io/sql_data_source.rb +97 -0
- data/lib/daru_lite/iruby/helpers.rb +38 -0
- data/lib/daru_lite/iruby/templates/dataframe.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi_tbody.html.erb +35 -0
- data/lib/daru_lite/iruby/templates/dataframe_mi_thead.html.erb +21 -0
- data/lib/daru_lite/iruby/templates/dataframe_tbody.html.erb +28 -0
- data/lib/daru_lite/iruby/templates/dataframe_thead.html.erb +21 -0
- data/lib/daru_lite/iruby/templates/multi_index.html.erb +12 -0
- data/lib/daru_lite/iruby/templates/vector.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/vector_mi.html.erb +5 -0
- data/lib/daru_lite/iruby/templates/vector_mi_tbody.html.erb +26 -0
- data/lib/daru_lite/iruby/templates/vector_mi_thead.html.erb +8 -0
- data/lib/daru_lite/iruby/templates/vector_tbody.html.erb +17 -0
- data/lib/daru_lite/iruby/templates/vector_thead.html.erb +8 -0
- data/lib/daru_lite/maths/arithmetic/dataframe.rb +91 -0
- data/lib/daru_lite/maths/arithmetic/vector.rb +117 -0
- data/lib/daru_lite/maths/statistics/dataframe.rb +202 -0
- data/lib/daru_lite/maths/statistics/vector.rb +1019 -0
- data/lib/daru_lite/monkeys.rb +56 -0
- data/lib/daru_lite/vector.rb +1678 -0
- data/lib/daru_lite/version.rb +3 -0
- data/lib/daru_lite.rb +99 -0
- data/profile/_base.rb +23 -0
- data/profile/df_to_a.rb +10 -0
- data/profile/filter.rb +13 -0
- data/profile/joining.rb +13 -0
- data/profile/sorting.rb +12 -0
- data/profile/vector_each_with_index.rb +9 -0
- data/profile/vector_new.rb +9 -0
- data/spec/accessors/array_wrapper_spec.rb +3 -0
- data/spec/category_spec.rb +1741 -0
- data/spec/core/group_by_spec.rb +655 -0
- data/spec/core/merge_spec.rb +179 -0
- data/spec/core/query_spec.rb +347 -0
- data/spec/daru_lite_spec.rb +22 -0
- data/spec/dataframe_spec.rb +4330 -0
- data/spec/date_time/data_spec.rb +197 -0
- data/spec/date_time/date_time_index_helper_spec.rb +72 -0
- data/spec/date_time/index_spec.rb +588 -0
- data/spec/date_time/offsets_spec.rb +465 -0
- data/spec/extensions/which_dsl_spec.rb +38 -0
- data/spec/fixtures/bank2.dat +200 -0
- data/spec/fixtures/boolean_converter_test.csv +5 -0
- data/spec/fixtures/countries.json +7794 -0
- data/spec/fixtures/duplicates.csv +32 -0
- data/spec/fixtures/eciresults.html +394 -0
- data/spec/fixtures/empties.dat +2 -0
- data/spec/fixtures/empty_rows_test.csv +17 -0
- data/spec/fixtures/macau.html +3691 -0
- data/spec/fixtures/macd_data.csv +150 -0
- data/spec/fixtures/matrix_test.csv +100 -0
- data/spec/fixtures/moneycontrol.html +6812 -0
- data/spec/fixtures/music_data.tsv +2501 -0
- data/spec/fixtures/repeated_fields.csv +7 -0
- data/spec/fixtures/sales-funnel.csv +18 -0
- data/spec/fixtures/scientific_notation.csv +4 -0
- data/spec/fixtures/string_converter_test.csv +5 -0
- data/spec/fixtures/strings.dat +2 -0
- data/spec/fixtures/test_xls.xls +0 -0
- data/spec/fixtures/test_xls_2.xls +0 -0
- data/spec/fixtures/url_test.txt~ +0 -0
- data/spec/fixtures/valid_markup.html +62 -0
- data/spec/fixtures/wiki_climate.html +1243 -0
- data/spec/fixtures/wiki_table_info.html +631 -0
- data/spec/formatters/table_formatter_spec.rb +137 -0
- data/spec/helpers_spec.rb +8 -0
- data/spec/index/categorical_index_spec.rb +170 -0
- data/spec/index/index_spec.rb +417 -0
- data/spec/index/multi_index_spec.rb +680 -0
- data/spec/io/io_spec.rb +373 -0
- data/spec/io/sql_data_source_spec.rb +56 -0
- data/spec/iruby/dataframe_spec.rb +170 -0
- data/spec/iruby/helpers_spec.rb +49 -0
- data/spec/iruby/multi_index_spec.rb +37 -0
- data/spec/iruby/vector_spec.rb +105 -0
- data/spec/maths/arithmetic/dataframe_spec.rb +148 -0
- data/spec/maths/arithmetic/vector_spec.rb +165 -0
- data/spec/maths/statistics/dataframe_spec.rb +178 -0
- data/spec/maths/statistics/vector_spec.rb +756 -0
- data/spec/monkeys_spec.rb +42 -0
- data/spec/shared/vector_display_spec.rb +213 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/database_helper.rb +30 -0
- data/spec/support/matchers.rb +5 -0
- data/spec/vector_spec.rb +2293 -0
- metadata +571 -0
@@ -0,0 +1,756 @@
|
|
1
|
+
describe DaruLite::Vector do
|
2
|
+
describe 'array' do
|
3
|
+
let(:dtype) { :array }
|
4
|
+
|
5
|
+
before do
|
6
|
+
@dv = DaruLite::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2], dtype: dtype
|
7
|
+
@dv_with_nils = DaruLite::Vector.new [323, 11, 555, nil, 666, 234, 21, 666, 343, nil, 1, 2]
|
8
|
+
end
|
9
|
+
|
10
|
+
context "#mean" do
|
11
|
+
it "calculates mean" do
|
12
|
+
expect(@dv.mean).to eq(282.2)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:dv) { dv = DaruLite::Vector.new (["Tyrion", "Daenerys", nil, "Jon Starkgaryen"]), index: DaruLite::Index.new([:t, :d, :n, :j]) }
|
17
|
+
|
18
|
+
context "#max" do
|
19
|
+
it "returns max value" do
|
20
|
+
expect(dv.max).to eq("Tyrion")
|
21
|
+
end
|
22
|
+
it "returns N max values" do
|
23
|
+
expect(dv.max(2)).to eq(["Tyrion","Jon Starkgaryen"])
|
24
|
+
end
|
25
|
+
it "returns max value, sorted by comparitive block input" do
|
26
|
+
expect(dv.max { |a,b| a.size <=> b.size }).to eq("Jon Starkgaryen")
|
27
|
+
end
|
28
|
+
it "returns N max values, sorted by comparitive block input" do
|
29
|
+
expect(dv.max(2) {|a,b| a.size <=> b.size}).to eq(["Jon Starkgaryen","Daenerys"])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "#max_by" do
|
34
|
+
it "raises error without object block" do
|
35
|
+
expect { dv.max_by }.to raise_error(ArgumentError)
|
36
|
+
end
|
37
|
+
it "raises error without object block when N is given" do
|
38
|
+
expect { dv.max_by(2) }.to raise_error(ArgumentError)
|
39
|
+
end
|
40
|
+
it "returns max value, sorted by object block input" do
|
41
|
+
expect(dv.max_by { |x| x.size }).to eq("Jon Starkgaryen")
|
42
|
+
end
|
43
|
+
it "returns N max values, sorted by object block input" do
|
44
|
+
expect(dv.max_by(2) {|x| x.size }).to eq(["Jon Starkgaryen","Daenerys"])
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "#index_of_max" do
|
49
|
+
it "returns index_of_max value" do
|
50
|
+
expect(dv.index_of_max).to eq(:t)
|
51
|
+
end
|
52
|
+
it "returns N index_of_max values" do
|
53
|
+
expect(dv.index_of_max(2)).to eq([:t, :j])
|
54
|
+
end
|
55
|
+
it "returns index_of_max value, sorted by comparitive block input" do
|
56
|
+
expect(dv.index_of_max { |a,b| a.size <=> b.size }).to eq(:j)
|
57
|
+
end
|
58
|
+
it "returns N index_of_max values, sorted by comparitive block input" do
|
59
|
+
expect(dv.index_of_max(2) {|a,b| a.size <=> b.size}).to eq([:j, :d])
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "#index_of_max_by" do
|
64
|
+
it "raises error without object block" do
|
65
|
+
expect { dv.index_of_max_by }.to raise_error(ArgumentError)
|
66
|
+
end
|
67
|
+
it "raises error without object block when N is given" do
|
68
|
+
expect { dv.index_of_max_by(2) }.to raise_error(ArgumentError)
|
69
|
+
end
|
70
|
+
it "returns index_of_max value, sorted by object block input" do
|
71
|
+
expect(dv.index_of_max_by { |x| x.size }).to eq(:j)
|
72
|
+
end
|
73
|
+
it "returns N index_of_max values, sorted by object block input" do
|
74
|
+
expect(dv.index_of_max_by(2) {|x| x.size }).to eq([:j, :d])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "#min" do
|
79
|
+
it "returns min value" do
|
80
|
+
expect(dv.min).to eq("Daenerys")
|
81
|
+
end
|
82
|
+
it "returns N min values" do
|
83
|
+
expect(dv.min(2)).to eq(["Daenerys","Jon Starkgaryen"])
|
84
|
+
end
|
85
|
+
it "returns min value, sorted by comparitive block input" do
|
86
|
+
expect(dv.min { |a,b| a.size <=> b.size }).to eq("Tyrion")
|
87
|
+
end
|
88
|
+
it "returns N min values, sorted by comparitive block input" do
|
89
|
+
expect(dv.min(2) {|a,b| a.size <=> b.size}).to eq(["Tyrion","Daenerys"])
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "#min_by" do
|
94
|
+
it "raises error without object block" do
|
95
|
+
expect { dv.min_by }.to raise_error(ArgumentError)
|
96
|
+
end
|
97
|
+
it "raises error without object block when N is given" do
|
98
|
+
expect { dv.min_by(2) }.to raise_error(ArgumentError)
|
99
|
+
end
|
100
|
+
it "returns min value, sorted by object block input" do
|
101
|
+
expect(dv.min_by { |x| x.size }).to eq("Tyrion")
|
102
|
+
end
|
103
|
+
it "returns N min values, sorted by object block input" do
|
104
|
+
expect(dv.min_by(2) {|x| x.size }).to eq(["Tyrion","Daenerys"])
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
context "#index_of_min" do
|
109
|
+
it "returns index of min value" do
|
110
|
+
expect(dv.index_of_min).to eq(:d)
|
111
|
+
end
|
112
|
+
it "returns N index of min values" do
|
113
|
+
expect(dv.index_of_min(2)).to eq([:d, :j])
|
114
|
+
end
|
115
|
+
it "returns index of min value, sorted by comparitive block input" do
|
116
|
+
expect(dv.index_of_min { |a,b| a.size <=> b.size }).to eq(:t)
|
117
|
+
end
|
118
|
+
it "returns N index of min values, sorted by comparitive block input" do
|
119
|
+
expect(dv.index_of_min(2) {|a,b| a.size <=> b.size}).to eq([:t, :d])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "#index_of_min_by" do
|
124
|
+
it "raises error without object block" do
|
125
|
+
expect { dv.index_of_min_by }.to raise_error(ArgumentError)
|
126
|
+
end
|
127
|
+
it "raises error without object block when N is given" do
|
128
|
+
expect { dv.index_of_min_by(2) }.to raise_error(ArgumentError)
|
129
|
+
end
|
130
|
+
it "returns index of min value, sorted by object block input" do
|
131
|
+
expect(dv.index_of_min_by { |x| x.size }).to eq(:t)
|
132
|
+
end
|
133
|
+
it "returns N index of min values, sorted by object block input" do
|
134
|
+
expect(dv.index_of_min_by(2) {|x| x.size }).to eq([:t, :d])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context "#sum_of_squares" do
|
139
|
+
it "calcs sum of squares, omits nil values" do
|
140
|
+
v = DaruLite::Vector.new [1,2,3,4,5,6], dtype: dtype
|
141
|
+
expect(v.sum_of_squares).to eq(17.5)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "#standard_deviation_sample" do
|
146
|
+
it "calcs standard deviation sample" do
|
147
|
+
@dv_with_nils.standard_deviation_sample
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context "#variance_sample" do
|
152
|
+
it "calculates sample variance" do
|
153
|
+
expect(@dv.variance).to be_within(0.01).of(75118.84)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context "#standard_deviation_population" do
|
158
|
+
it "calculates standard deviation population" do
|
159
|
+
@dv.standard_deviation_population
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "#variance_population" do
|
164
|
+
it "calculates population variance" do
|
165
|
+
expect(@dv.variance_population).to be_within(0.001).of(67606.95999999999)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "#covariance_sample" do
|
170
|
+
it "calculates sample covariance" do
|
171
|
+
@dv_1 = DaruLite::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2]
|
172
|
+
@dv_2 = DaruLite::Vector.new [123, 22, 444, 555, 324, 21, 666, 434, 5, 8]
|
173
|
+
expect(@dv_1.covariance @dv_2).to be_within(0.00001).of(65603.62222)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
context "#covariance_population" do
|
178
|
+
it "calculates population covariance" do
|
179
|
+
@dv_1 = DaruLite::Vector.new [323, 11, 555, 666, 234, 21, 666, 343, 1, 2]
|
180
|
+
@dv_2 = DaruLite::Vector.new [123, 22, 444, 555, 324, 21, 666, 434, 5, 8]
|
181
|
+
expect(@dv_1.covariance_population @dv_2).to be_within(0.01).of(59043.26)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "#sum_of_squared_deviation" do
|
186
|
+
it "calculates sum of squared deviation" do
|
187
|
+
expect(@dv.sum_of_squared_deviation).to eq(676069.6)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "#skew" do
|
192
|
+
it "calculates skewness" do
|
193
|
+
@dv.skew
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
context "#max" do
|
198
|
+
it "returns the max value" do
|
199
|
+
expect(@dv.max).to eq(666)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context "#min" do
|
204
|
+
it "returns the min value" do
|
205
|
+
expect(@dv.min).to eq(1)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
context "#sum" do
|
210
|
+
it "returns the sum" do
|
211
|
+
expect(@dv.sum).to eq(2822)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
context "#product" do
|
216
|
+
it "returns the product" do
|
217
|
+
v = DaruLite::Vector.new [1, 2, 3, 4, 5], dtype: dtype
|
218
|
+
expect(v.product).to eq(120)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context "#median" do
|
223
|
+
it "returns the median" do
|
224
|
+
@dv.median
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
context "#mode" do
|
229
|
+
it "returns the single modal value as a numeric" do
|
230
|
+
mode_test_example = DaruLite::Vector.new [1,2,3,2,4,4,4,4], dtype: dtype
|
231
|
+
expect(mode_test_example.mode).to eq(4)
|
232
|
+
end
|
233
|
+
|
234
|
+
it "returns multiple modal values as a vector" do
|
235
|
+
mode_test_example = DaruLite::Vector.new [1,2,2,2,3,2,4,4,4,4], dtype: dtype
|
236
|
+
expect(mode_test_example.mode).to eq(DaruLite::Vector.new [2,4], dtype: dtype)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "#describe" do
|
241
|
+
it "generates count, mean, std, min and max of vectors in one shot" do
|
242
|
+
expect(@dv.describe.round(2)).to eq(DaruLite::Vector.new([10.00, 282.20, 274.08, 1.00, 666.00],
|
243
|
+
index: [:count, :mean, :std, :min, :max],
|
244
|
+
name: :statistics
|
245
|
+
))
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
context "#kurtosis" do
|
250
|
+
it "calculates kurtosis" do
|
251
|
+
@dv.kurtosis
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "#count" do
|
256
|
+
it "counts specified element" do
|
257
|
+
expect(@dv.count(323)).to eq(1)
|
258
|
+
end
|
259
|
+
|
260
|
+
it "counts total number of elements" do
|
261
|
+
expect(@dv.count).to eq(10)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "counts by block provided" do
|
265
|
+
expect(@dv.count{|e| e.to_i.even? }).to eq(4)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
context "#value_counts" do
|
270
|
+
it "counts number of unique values in the Vector" do
|
271
|
+
vector = DaruLite::Vector.new(
|
272
|
+
["America","America","America","America","America",
|
273
|
+
"India","India", "China", "India", "China"])
|
274
|
+
expect(vector.value_counts).to eq(
|
275
|
+
DaruLite::Vector.new([5,3,2], index: ["America", "India", "China"]))
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
context "#coefficient_of_variation" do
|
280
|
+
it "calculates coefficient_of_variation" do
|
281
|
+
@dv.coefficient_of_variation
|
282
|
+
end
|
283
|
+
end
|
284
|
+
|
285
|
+
context "#percentile" do
|
286
|
+
it "calculates mid point percentile" do
|
287
|
+
expect(@dv.percentile(50)).to eq(278.5)
|
288
|
+
end
|
289
|
+
|
290
|
+
it "calculates linear percentile" do
|
291
|
+
# FIXME: Not enough testing?..
|
292
|
+
expect(@dv.percentile(50, :linear)).to eq(278.5)
|
293
|
+
end
|
294
|
+
|
295
|
+
it "fails on unknown strategy" do
|
296
|
+
expect { @dv.percentile(50, :killemall) }.to raise_error(ArgumentError, /strategy/)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
context "#average_deviation_population" do
|
301
|
+
it "calculates average_deviation_population" do
|
302
|
+
a = DaruLite::Vector.new([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype: dtype)
|
303
|
+
expect(a.average_deviation_population).to eq(20.quo(9).to_f)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context "#proportion" do
|
308
|
+
it "calculates proportion" do
|
309
|
+
expect(@dv.proportion(1)).to eq(0.1)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
context "#proportions" do
|
314
|
+
it "calculates proportions" do
|
315
|
+
actual_proportions = {
|
316
|
+
323=>0.1,11=>0.1,555=>0.1,666=>0.2,234=>0.1,21=>0.1,343=>0.1,1=>0.1,2=>0.1
|
317
|
+
}
|
318
|
+
expect(@dv.proportions).to eq(actual_proportions)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
context "#standard_error" do
|
323
|
+
it "calculates standard error" do
|
324
|
+
@dv.standard_error
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context "#vector_standardized_compute" do
|
329
|
+
it "calculates vector_standardized_compute" do
|
330
|
+
@dv.vector_standardized_compute(@dv.mean, @dv.sd)
|
331
|
+
@dv_with_nils.vector_standardized_compute(@dv.mean, @dv.sd)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
context "#vector_centered_compute" do
|
336
|
+
it "calculates vector_centered_compute" do
|
337
|
+
@dv.vector_centered_compute(@dv.mean)
|
338
|
+
@dv_with_nils.vector_centered_compute(@dv.mean)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
# Only Array tests
|
344
|
+
context "#percentile" do
|
345
|
+
it "tests linear percentile strategy" do
|
346
|
+
values = DaruLite::Vector.new [102, 104, 105, 107, 108, 109, 110, 112, 115, 116].shuffle
|
347
|
+
expect(values.percentil(0, :linear)).to eq(102)
|
348
|
+
expect(values.percentil(25, :linear)).to eq(104.75)
|
349
|
+
expect(values.percentil(50, :linear)).to eq(108.5)
|
350
|
+
expect(values.percentil(75, :linear)).to eq(112.75)
|
351
|
+
expect(values.percentil(100, :linear)).to eq(116)
|
352
|
+
|
353
|
+
values = DaruLite::Vector.new [102, 104, 105, 107, 108, 109, 110, 112, 115, 116, 118].shuffle
|
354
|
+
expect(values.percentil(0, :linear)).to eq(102)
|
355
|
+
expect(values.percentil(25, :linear)).to eq(105)
|
356
|
+
expect(values.percentil(50, :linear)).to eq(109)
|
357
|
+
expect(values.percentil(75, :linear)).to eq(115)
|
358
|
+
expect(values.percentil(100, :linear)).to eq(118)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
context "#frequencies" do
|
363
|
+
let(:vector) { DaruLite::Vector.new([5,5,5,5,5,6,6,7,8,9,10,1,2,3,4,nil,-99,-99]) }
|
364
|
+
subject { vector.frequencies }
|
365
|
+
it { is_expected.to eq DaruLite::Vector.new(
|
366
|
+
[5,2,1,1,1,1,1,1,1,1,2],
|
367
|
+
index: [5,6,7,8,9,10,1,2,3,4,-99]
|
368
|
+
)}
|
369
|
+
end
|
370
|
+
|
371
|
+
context "#ranked" do
|
372
|
+
it "curates by rank" do
|
373
|
+
vector = DaruLite::Vector.new([nil, 0.8, 1.2, 1.2, 2.3, 18, nil])
|
374
|
+
expect(vector.ranked).to eq(DaruLite::Vector.new([nil,1,2.5,2.5,4,5,nil]))
|
375
|
+
|
376
|
+
v = DaruLite::Vector.new [0.8, 1.2, 1.2, 2.3, 18]
|
377
|
+
expect(v.ranked).to eq(DaruLite::Vector.new [1, 2.5, 2.5, 4, 5])
|
378
|
+
end
|
379
|
+
|
380
|
+
it "tests paired ties" do
|
381
|
+
a = DaruLite::Vector.new [0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 4]
|
382
|
+
expected = DaruLite::Vector.new [2, 2, 2, 4.5, 4.5, 6, 7.5, 7.5, 10, 10, 10]
|
383
|
+
expect(a.ranked).to eq(expected)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
context "#dichotomize" do
|
388
|
+
it "dichotomizes" do
|
389
|
+
a = DaruLite::Vector.new [0, 0, 0, 1, 2, 3, nil]
|
390
|
+
exp = DaruLite::Vector.new [0, 0, 0, 1, 1, 1, nil]
|
391
|
+
expect(a.dichotomize).to eq(exp)
|
392
|
+
|
393
|
+
a = DaruLite::Vector.new [1, 1, 1, 2, 2, 2, 3]
|
394
|
+
exp = DaruLite::Vector.new [0, 0, 0, 1, 1, 1, 1]
|
395
|
+
expect(a.dichotomize).to eq(exp)
|
396
|
+
|
397
|
+
a = DaruLite::Vector.new [0, 0, 0, 1, 2, 3, nil]
|
398
|
+
exp = DaruLite::Vector.new [0, 0, 0, 0, 1, 1, nil]
|
399
|
+
expect(a.dichotomize(1)).to eq(exp)
|
400
|
+
|
401
|
+
a = DaruLite::Vector.new %w(a a a b c d)
|
402
|
+
exp = DaruLite::Vector.new [0, 0, 0, 1, 1, 1]
|
403
|
+
expect(a.dichotomize).to eq(exp)
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
context "#median_absolute_deviation" do
|
408
|
+
it "calculates median_absolute_deviation" do
|
409
|
+
a = DaruLite::Vector.new [1, 1, 2, 2, 4, 6, 9]
|
410
|
+
expect(a.median_absolute_deviation).to eq(1)
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
context "#round" do
|
415
|
+
it "rounds non-nil values" do
|
416
|
+
vector = DaruLite::Vector.new([1.44,55.32,nil,4])
|
417
|
+
expect(vector.round(1)).to eq(DaruLite::Vector.new([1.4,55.3,nil,4]))
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
context "#center" do
|
422
|
+
it "centers" do
|
423
|
+
mean = rand
|
424
|
+
samples = 11
|
425
|
+
centered = DaruLite::Vector.new(samples.times.map { |i| i - ((samples / 2).floor).to_i })
|
426
|
+
not_centered = centered.recode { |v| v + mean }
|
427
|
+
obs = not_centered.center
|
428
|
+
centered.each_with_index do |v, i|
|
429
|
+
expect(v).to be_within(0.0001).of(obs[i])
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
context "#standardize" do
|
435
|
+
it "returns a standardized vector" do
|
436
|
+
vector = DaruLite::Vector.new([11,55,33,25,nil,22])
|
437
|
+
expect(vector.standardize.round(2)).to eq(
|
438
|
+
DaruLite::Vector.new([-1.11, 1.57, 0.23, -0.26,nil, -0.44])
|
439
|
+
)
|
440
|
+
end
|
441
|
+
|
442
|
+
it "tests for vector standardized with zero variance" do
|
443
|
+
v1 = DaruLite::Vector.new 100.times.map { |_i| 1 }
|
444
|
+
exp = DaruLite::Vector.new 100.times.map { nil }
|
445
|
+
expect(v1.standardize).to eq(exp)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context "#vector_percentile" do
|
450
|
+
it "replaces each non-nil value with its percentile value" do
|
451
|
+
vector = DaruLite::Vector.new([1,nil,nil,2,2,3,4,nil,nil,5,5,5,6,10])
|
452
|
+
expect(vector.vector_percentile).to eq(DaruLite::Vector.new(
|
453
|
+
[10,nil,nil,25,25,40,50,nil,nil,70,70,70,90,100])
|
454
|
+
)
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
context "#sample_with_replacement" do
|
459
|
+
it "calculates sample_with_replacement" do
|
460
|
+
vec = DaruLite::Vector.new(
|
461
|
+
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
462
|
+
name: :common_all_dtypes)
|
463
|
+
srand(1)
|
464
|
+
expect(vec.sample_with_replacement(100).size).to eq(100)
|
465
|
+
|
466
|
+
srand(1)
|
467
|
+
expect(vec.sample_with_replacement(100).size).to eq(100)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
context "#sample_without_replacement" do
|
472
|
+
it "calculates sample_without_replacement" do
|
473
|
+
vec = DaruLite::Vector.new(
|
474
|
+
[5, 5, 5, 5, 5, 6, 6, 7, 8, 9, 10, 1, 2, 3, 4, nil, -99, -99],
|
475
|
+
name: :common_all_dtypes)
|
476
|
+
|
477
|
+
srand(1)
|
478
|
+
expect(vec.sample_without_replacement(17).sort).to eq(
|
479
|
+
vec.reject_values(*DaruLite::MISSING_VALUES).to_a.sort)
|
480
|
+
expect {
|
481
|
+
vec.sample_without_replacement(20)
|
482
|
+
}.to raise_error(ArgumentError)
|
483
|
+
|
484
|
+
srand(1)
|
485
|
+
expect(vec.sample_without_replacement(17).sort).to eq(
|
486
|
+
vec.reject_values(*DaruLite::MISSING_VALUES).to_a.sort)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context "#jackknife" do
|
491
|
+
it "jack knife correctly with named method" do
|
492
|
+
a = DaruLite::Vector.new [1, 2, 3, 4]
|
493
|
+
df = a.jackknife(:mean)
|
494
|
+
expect(df[:mean].mean).to eq (a.mean)
|
495
|
+
|
496
|
+
df = a.jackknife([:mean, :sd])
|
497
|
+
expect(df[:mean].mean).to eq(a.mean)
|
498
|
+
expect(df[:mean].sd).to eq(a.sd)
|
499
|
+
end
|
500
|
+
|
501
|
+
it "jack knife correctly with custom method" do
|
502
|
+
a = DaruLite::Vector.new [17.23, 18.71, 13.93, 18.81, 15.78, 11.29, 14.91, 13.39, 18.21, 11.57, 14.28, 10.94, 18.83, 15.52, 13.45, 15.25]
|
503
|
+
ds = a.jackknife(log_s2: ->(v) { Math.log(v.variance) })
|
504
|
+
exp = DaruLite::Vector.new [1.605, 2.972, 1.151, 3.097, 0.998, 3.308, 0.942, 1.393, 2.416, 2.951, 1.043, 3.806, 3.122, 0.958, 1.362, 0.937]
|
505
|
+
|
506
|
+
expect_correct_vector_in_delta ds[:log_s2], exp, 0.001
|
507
|
+
# expect(ds[:log_s2]).to be_within(0.001).of(exp)
|
508
|
+
expect(ds[:log_s2].mean).to be_within(0.00001).of(2.00389)
|
509
|
+
expect(ds[:log_s2].variance).to be_within(0.001).of(1.091)
|
510
|
+
end
|
511
|
+
|
512
|
+
it "jack knife correctly with k > 1" do
|
513
|
+
rng = Distribution::Normal.rng(0,1)
|
514
|
+
a = DaruLite::Vector.new_with_size(6) { rng.call}
|
515
|
+
|
516
|
+
ds = a.jackknife(:mean, 2)
|
517
|
+
mean = a.mean
|
518
|
+
exp = DaruLite::Vector.new [3 * mean - 2 * (a[2] + a[3] + a[4] + a[5]) / 4, 3 * mean - 2 * (a[0] + a[1] + a[4] + a[5]) / 4, 3 * mean - 2 * (a[0] + a[1] + a[2] + a[3]) / 4]
|
519
|
+
expect_correct_vector_in_delta(exp, ds[:mean], 1e-13)
|
520
|
+
end
|
521
|
+
end
|
522
|
+
|
523
|
+
before do
|
524
|
+
# daily closes of iShares XIU on the TSX
|
525
|
+
@shares = DaruLite::Vector.new([17.28, 17.45, 17.84, 17.74, 17.82, 17.85, 17.36, 17.3, 17.56, 17.49, 17.46, 17.4, 17.03, 17.01,16.86, 16.86, 16.56, 16.36, 16.66, 16.77])
|
526
|
+
end
|
527
|
+
|
528
|
+
context "#acf" do
|
529
|
+
it "calculates autocorrelation co-efficients" do
|
530
|
+
acf = @shares.acf
|
531
|
+
|
532
|
+
expect(acf.length).to eq(14)
|
533
|
+
|
534
|
+
# test the first few autocorrelations
|
535
|
+
expect(acf[0]).to be_within(0.0001).of(1.0)
|
536
|
+
expect(acf[1]).to be_within(0.001) .of(0.852)
|
537
|
+
expect(acf[2]).to be_within(0.001) .of(0.669)
|
538
|
+
expect(acf[3]).to be_within(0.001) .of(0.486)
|
539
|
+
end
|
540
|
+
end
|
541
|
+
|
542
|
+
context "#percent_change" do
|
543
|
+
it "calculates percent change" do
|
544
|
+
vector = DaruLite::Vector.new([4,6,6,8,10],index: ['a','f','t','i','k'])
|
545
|
+
expect(vector.percent_change).to eq(
|
546
|
+
DaruLite::Vector.new([nil, 0.5, 0.0, 0.3333333333333333, 0.25], index: ['a','f','t','i','k']))
|
547
|
+
end
|
548
|
+
|
549
|
+
it "tests for numerical vectors with nils" do
|
550
|
+
vector2 = DaruLite::Vector.new([nil,6,nil,8,10],index: ['a','f','t','i','k'])
|
551
|
+
expect(vector2.percent_change).to eq(
|
552
|
+
DaruLite::Vector.new([nil, nil, nil, 0.3333333333333333, 0.25], index: ['a','f','t','i','k']))
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
context "#diff" do
|
557
|
+
it "performs the difference of the series" do
|
558
|
+
diff = @shares.diff
|
559
|
+
|
560
|
+
expect(diff.class).to eq(DaruLite::Vector)
|
561
|
+
expect(diff[@shares.size - 1]).to be_within(0.001).of( 0.11)
|
562
|
+
expect(diff[@shares.size - 2]).to be_within(0.001).of( 0.30)
|
563
|
+
expect(diff[@shares.size - 3]).to be_within(0.001).of(-0.20)
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
context "#rolling" do
|
568
|
+
it "calculates rolling mean" do
|
569
|
+
ma10 = @shares.rolling_mean
|
570
|
+
|
571
|
+
expect(ma10[-1]) .to be_within(0.001).of(16.897)
|
572
|
+
expect(ma10[-5]) .to be_within(0.001).of(17.233)
|
573
|
+
expect(ma10[-10]).to be_within(0.001).of(17.587)
|
574
|
+
|
575
|
+
# test with a different lookback period
|
576
|
+
ma5 = @shares.rolling :mean, 5
|
577
|
+
|
578
|
+
expect(ma5[-1]).to be_within(0.001).of(16.642)
|
579
|
+
expect(ma5[-10]).to be_within(0.001).of(17.434)
|
580
|
+
expect(ma5[-15]).to be_within(0.001).of(17.74)
|
581
|
+
end
|
582
|
+
|
583
|
+
it "calculates rolling median" do
|
584
|
+
me10 = @shares.rolling_median.round(2)
|
585
|
+
expect(me10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.525,17.525,17.525,17.475,17.430,17.380,17.330,17.165,17.020,16.94,16.860]).round(2))
|
586
|
+
|
587
|
+
me5 = @shares.rolling(:median, 5).round(2)
|
588
|
+
expect(me5).to eq(DaruLite::Vector.new([nil,nil,nil,nil,17.74,17.82,17.82,17.74,17.56,17.49,17.46,17.46,17.46,17.40,17.03,17.01,16.86,16.86,16.66,16.66]))
|
589
|
+
end
|
590
|
+
|
591
|
+
it "calculates rolling max" do
|
592
|
+
max10 = @shares.rolling_max.round(2)
|
593
|
+
expect(max10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.85,17.85,17.85,17.85,17.85,17.85,17.56,17.56,17.56,17.49,17.46]))
|
594
|
+
|
595
|
+
max5 = @shares.rolling(:max, 5).round(2)
|
596
|
+
expect(max5).to eq(DaruLite::Vector.new([nil, nil, nil, nil,17.84,17.85,17.85,17.85,17.85,17.85,17.56,17.56,17.56,17.49,17.46,17.40,17.03,17.01,16.86,16.86]))
|
597
|
+
end
|
598
|
+
|
599
|
+
it "calculates rolling min" do
|
600
|
+
min10 = @shares.rolling_min.round(2)
|
601
|
+
expect(min10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,17.28,17.30,17.30,17.03,17.01,16.86,16.86,16.56,16.36,16.36,16.36]))
|
602
|
+
|
603
|
+
min5 = @shares.rolling(:min, 5).round(2)
|
604
|
+
expect(min5).to eq(DaruLite::Vector.new([nil,nil,nil,nil,17.28,17.45,17.36,17.30,17.30,17.30,17.30,17.30,17.03,17.01,16.86,16.86,16.56,16.36,16.36,16.36]))
|
605
|
+
end
|
606
|
+
|
607
|
+
it "calculates rolling sum" do
|
608
|
+
sum10 = @shares.rolling_sum.round(2)
|
609
|
+
expect(sum10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,175.69,175.87,175.82,175.01,174.28,173.32,172.33,171.53,170.59,169.69,168.97]))
|
610
|
+
|
611
|
+
sum5 = @shares.rolling(:sum, 5).round(2)
|
612
|
+
expect(sum5).to eq(DaruLite::Vector.new([nil,nil,nil,nil,88.13,88.70,88.61,88.07,87.89,87.56,87.17,87.21,86.94,86.39,85.76,85.16,84.32,83.65,83.30,83.21]))
|
613
|
+
end
|
614
|
+
|
615
|
+
it "calculates rolling std" do
|
616
|
+
std10 = @shares.rolling_std.round(2)
|
617
|
+
expect(std10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,0.227227,0.208116,0.212331,0.253485,0.280666,0.295477,0.267127,0.335826,0.412834,0.388886,0.345995]).round(2))
|
618
|
+
|
619
|
+
std5 = @shares.rolling(:std, 5).round(2)
|
620
|
+
expect(std5).to eq(DaruLite::Vector.new([nil,nil,nil,nil,0.248556,0.167780,0.206930,0.263211,0.253811,0.215105,0.103827,0.098082,0.208255,0.237844,0.263002,0.220839,0.187963,0.263629,0.212132,0.193959]).round(2))
|
621
|
+
end
|
622
|
+
|
623
|
+
it "calculates rolling variance" do
|
624
|
+
var10 = @shares.rolling_variance.round(2)
|
625
|
+
expect(var10).to eq(DaruLite::Vector.new([nil,nil,nil,nil,nil,nil,nil,nil,nil,0.051632,0.043312,0.045084,0.064254,0.078773,0.087307,0.071357,0.112779,0.170432,0.151232,0.119712]).round(2))
|
626
|
+
|
627
|
+
var5 = @shares.rolling(:variance, 5).round(2)
|
628
|
+
expect(var5).to eq(DaruLite::Vector.new([nil,nil,nil,nil,0.06178,0.02815,0.04282,0.06928,0.06442,0.04627,0.01078,0.00962,0.04337,0.05657,0.06917,0.04877,0.03533,0.06950,0.04500,0.03762]).round(2))
|
629
|
+
end
|
630
|
+
|
631
|
+
it "calculates rolling non-nil count" do
|
632
|
+
@shares.rolling_count
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
context "#ema" do
|
637
|
+
it "calculates exponential moving average" do
|
638
|
+
# test default
|
639
|
+
ema10 = @shares.ema
|
640
|
+
|
641
|
+
expect(ema10[-1]) .to be_within(0.00001).of( 16.87187)
|
642
|
+
expect(ema10[-5]) .to be_within(0.00001).of( 17.19187)
|
643
|
+
expect(ema10[-10]).to be_within(0.00001).of( 17.54918)
|
644
|
+
|
645
|
+
# test with a different loopback period
|
646
|
+
ema5 = @shares.ema 5
|
647
|
+
|
648
|
+
expect(ema5[-1]) .to be_within( 0.00001).of(16.71299)
|
649
|
+
expect(ema5[-10]).to be_within( 0.00001).of(17.49079)
|
650
|
+
expect(ema5[-15]).to be_within( 0.00001).of(17.70067)
|
651
|
+
|
652
|
+
# test with a different smoother
|
653
|
+
ema_w = @shares.ema 10, true
|
654
|
+
|
655
|
+
expect(ema_w[-1]) .to be_within(0.00001).of(17.08044)
|
656
|
+
expect(ema_w[-5]) .to be_within(0.00001).of(17.33219)
|
657
|
+
expect(ema_w[-10]).to be_within(0.00001).of(17.55810)
|
658
|
+
end
|
659
|
+
end
|
660
|
+
|
661
|
+
context "#emv" do
|
662
|
+
it "calculates exponential moving variance" do
|
663
|
+
# test default
|
664
|
+
emv10 = @shares.emv
|
665
|
+
|
666
|
+
expect(emv10[-1]) .to be_within(0.00001).of(0.14441)
|
667
|
+
expect(emv10[-5]) .to be_within(0.00001).of(0.10797)
|
668
|
+
expect(emv10[-10]).to be_within(0.00001).of(0.03979)
|
669
|
+
|
670
|
+
# test with a different loopback period
|
671
|
+
emv5 = @shares.emv 5
|
672
|
+
|
673
|
+
expect(emv5[-1]) .to be_within(0.00001).of(0.05172)
|
674
|
+
expect(emv5[-10]).to be_within(0.00001).of(0.01736)
|
675
|
+
expect(emv5[-15]).to be_within(0.00001).of(0.04410)
|
676
|
+
|
677
|
+
# test with a different smoother
|
678
|
+
emv_w = @shares.emv 10, true
|
679
|
+
|
680
|
+
expect(emv_w[-1]) .to be_within(0.00001).of(0.20318)
|
681
|
+
expect(emv_w[-5]) .to be_within(0.00001).of(0.11319)
|
682
|
+
expect(emv_w[-10]).to be_within(0.00001).of(0.04289)
|
683
|
+
end
|
684
|
+
end
|
685
|
+
|
686
|
+
context "#emsd" do
|
687
|
+
it "calculates exponential moving standard deviation" do
|
688
|
+
# test default
|
689
|
+
emsd10 = @shares.emsd
|
690
|
+
|
691
|
+
expect(emsd10[-1]) .to be_within(0.00001).of(0.38002)
|
692
|
+
expect(emsd10[-5]) .to be_within(0.00001).of(0.32859)
|
693
|
+
expect(emsd10[-10]).to be_within(0.00001).of(0.19947)
|
694
|
+
|
695
|
+
# test with a different loopback period
|
696
|
+
emsd5 = @shares.emsd 5
|
697
|
+
|
698
|
+
expect(emsd5[-1]) .to be_within(0.00001).of(0.22742)
|
699
|
+
expect(emsd5[-10]).to be_within(0.00001).of(0.13174)
|
700
|
+
expect(emsd5[-15]).to be_within(0.00001).of(0.21000)
|
701
|
+
|
702
|
+
# test with a different smoother
|
703
|
+
emsd_w = @shares.emsd 10, true
|
704
|
+
|
705
|
+
expect(emsd_w[-1]) .to be_within(0.00001).of(0.45076)
|
706
|
+
expect(emsd_w[-5]) .to be_within(0.00001).of(0.33644)
|
707
|
+
expect(emsd_w[-10]).to be_within(0.00001).of(0.20710)
|
708
|
+
end
|
709
|
+
end
|
710
|
+
|
711
|
+
RSpec.shared_examples 'correct macd' do |*args|
|
712
|
+
let(:source) { DaruLite::DataFrame.from_csv('spec/fixtures/macd_data.csv') }
|
713
|
+
|
714
|
+
# skip initial records during compare as ema is sensitive to
|
715
|
+
# period used.
|
716
|
+
# http://ta-lib.org/d_api/ta_setunstableperiod.html
|
717
|
+
let(:stability_offset) { 90 }
|
718
|
+
let(:delta) { 0.001 }
|
719
|
+
let(:desc) { args.empty? ? '12_26_9' : args.join('_') }
|
720
|
+
|
721
|
+
subject { source['price'].macd(*args) }
|
722
|
+
|
723
|
+
%w[ macd macdsig macdhist ].each_with_index do |field, i|
|
724
|
+
it do
|
725
|
+
act = subject[i][stability_offset..-1]
|
726
|
+
exp = source["#{field}_#{desc}"][stability_offset..-1]
|
727
|
+
expect(act).to be_all_within(delta).of(exp)
|
728
|
+
end
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
describe '#macd' do
|
733
|
+
context 'by default' do
|
734
|
+
it_should_behave_like 'correct macd'
|
735
|
+
end
|
736
|
+
|
737
|
+
context 'custom values for fast, slow, signal' do
|
738
|
+
it_should_behave_like 'correct macd', 6, 13, 4
|
739
|
+
end
|
740
|
+
|
741
|
+
end
|
742
|
+
|
743
|
+
context "#cumsum" do
|
744
|
+
it "calculates cumulative sum" do
|
745
|
+
vector = DaruLite::Vector.new([1,2,3,4,5,6,7,8,9,10])
|
746
|
+
expect(vector.cumsum).to eq(
|
747
|
+
DaruLite::Vector.new([1,3,6,10,15,21,28,36,45,55]))
|
748
|
+
end
|
749
|
+
|
750
|
+
it "works with missing values" do
|
751
|
+
vector = DaruLite::Vector.new([1,2,nil,3,nil,4,5])
|
752
|
+
expect(vector.cumsum).to eq(
|
753
|
+
DaruLite::Vector.new([1,3,nil,6,nil,10,15]))
|
754
|
+
end
|
755
|
+
end
|
756
|
+
end
|