mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
all: refactor standard indicator helper and fix tests
This commit is contained in:
parent
0456cdc7a9
commit
3959e288fd
|
@ -27,7 +27,7 @@ func (s *LowerShadowTakeProfit) Bind(session *ExchangeSession, orderExecutor *Ge
|
||||||
s.session = session
|
s.session = session
|
||||||
s.orderExecutor = orderExecutor
|
s.orderExecutor = orderExecutor
|
||||||
|
|
||||||
stdIndicatorSet, _ := session.StandardIndicatorSet(s.Symbol)
|
stdIndicatorSet := session.StandardIndicatorSet(s.Symbol)
|
||||||
ewma := stdIndicatorSet.EWMA(s.IntervalWindow)
|
ewma := stdIndicatorSet.EWMA(s.IntervalWindow)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -438,17 +438,16 @@ func (session *ExchangeSession) initSymbol(ctx context.Context, environ *Environ
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) StandardIndicatorSet(symbol string) (*StandardIndicatorSet, bool) {
|
func (session *ExchangeSession) StandardIndicatorSet(symbol string) *StandardIndicatorSet {
|
||||||
set, ok := session.standardIndicatorSets[symbol]
|
set, ok := session.standardIndicatorSets[symbol]
|
||||||
if !ok {
|
if ok {
|
||||||
if store, ok2 := session.MarketDataStore(symbol); ok2 {
|
return set
|
||||||
set = NewStandardIndicatorSet(symbol, session.MarketDataStream, store)
|
|
||||||
session.standardIndicatorSets[symbol] = set
|
|
||||||
return set, true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return set, ok
|
store, _ := session.MarketDataStore(symbol)
|
||||||
|
set = NewStandardIndicatorSet(symbol, session.MarketDataStream, store)
|
||||||
|
session.standardIndicatorSets[symbol] = set
|
||||||
|
return set
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *ExchangeSession) Position(symbol string) (pos *types.Position, ok bool) {
|
func (session *ExchangeSession) Position(symbol string) (pos *types.Position, ok bool) {
|
||||||
|
|
|
@ -292,7 +292,7 @@ func (trader *Trader) injectFields() error {
|
||||||
return fmt.Errorf("market of symbol %s not found", symbol)
|
return fmt.Errorf("market of symbol %s not found", symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
indicatorSet, ok := session.StandardIndicatorSet(symbol)
|
indicatorSet := session.StandardIndicatorSet(symbol)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("standardIndicatorSet of symbol %s not found", symbol)
|
return fmt.Errorf("standardIndicatorSet of symbol %s not found", symbol)
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,10 @@ func Test_calculateATR(t *testing.T) {
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
atr := &ATR{IntervalWindow: types.IntervalWindow{Window: tt.window}}
|
atr := &ATR{IntervalWindow: types.IntervalWindow{Window: tt.window}}
|
||||||
atr.CalculateAndUpdate(tt.kLines)
|
for _, k := range tt.kLines {
|
||||||
|
atr.PushK(k)
|
||||||
|
}
|
||||||
|
|
||||||
got := atr.Last()
|
got := atr.Last()
|
||||||
diff := math.Trunc((got-tt.want)*100) / 100
|
diff := math.Trunc((got-tt.want)*100) / 100
|
||||||
if diff != 0 {
|
if diff != 0 {
|
||||||
|
|
|
@ -55,7 +55,7 @@ func (inc *HULL) Length() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (inc *HULL) PushK(k types.KLine) {
|
func (inc *HULL) PushK(k types.KLine) {
|
||||||
if k.EndTime.Before(inc.ma1.EndTime) {
|
if inc.ma1 != nil && inc.ma1.Length() > 0 && k.EndTime.Before(inc.ma1.EndTime) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,10 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -26,6 +27,7 @@ func Test_HULL(t *testing.T) {
|
||||||
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
if err := json.Unmarshal(randomPrices, &input); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
kLines []types.KLine
|
kLines []types.KLine
|
||||||
|
@ -44,8 +46,11 @@ func Test_HULL(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
hull := HULL{IntervalWindow: types.IntervalWindow{Window: 16}}
|
hull := &HULL{IntervalWindow: types.IntervalWindow{Window: 16}}
|
||||||
hull.CalculateAndUpdate(tt.kLines)
|
for _, k := range tt.kLines {
|
||||||
|
hull.PushK(k)
|
||||||
|
}
|
||||||
|
|
||||||
last := hull.Last()
|
last := hull.Last()
|
||||||
assert.InDelta(t, tt.want, last, Delta)
|
assert.InDelta(t, tt.want, last, Delta)
|
||||||
assert.InDelta(t, tt.next, hull.Index(1), Delta)
|
assert.InDelta(t, tt.next, hull.Index(1), Delta)
|
||||||
|
|
|
@ -25,7 +25,6 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Strategy struct {
|
type Strategy struct {
|
||||||
|
|
||||||
SourceExchangeName string `json:"sourceExchange"`
|
SourceExchangeName string `json:"sourceExchange"`
|
||||||
|
|
||||||
TargetExchangeName string `json:"targetExchange"`
|
TargetExchangeName string `json:"targetExchange"`
|
||||||
|
@ -175,11 +174,7 @@ func (s *Strategy) handleOrderUpdate(order types.Order) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) loadIndicator(sourceSession *bbgo.ExchangeSession) (types.Float64Indicator, error) {
|
func (s *Strategy) loadIndicator(sourceSession *bbgo.ExchangeSession) (types.Float64Indicator, error) {
|
||||||
var standardIndicatorSet, ok = sourceSession.StandardIndicatorSet(s.Symbol)
|
var standardIndicatorSet = sourceSession.StandardIndicatorSet(s.Symbol)
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
var iw = types.IntervalWindow{Interval: s.MovingAverageInterval, Window: s.MovingAverageWindow}
|
var iw = types.IntervalWindow{Interval: s.MovingAverageInterval, Window: s.MovingAverageWindow}
|
||||||
|
|
||||||
switch strings.ToUpper(s.MovingAverageType) {
|
switch strings.ToUpper(s.MovingAverageType) {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package funding
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
@ -93,23 +92,13 @@ func (s *Strategy) Validate() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
|
standardIndicatorSet := session.StandardIndicatorSet(s.Symbol)
|
||||||
|
|
||||||
standardIndicatorSet, ok := session.StandardIndicatorSet(s.Symbol)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
|
||||||
}
|
|
||||||
//binanceExchange, ok := session.Exchange.(*binance.Exchange)
|
|
||||||
//if !ok {
|
|
||||||
// log.Error("exchange failed")
|
|
||||||
//}
|
|
||||||
if !session.Futures {
|
if !session.Futures {
|
||||||
log.Error("futures not enabled in config for this strategy")
|
log.Error("futures not enabled in config for this strategy")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//if s.FundingRate != nil {
|
|
||||||
// go s.listenToFundingRate(ctx, binanceExchange)
|
|
||||||
//}
|
|
||||||
premiumIndex, err := session.Exchange.(*binance.Exchange).QueryPremiumIndex(ctx, s.Symbol)
|
premiumIndex, err := session.Exchange.(*binance.Exchange).QueryPremiumIndex(ctx, s.Symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("exchange does not support funding rate api")
|
log.Error("exchange does not support funding rate api")
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
||||||
position := orderExecutor.Position()
|
position := orderExecutor.Position()
|
||||||
symbol := position.Symbol
|
symbol := position.Symbol
|
||||||
store, _ := session.MarketDataStore(s.Symbol)
|
store, _ := session.MarketDataStore(s.Symbol)
|
||||||
standardIndicator, _ := session.StandardIndicatorSet(s.Symbol)
|
standardIndicator := session.StandardIndicatorSet(s.Symbol)
|
||||||
|
|
||||||
s.lastLow = fixedpoint.Zero
|
s.lastLow = fixedpoint.Zero
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
return fmt.Errorf("market %s is not defined", s.Symbol)
|
return fmt.Errorf("market %s is not defined", s.Symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
standardIndicatorSet, ok := session.StandardIndicatorSet(s.Symbol)
|
standardIndicatorSet := session.StandardIndicatorSet(s.Symbol)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/indicator"
|
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,32 +81,11 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.State = &State{Counter: 1}
|
s.State = &State{Counter: 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional: You can get the market data store from session
|
indicators := session.StandardIndicatorSet(s.Symbol)
|
||||||
store, ok := session.MarketDataStore(s.Symbol)
|
atr := indicators.ATR(types.IntervalWindow{
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("market data store %s not found", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialize a custom indicator
|
|
||||||
atr := &indicator.ATR{
|
|
||||||
IntervalWindow: types.IntervalWindow{
|
|
||||||
Interval: types.Interval1m,
|
Interval: types.Interval1m,
|
||||||
Window: 14,
|
Window: 14,
|
||||||
},
|
})
|
||||||
}
|
|
||||||
|
|
||||||
// Bind the indicator to the market data store, so that when a new kline is received,
|
|
||||||
// the indicator will be updated.
|
|
||||||
atr.Bind(store)
|
|
||||||
|
|
||||||
// To get the past kline history, call KLinesOfInterval from the market data store
|
|
||||||
klines, ok := store.KLinesOfInterval(types.Interval1m)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("market data store %s lkline not found", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use the history data to initialize the indicator
|
|
||||||
atr.CalculateAndUpdate(*klines)
|
|
||||||
|
|
||||||
// To get the market information from the current session
|
// To get the market information from the current session
|
||||||
// The market object provides the precision, MoQ (minimal of quantity) information
|
// The market object provides the precision, MoQ (minimal of quantity) information
|
||||||
|
|
|
@ -387,10 +387,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
log.Infof("adjusted minimal support volume to %s according to sensitivity %s", s.MinVolume.String(), s.Sensitivity.String())
|
log.Infof("adjusted minimal support volume to %s according to sensitivity %s", s.MinVolume.String(), s.Sensitivity.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
standardIndicatorSet, ok := session.StandardIndicatorSet(s.Symbol)
|
standardIndicatorSet := session.StandardIndicatorSet(s.Symbol)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.TriggerMovingAverage != zeroiw {
|
if s.TriggerMovingAverage != zeroiw {
|
||||||
s.triggerEMA = standardIndicatorSet.EWMA(s.TriggerMovingAverage)
|
s.triggerEMA = standardIndicatorSet.EWMA(s.TriggerMovingAverage)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package techsignal
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -145,10 +144,7 @@ func (s *Strategy) listenToFundingRate(ctx context.Context, exchange *binance.Ex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||||
standardIndicatorSet, ok := session.StandardIndicatorSet(s.Symbol)
|
standardIndicatorSet := session.StandardIndicatorSet(s.Symbol)
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.FundingRate != nil {
|
if s.FundingRate != nil {
|
||||||
if binanceExchange, ok := session.Exchange.(*binance.Exchange); ok {
|
if binanceExchange, ok := session.Exchange.(*binance.Exchange); ok {
|
||||||
|
|
|
@ -681,7 +681,7 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
|
||||||
return fmt.Errorf("maker session market %s is not defined", s.Symbol)
|
return fmt.Errorf("maker session market %s is not defined", s.Symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
standardIndicatorSet, ok := s.sourceSession.StandardIndicatorSet(s.Symbol)
|
standardIndicatorSet := s.sourceSession.StandardIndicatorSet(s.Symbol)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s standard indicator set not found", s.Symbol)
|
return fmt.Errorf("%s standard indicator set not found", s.Symbol)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user