diff --git a/config/buyandhold.yaml b/config/buyandhold.yaml index 6637885e1..d3057a1c9 100644 --- a/config/buyandhold.yaml +++ b/config/buyandhold.yaml @@ -59,4 +59,4 @@ exchangeStrategies: symbol: "BTCUSDT" interval: "1m" baseQuantity: 0.001 - minDropPercentage: -0.001 + minDropPercentage: -0.01 diff --git a/pkg/bbgo/environment.go b/pkg/bbgo/environment.go index bee0c2e92..2fff4f91d 100644 --- a/pkg/bbgo/environment.go +++ b/pkg/bbgo/environment.go @@ -147,7 +147,6 @@ func (environ *Environment) Init(ctx context.Context) (err error) { } session.lastPrices[kline.Symbol] = kline.Close - session.marketDataStores[kline.Symbol].AddKLine(kline) }) session.Stream.OnTradeUpdate(func(trade types.Trade) { @@ -167,8 +166,10 @@ func (environ *Environment) Init(ctx context.Context) (err error) { var lastPriceTime time.Time for interval := range types.SupportedIntervals { + // avoid querying the last unclosed kline + endTime := environ.startTime.Add(- interval.Duration()) kLines, err := session.Exchange.QueryKLines(ctx, symbol, interval, types.KLineQueryOptions{ - EndTime: &environ.startTime, + EndTime: &endTime, Limit: 500, // indicators need at least 100 }) if err != nil { diff --git a/pkg/indicator/boll.go b/pkg/indicator/boll.go index 55e7e0e63..47fe9e282 100644 --- a/pkg/indicator/boll.go +++ b/pkg/indicator/boll.go @@ -80,7 +80,7 @@ func (inc *BOLL) calculateAndUpdate(kLines []types.KLine) { } var recentK = kLines[index-(inc.Window-1) : index+1] - sma, err := calculateSMA(recentK, inc.Window) + sma, err := calculateSMA(recentK, inc.Window, KLineClosePriceMapper) if err != nil { log.WithError(err).Error("SMA error") return diff --git a/pkg/indicator/ewma.go b/pkg/indicator/ewma.go index f8e0990aa..9c8ddab15 100644 --- a/pkg/indicator/ewma.go +++ b/pkg/indicator/ewma.go @@ -38,9 +38,12 @@ func (inc *EWMA) calculateAndUpdate(allKLines []types.KLine) { // for the first value, we should use the close price inc.Values = []float64{priceF(allKLines[0])} } else { + // from = len(inc.Values) + // update ewma with the existing values for i := dataLen - 1; i > 0; i-- { - if allKLines[i].StartTime.After(inc.LastOpenTime) { + var k = allKLines[i] + if k.StartTime.After(inc.LastOpenTime) { from = i } else { break @@ -57,13 +60,13 @@ func (inc *EWMA) calculateAndUpdate(allKLines []types.KLine) { } if len(inc.Values) != dataLen { - log.Warnf("EMA %s (%d) value length (%d) != all kline data length (%d)", inc.Interval, inc.Window, len(inc.Values), dataLen) + log.Warnf("%s EMA (%d) value length (%d) != all kline data length (%d)", inc.Interval, inc.Window, len(inc.Values), dataLen) } v1 := math.Floor(inc.Values[len(inc.Values)-1]*100.0) / 100.0 v2 := math.Floor(CalculateKLineEWMA(allKLines, priceF, inc.Window)*100.0) / 100.0 if v1 != v2 { - log.Warnf("ACCUMULATED EMA %s (%d) %f != EMA %f", inc.Interval, inc.Window, v1, v2) + log.Warnf("ACCUMULATED %s EMA (%d) %f != EMA %f", inc.Interval, inc.Window, v1, v2) } } diff --git a/pkg/indicator/sma.go b/pkg/indicator/sma.go index 9ff7b7496..a44c6e27e 100644 --- a/pkg/indicator/sma.go +++ b/pkg/indicator/sma.go @@ -44,7 +44,7 @@ func (inc *SMA) calculateAndUpdate(kLines []types.KLine) { var recentK = kLines[index-(inc.Window-1) : index+1] - sma, err := calculateSMA(recentK, inc.Window) + sma, err := calculateSMA(recentK, inc.Window, KLineClosePriceMapper) if err != nil { log.WithError(err).Error("SMA error") return @@ -67,7 +67,7 @@ func (inc *SMA) Bind(updater KLineWindowUpdater) { updater.OnKLineWindowUpdate(inc.handleKLineWindowUpdate) } -func calculateSMA(kLines []types.KLine, window int) (float64, error) { +func calculateSMA(kLines []types.KLine, window int, priceF KLinePriceMapper) (float64, error) { length := len(kLines) if length == 0 || length < window { return 0.0, fmt.Errorf("insufficient elements for calculating SMA with window = %d", window) @@ -75,7 +75,7 @@ func calculateSMA(kLines []types.KLine, window int) (float64, error) { sum := 0.0 for _, k := range kLines { - sum += k.Close + sum += priceF(k) } avg := sum / float64(window)