mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
test: add test cases for dema, hull, tema, till, vidya and zlema indicators
This commit is contained in:
parent
5dc69a6175
commit
c18f684afd
55
pkg/indicator/dema_test.go
Normal file
55
pkg/indicator/dema_test.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
python:
|
||||
|
||||
import pandas as pd
|
||||
s = pd.Series(([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9])
|
||||
ma1 = s.ewm(span=16).mean()
|
||||
ma2 = ma1.ewm(span=16).mean()
|
||||
result = (2 * ma1 - ma2)
|
||||
print(result)
|
||||
*/
|
||||
func Test_DEMA(t *testing.T) {
|
||||
var Delta = 4e-2
|
||||
var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`)
|
||||
var input []fixedpoint.Value
|
||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
want float64
|
||||
next float64
|
||||
all int
|
||||
}{
|
||||
{
|
||||
name: "random_case",
|
||||
kLines: buildKLines(input),
|
||||
want: 6.420838,
|
||||
next: 5.609367,
|
||||
all: 50,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
dema := DEMA{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
dema.calculateAndUpdate(tt.kLines)
|
||||
last := dema.Last()
|
||||
assert.InDelta(t, tt.want, last, Delta)
|
||||
assert.InDelta(t, tt.next, dema.Index(1), Delta)
|
||||
assert.Equal(t, tt.all, dema.Length())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@ type HULL struct {
|
|||
}
|
||||
|
||||
func (inc *HULL) Update(value float64) {
|
||||
if inc.result.Length() == 0 {
|
||||
if inc.result == nil {
|
||||
inc.ma1 = &EWMA{IntervalWindow: types.IntervalWindow{inc.Interval, inc.Window / 2}}
|
||||
inc.ma2 = &EWMA{IntervalWindow: types.IntervalWindow{inc.Interval, inc.Window}}
|
||||
inc.result = &EWMA{IntervalWindow: types.IntervalWindow{inc.Interval, int(math.Sqrt(float64(inc.Window)))}}
|
||||
|
@ -46,7 +46,7 @@ var _ types.Series = &HULL{}
|
|||
// TODO: should we just ignore the possible overlapping?
|
||||
func (inc *HULL) calculateAndUpdate(allKLines []types.KLine) {
|
||||
doable := false
|
||||
if inc.ma1.Length() == 0 {
|
||||
if inc.ma1 == nil || inc.ma1.Length() == 0 {
|
||||
doable = true
|
||||
}
|
||||
for _, k := range allKLines {
|
||||
|
|
55
pkg/indicator/hull_test.go
Normal file
55
pkg/indicator/hull_test.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
python:
|
||||
|
||||
import pandas as pd
|
||||
s = pd.Series(([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9])
|
||||
ma1 = s.ewm(span=8).mean()
|
||||
ma2 = s.ewm(span=16).mean()
|
||||
result = (2 * ma1 - ma2).ewm(span=4).mean()
|
||||
print(result)
|
||||
*/
|
||||
func Test_HULL(t *testing.T) {
|
||||
var Delta = 1.5e-2
|
||||
var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`)
|
||||
var input []fixedpoint.Value
|
||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
want float64
|
||||
next float64
|
||||
all int
|
||||
}{
|
||||
{
|
||||
name: "random_case",
|
||||
kLines: buildKLines(input),
|
||||
want: 6.002935,
|
||||
next: 5.167056,
|
||||
all: 50,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
hull := HULL{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
hull.calculateAndUpdate(tt.kLines)
|
||||
last := hull.Last()
|
||||
assert.InDelta(t, tt.want, last, Delta)
|
||||
assert.InDelta(t, tt.next, hull.Index(1), Delta)
|
||||
assert.Equal(t, tt.all, hull.Length())
|
||||
})
|
||||
}
|
||||
}
|
56
pkg/indicator/tema_test.go
Normal file
56
pkg/indicator/tema_test.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
python:
|
||||
|
||||
import pandas as pd
|
||||
s = pd.Series(([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9])
|
||||
ma1 = s.ewm(span=16).mean()
|
||||
ma2 = ma1.ewm(span=16).mean()
|
||||
ma3 = ma2.ewm(span=16).mean()
|
||||
result = (3 * ma1 - 3 * ma2 + ma3)
|
||||
print(result)
|
||||
*/
|
||||
func Test_TEMA(t *testing.T) {
|
||||
var Delta = 4.3e-2
|
||||
var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`)
|
||||
var input []fixedpoint.Value
|
||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
want float64
|
||||
next float64
|
||||
all int
|
||||
}{
|
||||
{
|
||||
name: "random_case",
|
||||
kLines: buildKLines(input),
|
||||
want: 7.163145,
|
||||
next: 6.106229,
|
||||
all: 50,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
tema := TEMA{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
tema.calculateAndUpdate(tt.kLines)
|
||||
last := tema.Last()
|
||||
assert.InDelta(t, tt.want, last, Delta)
|
||||
assert.InDelta(t, tt.next, tema.Index(1), Delta)
|
||||
assert.Equal(t, tt.all, tema.Length())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -41,7 +41,7 @@ func (inc *TILL) Update(value float64) {
|
|||
inc.c1 = -cube
|
||||
inc.c2 = 3.*square + 3.*cube
|
||||
inc.c3 = -6.*square - 3*inc.VolumeFactor - 3*cube
|
||||
inc.c4 = 1 + 3*inc.VolumeFactor + cube + 3*square
|
||||
inc.c4 = 1. + 3.*inc.VolumeFactor + cube + 3.*square
|
||||
}
|
||||
|
||||
inc.e1.Update(value)
|
||||
|
@ -82,7 +82,7 @@ var _ types.Series = &TILL{}
|
|||
|
||||
func (inc *TILL) calculateAndUpdate(allKLines []types.KLine) {
|
||||
doable := false
|
||||
if inc.e1.Length() == 0 {
|
||||
if inc.e1 == nil {
|
||||
doable = true
|
||||
}
|
||||
for _, k := range allKLines {
|
||||
|
|
65
pkg/indicator/till_test.go
Normal file
65
pkg/indicator/till_test.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
python:
|
||||
|
||||
import pandas as pd
|
||||
s = pd.Series(([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9])
|
||||
ma1 = s.ewm(span=16).mean()
|
||||
ma2 = ma1.ewm(span=16).mean()
|
||||
ma3 = ma2.ewm(span=16).mean()
|
||||
ma4 = ma3.ewm(span=16).mean()
|
||||
ma5 = ma4.ewm(span=16).mean()
|
||||
ma6 = ma5.ewm(span=16).mean()
|
||||
square = 0.7 * 0.7
|
||||
cube = 0.7 ** 3
|
||||
c1 = -cube
|
||||
c2 = 3 * square + 3 * cube
|
||||
c3 = -6 * square - 3 * 0.7 - 3 * cube
|
||||
c4 = 1 + 3 * 0.7 + cube + 3 * square
|
||||
result = (c1 * ma6 + c2 * ma5 + c3 * ma4 + c4 * ma3)
|
||||
print(result)
|
||||
*/
|
||||
func Test_TILL(t *testing.T) {
|
||||
var Delta = 0.18
|
||||
var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`)
|
||||
var input []fixedpoint.Value
|
||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
want float64
|
||||
next float64
|
||||
all int
|
||||
}{
|
||||
{
|
||||
name: "random_case",
|
||||
kLines: buildKLines(input),
|
||||
want: 4.528608,
|
||||
next: 4.457134,
|
||||
all: 50,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
till := TILL{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
till.calculateAndUpdate(tt.kLines)
|
||||
last := till.Last()
|
||||
assert.InDelta(t, tt.want, last, Delta)
|
||||
assert.InDelta(t, tt.next, till.Index(1), Delta)
|
||||
assert.Equal(t, tt.all, till.Length())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ func (inc *VIDYA) Update(value float64) {
|
|||
if len(inc.input) > MaxNumOfEWMA {
|
||||
inc.input = inc.input[MaxNumOfEWMATruncateSize-1:]
|
||||
}
|
||||
upsum := 0.
|
||||
/*upsum := 0.
|
||||
downsum := 0.
|
||||
for i := 0; i < inc.Window; i++ {
|
||||
if len(inc.input) <= i+1 {
|
||||
|
@ -44,7 +44,9 @@ func (inc *VIDYA) Update(value float64) {
|
|||
if upsum == 0 && downsum == 0 {
|
||||
return
|
||||
}
|
||||
CMO := math.Abs((upsum - downsum) / (upsum + downsum))
|
||||
CMO := math.Abs((upsum - downsum) / (upsum + downsum))*/
|
||||
change := types.Change(&inc.input)
|
||||
CMO := math.Abs(types.Sum(change, inc.Window) / types.Sum(types.Abs(change), inc.Window))
|
||||
alpha := 2. / float64(inc.Window+1)
|
||||
inc.Values.Push(value*alpha*CMO + inc.Values.Last()*(1.-alpha*CMO))
|
||||
if inc.Values.Length() > MaxNumOfEWMA {
|
||||
|
|
19
pkg/indicator/vidya_test.go
Normal file
19
pkg/indicator/vidya_test.go
Normal file
|
@ -0,0 +1,19 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_VIDYA(t *testing.T) {
|
||||
vidya := &VIDYA{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
vidya.Update(1)
|
||||
assert.Equal(t, vidya.Last(), 1.)
|
||||
vidya.Update(2)
|
||||
newV := 2./17.*2. + 1.*(1.-2./17.)
|
||||
assert.Equal(t, vidya.Last(), newV)
|
||||
vidya.Update(1)
|
||||
assert.Equal(t, vidya.Last(), vidya.Index(1))
|
||||
}
|
|
@ -11,7 +11,7 @@ import (
|
|||
type ZLEMA struct {
|
||||
types.IntervalWindow
|
||||
|
||||
data *EWMA
|
||||
data types.Float64Slice
|
||||
zlema *EWMA
|
||||
lag int
|
||||
|
||||
|
@ -32,13 +32,17 @@ func (inc *ZLEMA) Length() int {
|
|||
|
||||
func (inc *ZLEMA) Update(value float64) {
|
||||
if inc.lag == 0 || inc.zlema == nil {
|
||||
inc.data = &EWMA{IntervalWindow: types.IntervalWindow{inc.Interval, inc.Window}}
|
||||
inc.zlema = &EWMA{IntervalWindow: types.IntervalWindow{inc.Interval, inc.Window}}
|
||||
inc.lag = (inc.Window - 1) / 2
|
||||
inc.lag = int((float64(inc.Window)-1.)/2. + 0.5)
|
||||
}
|
||||
inc.data.Update(value)
|
||||
data := inc.data.Last()
|
||||
emaData := 2*data - inc.data.Index(inc.lag)
|
||||
inc.data.Push(value)
|
||||
if len(inc.data) > MaxNumOfEWMA {
|
||||
inc.data = inc.data[MaxNumOfEWMATruncateSize-1:]
|
||||
}
|
||||
if inc.lag >= inc.data.Length() {
|
||||
return
|
||||
}
|
||||
emaData := 2.*value - inc.data[len(inc.data)-1-inc.lag]
|
||||
inc.zlema.Update(emaData)
|
||||
}
|
||||
|
||||
|
|
55
pkg/indicator/zlema_test.go
Normal file
55
pkg/indicator/zlema_test.go
Normal file
|
@ -0,0 +1,55 @@
|
|||
package indicator
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
/*
|
||||
python:
|
||||
|
||||
import pandas as pd
|
||||
s = pd.Series(([0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9])
|
||||
lag = int((16-1)/2)
|
||||
emadata = s + (s - s.shift(lag))
|
||||
result = emadata.ewm(span=16).mean()
|
||||
print(result)
|
||||
*/
|
||||
func Test_ZLEMA(t *testing.T) {
|
||||
var Delta = 6.5e-2
|
||||
var randomPrices = []byte(`[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`)
|
||||
var input []fixedpoint.Value
|
||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
want float64
|
||||
next float64
|
||||
all int
|
||||
}{
|
||||
{
|
||||
name: "random_case",
|
||||
kLines: buildKLines(input),
|
||||
want: 6.622881,
|
||||
next: 5.231044,
|
||||
all: 42,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
zlema := ZLEMA{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||
zlema.calculateAndUpdate(tt.kLines)
|
||||
last := zlema.Last()
|
||||
assert.InDelta(t, tt.want, last, Delta)
|
||||
assert.InDelta(t, tt.next, zlema.Index(1), Delta)
|
||||
assert.Equal(t, tt.all, zlema.Length())
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user