mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
Merge pull request #844 from c9s/strategy/pivotshort
strategy/pivotshort: refactor and update indicator api usage
This commit is contained in:
commit
605c66556e
|
@ -34,9 +34,3 @@ func (inc *Low) PushK(k types.KLine) {
|
|||
inc.EndTime = k.EndTime.Time()
|
||||
inc.EmitUpdate(inc.Last())
|
||||
}
|
||||
|
||||
func (inc *Low) LoadK(allKLines []types.KLine) {
|
||||
for _, k := range allKLines {
|
||||
inc.PushK(k)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,42 +60,22 @@ func (inc *MACD) Last() float64 {
|
|||
return inc.Values[len(inc.Values)-1]
|
||||
}
|
||||
|
||||
func (inc *MACD) Length() int {
|
||||
return len(inc.Values)
|
||||
}
|
||||
|
||||
func (inc *MACD) PushK(k types.KLine) {
|
||||
inc.Update(k.Close.Float64())
|
||||
}
|
||||
|
||||
func (inc *MACD) CalculateAndUpdate(allKLines []types.KLine) {
|
||||
if len(allKLines) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
last := allKLines[len(allKLines)-1]
|
||||
if len(inc.Values) == 0 {
|
||||
for _, k := range allKLines {
|
||||
if inc.EndTime != zeroTime && !k.EndTime.After(inc.EndTime) {
|
||||
continue
|
||||
}
|
||||
|
||||
inc.PushK(k)
|
||||
}
|
||||
} else {
|
||||
inc.PushK(last)
|
||||
}
|
||||
|
||||
inc.EmitUpdate(inc.Last())
|
||||
inc.EndTime = last.EndTime.Time()
|
||||
func (inc *MACD) MACD() types.SeriesExtend {
|
||||
out := &MACDValues{MACD: inc}
|
||||
out.SeriesBase.Series = out
|
||||
return out
|
||||
}
|
||||
|
||||
func (inc *MACD) handleKLineWindowUpdate(interval types.Interval, window types.KLineWindow) {
|
||||
if inc.Interval != interval {
|
||||
return
|
||||
}
|
||||
|
||||
inc.CalculateAndUpdate(window)
|
||||
}
|
||||
|
||||
func (inc *MACD) Bind(updater KLineWindowUpdater) {
|
||||
updater.OnKLineWindowUpdate(inc.handleKLineWindowUpdate)
|
||||
func (inc *MACD) Singals() types.SeriesExtend {
|
||||
return inc.SignalLine
|
||||
}
|
||||
|
||||
type MACDValues struct {
|
||||
|
@ -123,13 +103,3 @@ func (inc *MACDValues) Index(i int) float64 {
|
|||
func (inc *MACDValues) Length() int {
|
||||
return len(inc.Values)
|
||||
}
|
||||
|
||||
func (inc *MACD) MACD() types.SeriesExtend {
|
||||
out := &MACDValues{MACD: inc}
|
||||
out.SeriesBase.Series = out
|
||||
return out
|
||||
}
|
||||
|
||||
func (inc *MACD) Singals() types.SeriesExtend {
|
||||
return inc.SignalLine
|
||||
}
|
||||
|
|
|
@ -41,7 +41,9 @@ func Test_calculateMACD(t *testing.T) {
|
|||
t.Run(tt.name, func(t *testing.T) {
|
||||
iw := types.IntervalWindow{Window: 9}
|
||||
macd := MACD{IntervalWindow: iw, ShortPeriod: 12, LongPeriod: 26}
|
||||
macd.CalculateAndUpdate(tt.kLines)
|
||||
for _, k := range tt.kLines {
|
||||
macd.PushK(k)
|
||||
}
|
||||
|
||||
got := macd.Last()
|
||||
diff := math.Trunc((got-tt.want)*100) / 100
|
||||
|
|
|
@ -34,7 +34,7 @@ type BreakLow struct {
|
|||
TrendEMA *types.IntervalWindow `json:"trendEMA"`
|
||||
|
||||
lastLow fixedpoint.Value
|
||||
pivot *indicator.Pivot
|
||||
pivot *indicator.PivotLow
|
||||
stopEWMA *indicator.EWMA
|
||||
|
||||
trendEWMA *indicator.EWMA
|
||||
|
@ -65,14 +65,11 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
|||
|
||||
position := orderExecutor.Position()
|
||||
symbol := position.Symbol
|
||||
store, _ := session.MarketDataStore(s.Symbol)
|
||||
standardIndicator := session.StandardIndicatorSet(s.Symbol)
|
||||
|
||||
s.lastLow = fixedpoint.Zero
|
||||
|
||||
s.pivot = &indicator.Pivot{IntervalWindow: s.IntervalWindow}
|
||||
s.pivot.Bind(store)
|
||||
preloadPivot(s.pivot, store)
|
||||
s.pivot = standardIndicator.PivotLow(s.IntervalWindow)
|
||||
|
||||
if s.StopEMA != nil {
|
||||
s.stopEWMA = standardIndicator.EWMA(*s.StopEMA)
|
||||
|
@ -89,13 +86,13 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
|||
|
||||
// update pivot low data
|
||||
session.MarketDataStream.OnStart(func() {
|
||||
lastLow := fixedpoint.NewFromFloat(s.pivot.LastLow())
|
||||
lastLow := fixedpoint.NewFromFloat(s.pivot.Lows.Last())
|
||||
if lastLow.IsZero() {
|
||||
return
|
||||
}
|
||||
|
||||
if lastLow.Compare(s.lastLow) != 0 {
|
||||
bbgo.Notify("%s found new pivot low: %f", s.Symbol, s.pivot.LastLow())
|
||||
bbgo.Notify("%s found new pivot low: %f", s.Symbol, s.pivot.Lows.Last())
|
||||
}
|
||||
|
||||
s.lastLow = lastLow
|
||||
|
@ -120,8 +117,7 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
|||
})
|
||||
|
||||
session.MarketDataStream.OnKLineClosed(types.KLineWith(symbol, s.Interval, func(kline types.KLine) {
|
||||
|
||||
lastLow := fixedpoint.NewFromFloat(s.pivot.LastLow())
|
||||
lastLow := fixedpoint.NewFromFloat(s.pivot.Lows.Last())
|
||||
if lastLow.IsZero() {
|
||||
return
|
||||
}
|
||||
|
@ -133,13 +129,12 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
|||
s.lastLow = lastLow
|
||||
s.pivotLowPrices = append(s.pivotLowPrices, s.lastLow)
|
||||
|
||||
|
||||
// when position is opened, do not send pivot low notify
|
||||
if position.IsOpened(kline.Close) {
|
||||
return
|
||||
}
|
||||
|
||||
bbgo.Notify("%s new pivot low: %f", s.Symbol, s.pivot.LastLow())
|
||||
bbgo.Notify("%s new pivot low: %f", s.Symbol, s.pivot.Lows.Last())
|
||||
}))
|
||||
|
||||
session.MarketDataStream.OnKLineClosed(types.KLineWith(symbol, types.Interval1m, func(kline types.KLine) {
|
||||
|
@ -246,4 +241,3 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener
|
|||
}
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ type ResistanceShort struct {
|
|||
session *bbgo.ExchangeSession
|
||||
orderExecutor *bbgo.GeneralOrderExecutor
|
||||
|
||||
resistancePivot *indicator.Pivot
|
||||
resistancePivot *indicator.PivotLow
|
||||
resistancePrices []float64
|
||||
currentResistancePrice fixedpoint.Value
|
||||
|
||||
|
@ -47,19 +47,10 @@ func (s *ResistanceShort) Bind(session *bbgo.ExchangeSession, orderExecutor *bbg
|
|||
s.GroupDistance = fixedpoint.NewFromFloat(0.01)
|
||||
}
|
||||
|
||||
store, _ := session.MarketDataStore(s.Symbol)
|
||||
|
||||
s.resistancePivot = &indicator.Pivot{IntervalWindow: s.IntervalWindow}
|
||||
s.resistancePivot.Bind(store)
|
||||
|
||||
// preload history kline data to the resistance pivot indicator
|
||||
// we use the last kline to find the higher lows
|
||||
lastKLine := preloadPivot(s.resistancePivot, store)
|
||||
s.resistancePivot = session.StandardIndicatorSet(s.Symbol).PivotLow(s.IntervalWindow)
|
||||
|
||||
// use the last kline from the history before we get the next closed kline
|
||||
if lastKLine != nil {
|
||||
s.updateResistanceOrders(lastKLine.Close)
|
||||
}
|
||||
s.updateResistanceOrders(fixedpoint.NewFromFloat(s.resistancePivot.Lows.Last()))
|
||||
|
||||
session.MarketDataStream.OnKLineClosed(types.KLineWith(s.Symbol, s.Interval, func(kline types.KLine) {
|
||||
position := s.orderExecutor.Position()
|
||||
|
|
|
@ -35,7 +35,7 @@ type SupportTakeProfit struct {
|
|||
|
||||
Ratio fixedpoint.Value `json:"ratio"`
|
||||
|
||||
pivot *indicator.Pivot
|
||||
pivot *indicator.PivotLow
|
||||
orderExecutor *bbgo.GeneralOrderExecutor
|
||||
session *bbgo.ExchangeSession
|
||||
activeOrders *bbgo.ActiveOrderBook
|
||||
|
@ -62,11 +62,8 @@ func (s *SupportTakeProfit) Bind(session *bbgo.ExchangeSession, orderExecutor *b
|
|||
s.activeOrders.BindStream(session.UserDataStream)
|
||||
|
||||
position := orderExecutor.Position()
|
||||
symbol := position.Symbol
|
||||
store, _ := session.MarketDataStore(symbol)
|
||||
s.pivot = &indicator.Pivot{IntervalWindow: s.IntervalWindow}
|
||||
s.pivot.Bind(store)
|
||||
preloadPivot(s.pivot, store)
|
||||
|
||||
s.pivot = session.StandardIndicatorSet(s.Symbol).PivotLow(s.IntervalWindow)
|
||||
|
||||
session.MarketDataStream.OnKLineClosed(types.KLineWith(s.Symbol, s.Interval, func(kline types.KLine) {
|
||||
if !s.updateSupportPrice(kline.Close) {
|
||||
|
@ -88,7 +85,7 @@ func (s *SupportTakeProfit) Bind(session *bbgo.ExchangeSession, orderExecutor *b
|
|||
|
||||
bbgo.Notify("placing %s take profit order at price %f", s.Symbol, buyPrice.Float64())
|
||||
createdOrders, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
||||
Symbol: symbol,
|
||||
Symbol: s.Symbol,
|
||||
Type: types.OrderTypeLimitMaker,
|
||||
Side: types.SideTypeBuy,
|
||||
Price: buyPrice,
|
||||
|
@ -215,7 +212,6 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
|||
s.ExitMethods.SetAndSubscribe(session, s)
|
||||
}
|
||||
|
||||
|
||||
func (s *Strategy) CurrentPosition() *types.Position {
|
||||
return s.Position
|
||||
}
|
||||
|
@ -293,21 +289,3 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func preloadPivot(pivot *indicator.Pivot, store *bbgo.MarketDataStore) *types.KLine {
|
||||
klines, ok := store.KLinesOfInterval(pivot.Interval)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
last := (*klines)[len(*klines)-1]
|
||||
log.Debugf("updating pivot indicator: %d klines", len(*klines))
|
||||
|
||||
for i := pivot.Window; i < len(*klines); i++ {
|
||||
pivot.CalculateAndUpdate((*klines)[0 : i+1])
|
||||
}
|
||||
|
||||
log.Debugf("found %v previous lows: %v", pivot.IntervalWindow, pivot.Lows)
|
||||
log.Debugf("found %v previous highs: %v", pivot.IntervalWindow, pivot.Highs)
|
||||
return &last
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user