[add] 新增NR和CCI指标

This commit is contained in:
lychiyu 2024-08-31 16:47:20 +08:00
parent 9f5b2c470f
commit 76a133a6b4
5 changed files with 113 additions and 782 deletions

8
go.mod
View File

@ -4,8 +4,6 @@ module git.qtrade.icu/lychiyu/bbgo
go 1.22.4
toolchain go1.23.0
require (
github.com/DATA-DOG/go-sqlmock v1.5.2
github.com/Masterminds/squirrel v1.5.4
@ -50,9 +48,12 @@ require (
github.com/stretchr/testify v1.9.0
github.com/valyala/fastjson v1.6.4
github.com/wcharczuk/go-chart/v2 v2.1.1
github.com/webview/webview v0.0.0-20210216142346-e0bfdf0e5d90
github.com/x-cray/logrus-prefixed-formatter v0.5.2
github.com/zserge/lorca v0.1.10
go.uber.org/mock v0.4.0
go.uber.org/multierr v1.11.0
golang.org/x/oauth2 v0.21.0
golang.org/x/sync v0.7.0
golang.org/x/time v0.5.0
gonum.org/v1/gonum v0.15.0
@ -79,6 +80,7 @@ require (
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@ -126,6 +128,7 @@ require (
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rollbar/rollbar-go v1.0.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
@ -147,7 +150,6 @@ require (
golang.org/x/image v0.14.0 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect

791
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -112,3 +112,10 @@ func (i *IndicatorSet) ATRP(interval types.Interval, window int) *indicatorv2.AT
func (i *IndicatorSet) ADX(interval types.Interval, window int) *indicatorv2.ADXStream {
return indicatorv2.ADX(i.KLines(interval), window)
}
func (i *IndicatorSet) NR(interval types.Interval, nrCount int, strictMode bool) *indicatorv2.NRStrean {
return indicatorv2.NR(i.KLines(interval), nrCount, strictMode)
}
func (i *IndicatorSet) CCI(interval types.Interval, window int) *indicatorv2.CCIStream {
return indicatorv2.CCI(indicatorv2.HLC3(i.KLines(interval)), window)
}

View File

@ -44,7 +44,7 @@ func CCI(source types.Float64Source, window int) *CCIStream {
return s
}
func (s *CCIStream) Calculate(value float64) float64 {
func (s *CCIStream) Calculate1(value float64) float64 {
var tp = value
if s.TypicalPrice.Length() > 0 {
tp = s.TypicalPrice.Last(0) - s.source.Last(s.window) + value
@ -63,3 +63,20 @@ func (s *CCIStream) Calculate(value float64) float64 {
cci := (value - ma) / (0.015 * md)
return cci
}
func (s *CCIStream) Calculate(value float64) float64 {
ma := 0.
for i := 0; i < s.window; i++ {
ma += s.source.Last(i)
}
ma = ma / float64(s.window)
md := 0.
for i := 0; i < s.window; i++ {
md += math.Abs(s.source.Last(i) - ma)
}
md = md / float64(s.window)
cci := (value - ma) / (0.015 * md)
return cci
}

70
pkg/indicator/v2/nr.go Normal file
View File

@ -0,0 +1,70 @@
package indicatorv2
import (
"git.qtrade.icu/lychiyu/bbgo/pkg/types"
)
type NRStrean struct {
*types.Float64Series
nrCount int
kLines []types.KLine
strictMode bool
NrKLine types.KLine
}
func NR(source KLineSubscription, nrCount int, strictMode bool) *NRStrean {
s := &NRStrean{
nrCount: nrCount,
Float64Series: types.NewFloat64Series(),
}
source.AddSubscriber(func(k types.KLine) {
s.calculateAndPush(k)
})
return s
}
func (s *NRStrean) calculateAndPush(k types.KLine) {
s.kLines = append(s.kLines, k)
if len(s.kLines) < s.nrCount {
return
}
nr := s.kLines[len(s.kLines)-1]
preNr := s.kLines[len(s.kLines)-2]
isNR := true
if preNr.High < nr.High || preNr.Low > nr.Low {
isNR = false
return
}
for i := len(s.kLines) - s.nrCount; i < len(s.kLines); i++ {
// 这种是所有的kline都要高于nr
//if s.CalKLines[i].High > nr.High || s.CalKLines[i].Low < nr.Low {
// isNR = false
// break
//}
if s.strictMode {
if s.kLines[i].High-s.kLines[i].Low < nr.High-nr.Low {
isNR = false
break
}
} else {
if (s.kLines[i].High-s.kLines[i].Low)/s.kLines[i].Low < (nr.High-nr.Low)/nr.Low {
isNR = false
break
}
}
}
if isNR {
s.NrKLine = nr
s.PushAndEmit(nr.High.Float64())
}
return
}