mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
indicator: add adx
This commit is contained in:
parent
d58461d1cf
commit
474a8ab864
69
pkg/indicator/v2/adx.go
Normal file
69
pkg/indicator/v2/adx.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package indicatorv2
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type ADXStream struct {
|
||||
*types.Float64Series
|
||||
Plus, Minus *types.Float64Series
|
||||
|
||||
window int
|
||||
prevHigh, prevLow fixedpoint.Value
|
||||
}
|
||||
|
||||
func ADX(source KLineSubscription, window int) *ADXStream {
|
||||
var (
|
||||
atr = ATR2(source, window)
|
||||
dmp = types.NewFloat64Series()
|
||||
dmm = types.NewFloat64Series()
|
||||
adx = types.NewFloat64Series()
|
||||
sdmp = RMA2(dmp, window, true)
|
||||
sdmm = RMA2(dmm, window, true)
|
||||
sadx = RMA2(adx, window, true)
|
||||
s = &ADXStream{
|
||||
window: window,
|
||||
Plus: types.NewFloat64Series(),
|
||||
Minus: types.NewFloat64Series(),
|
||||
Float64Series: types.NewFloat64Series(),
|
||||
prevHigh: fixedpoint.Zero,
|
||||
prevLow: fixedpoint.Zero,
|
||||
}
|
||||
)
|
||||
|
||||
source.AddSubscriber(func(k types.KLine) {
|
||||
up, down := k.High.Sub(s.prevHigh), -k.Low.Sub(s.prevLow)
|
||||
if up.Compare(down) > 0 && up > 0 {
|
||||
dmp.PushAndEmit(up.Float64())
|
||||
} else {
|
||||
dmp.PushAndEmit(0.0)
|
||||
}
|
||||
|
||||
if down.Compare(up) > 0 && down > 0 {
|
||||
dmm.PushAndEmit(down.Float64())
|
||||
} else {
|
||||
dmm.PushAndEmit(0.0)
|
||||
}
|
||||
|
||||
s.Plus.PushAndEmit(sdmp.Last(0) / atr.Last(0) * 100)
|
||||
s.Minus.PushAndEmit(sdmm.Last(0) / atr.Last(0) * 100)
|
||||
|
||||
sum := s.Plus.Last(0) + s.Minus.Last(0)
|
||||
if sum == 0 {
|
||||
sum = 1
|
||||
}
|
||||
adx.PushAndEmit(math.Abs(s.Plus.Last(0)-s.Minus.Last(0)) / sum)
|
||||
|
||||
s.PushAndEmit(sadx.Last(0) * 100)
|
||||
s.prevHigh, s.prevLow = k.High, k.Low
|
||||
s.Truncate()
|
||||
})
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *ADXStream) Truncate() {
|
||||
s.Slice = s.Slice.Truncate(MaxNumOfRMA)
|
||||
}
|
61
pkg/indicator/v2/adx_test.go
Normal file
61
pkg/indicator/v2/adx_test.go
Normal file
|
@ -0,0 +1,61 @@
|
|||
package indicatorv2
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
func Test_ADX(t *testing.T) {
|
||||
var bytes = []byte(`{
|
||||
"high": [40145.0, 40186.36, 40196.39, 40344.6, 40245.48, 40273.24, 40464.0, 40699.0, 40627.48, 40436.31, 40370.0, 40376.8, 40227.03, 40056.52, 39721.7, 39597.94, 39750.15, 39927.0, 40289.02, 40189.0],
|
||||
"low": [39870.71, 39834.98, 39866.31, 40108.31, 40016.09, 40094.66, 40105.0, 40196.48, 40154.99, 39800.0, 39959.21, 39922.98, 39940.02, 39632.0, 39261.39, 39254.63, 39473.91, 39555.51, 39819.0, 40006.84],
|
||||
"close": [40105.78, 39935.23, 40183.97, 40182.03, 40212.26, 40149.99, 40378.0, 40618.37, 40401.03, 39990.39, 40179.13, 40097.23, 40014.72, 39667.85, 39303.1, 39519.99, 39693.79, 39827.96, 40074.94, 40059.84]
|
||||
}`)
|
||||
|
||||
var buildKLines = func(bytes []byte) (kLines []types.KLine) {
|
||||
var prices map[string][]fixedpoint.Value
|
||||
_ = json.Unmarshal(bytes, &prices)
|
||||
for i, h := range prices["high"] {
|
||||
kLine := types.KLine{High: h, Low: prices["low"][i], Close: prices["close"][i]}
|
||||
kLines = append(kLines, kLine)
|
||||
}
|
||||
return kLines
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
kLines []types.KLine
|
||||
window int
|
||||
want float64
|
||||
}{
|
||||
{
|
||||
name: "test_binance_btcusdt_1h",
|
||||
kLines: buildKLines(bytes),
|
||||
window: 7,
|
||||
want: 31.895091,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
stream := &types.StandardStream{}
|
||||
|
||||
kLines := KLines(stream, "", "")
|
||||
adx := ADX(kLines, tt.window)
|
||||
|
||||
for _, k := range tt.kLines {
|
||||
stream.EmitKLineClosed(k)
|
||||
}
|
||||
|
||||
got := adx.Last(0)
|
||||
diff := math.Trunc((got-tt.want)*100) / 100
|
||||
if diff != 0 {
|
||||
t.Errorf("ADX() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user