-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathrolling_test.go
More file actions
117 lines (106 loc) · 3.1 KB
/
rolling_test.go
File metadata and controls
117 lines (106 loc) · 3.1 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
package num
import (
"reflect"
"testing"
"gitee.com/quant1x/num/labs"
)
func TestRolling(t *testing.T) {
testSliceFloat := []float64{1, 2, 3, 4, 5, 6}
//expected := []float64{1, 2, 3, 4, 5, 6}
expected := [][]float64{
{},
{},
{1, 2, 3},
{2, 3, 4},
{3, 4, 5},
{4, 5, 6},
}
output := Rolling(testSliceFloat, 3)
if reflect.DeepEqual(expected, output) != true {
t.Errorf("Got %v, want %v", output, expected)
}
output = Rolling(testSliceFloat, 3)
if reflect.DeepEqual(expected, output) != true {
t.Errorf("Got %v, want %v", output, expected)
}
output = Rolling(testSliceFloat, []int{3, 3, 3, 3, 3, 3})
if reflect.DeepEqual(expected, output) != true {
t.Errorf("Got %v, want %v", output, expected)
}
output = Rolling(testSliceFloat, []float64{3, 3, 3, 3, 3, 3})
if reflect.DeepEqual(expected, output) != true {
t.Errorf("Got %v, want %v", output, expected)
}
}
func Test_v3Rolling(t *testing.T) {
type args[E BaseType] struct {
S []E
N any
apply func(N DType, values ...E) E
}
type testCase[E BaseType] struct {
name string
args args[E]
want []E
}
tests := []testCase[float64]{
{
name: "ma",
args: args[float64]{
S: []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
N: 5,
apply: func(N DType, values ...float64) float64 {
return Sum(values) / N
},
},
want: []float64{Float64NaN(), Float64NaN(), Float64NaN(), Float64NaN(), 3, 4, 5, 6, 7, 8},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := RollingApply(tt.args.S, tt.args.N, tt.args.apply); !labs.DeepEqual(got, tt.want) {
t.Errorf("RollingApply() = %v, want %v", got, tt.want)
}
})
}
}
func TestRolling_MinPeriod(t *testing.T) {
// test Rolling blocks respect min_period by using Periods with Min set
testSlice := []float64{1, 2, 3, 4, 5}
// periods: always 3, but min_period = 4 -> should never produce a full window until index>=3
p := AnyToPeriod(3)
p.Min = 4
out := Rolling(testSlice, p)
// expect all empty blocks because min_period 4 cannot be satisfied by window 3
for i, blk := range out {
if len(blk) != 0 {
t.Fatalf("index %d: expected empty block due to min_period, got %v", i, blk)
}
}
// test v3Rolling apply (moving average) returns NaN where min_period not met
want := []float64{Float64NaN(), Float64NaN(), Float64NaN(), Float64NaN(), 3}
// Periods: 5 window, but min 5 -> only last element (index 4) has enough
p2 := AnyToPeriod(5)
p2.Min = 5
got := RollingApply(testSlice, p2, func(N DType, values ...float64) float64 {
return Sum(values) / N
})
if !labs.DeepEqual(got, want) {
t.Fatalf("v3Rolling with min_period: got %v, want %v", got, want)
}
}
func TestRollingWithMin_Helper(t *testing.T) {
xs := []float64{1, 2, 3}
// old Rolling with N=3 returns a block at index 2
out1 := Rolling(xs, 3)
if len(out1[2]) != 3 {
t.Fatalf("expected full block at index 2 for Rolling, got %v", out1[2])
}
// Rolling with min=4 should force empty blocks (new signature Rolling(S, N, min))
out2 := Rolling(xs, 3, 4)
for i, b := range out2 {
if len(b) != 0 {
t.Fatalf("expected empty block at index %d due to min, got %v", i, b)
}
}
}