Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: [dca2] store price quantity pairs of the open-position order… #1638

Merged
merged 3 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/strategy/dca2/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ import (
"github.com/sirupsen/logrus"
)

type Round struct {
OpenPositionOrders []types.Order
TakeProfitOrder types.Order
}

type Collector struct {
logger *logrus.Entry
symbol string
Expand Down
11 changes: 11 additions & 0 deletions pkg/strategy/dca2/open_position.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/exchange/retry"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
Expand Down Expand Up @@ -32,6 +33,16 @@ func (s *Strategy) placeOpenPositionOrders(ctx context.Context) error {

s.debugOrders(createdOrders)

// store price quantity pairs into persistence
var pvs []types.PriceVolume
for _, createdOrder := range createdOrders {
pvs = append(pvs, types.PriceVolume{Price: createdOrder.Price, Volume: createdOrder.Quantity})
}

s.ProfitStats.OpenPositionPVs = pvs

bbgo.Sync(ctx, s)

return nil
}

Expand Down
3 changes: 3 additions & 0 deletions pkg/strategy/dca2/profit_stats.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ type ProfitStats struct {
TotalProfit fixedpoint.Value `json:"totalProfit,omitempty"`
TotalFee map[string]fixedpoint.Value `json:"totalFee,omitempty"`

// used to flexible recovery
OpenPositionPVs []types.PriceVolume `json:"openPositionPVs,omitempty"`

types.PersistenceTTL
}

Expand Down
44 changes: 0 additions & 44 deletions pkg/strategy/dca2/recover.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,47 +194,3 @@ func recoverStartTimeOfNextRound(ctx context.Context, currentRound Round, coolDo

return time.Time{}
}

type Round struct {
OpenPositionOrders []types.Order
TakeProfitOrder types.Order
}

func getCurrentRoundOrders(openOrders, closedOrders []types.Order, groupID uint32) (Round, error) {
openPositionSide := types.SideTypeBuy
takeProfitSide := types.SideTypeSell

var allOrders []types.Order
allOrders = append(allOrders, openOrders...)
allOrders = append(allOrders, closedOrders...)

types.SortOrdersDescending(allOrders)

var currentRound Round
lastSide := takeProfitSide
for _, order := range allOrders {
// group id filter is used for debug when local running
if order.GroupID != groupID {
continue
}

if order.Side == takeProfitSide && lastSide == openPositionSide {
break
}

switch order.Side {
case openPositionSide:
currentRound.OpenPositionOrders = append(currentRound.OpenPositionOrders, order)
case takeProfitSide:
if currentRound.TakeProfitOrder.OrderID != 0 {
return currentRound, fmt.Errorf("there are two take-profit orders in one round, please check it")
}
currentRound.TakeProfitOrder = order
default:
}

lastSide = order.Side
}

return currentRound, nil
}
56 changes: 0 additions & 56 deletions pkg/strategy/dca2/recover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,62 +23,6 @@ func generateTestOrder(side types.SideType, status types.OrderStatus, createdAt

}

func Test_GetCurrenctRoundOrders(t *testing.T) {
t.Run("case 1", func(t *testing.T) {
now := time.Now()
openOrders := []types.Order{
generateTestOrder(types.SideTypeSell, types.OrderStatusNew, now),
}

closedOrders := []types.Order{
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-1*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-2*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-3*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-4*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-5*time.Second)),
}

currentRound, err := getCurrentRoundOrders(openOrders, closedOrders, 0)

assert.NoError(t, err)
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
assert.Equal(t, 5, len(currentRound.OpenPositionOrders))
})

t.Run("case 2", func(t *testing.T) {
now := time.Now()
openOrders := []types.Order{
generateTestOrder(types.SideTypeSell, types.OrderStatusNew, now),
}

closedOrders := []types.Order{
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-1*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-2*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-3*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-4*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-5*time.Second)),
generateTestOrder(types.SideTypeSell, types.OrderStatusFilled, now.Add(-6*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-7*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-8*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-9*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-10*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-11*time.Second)),
generateTestOrder(types.SideTypeSell, types.OrderStatusFilled, now.Add(-12*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-13*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-14*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-15*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-16*time.Second)),
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-17*time.Second)),
}

currentRound, err := getCurrentRoundOrders(openOrders, closedOrders, 0)

assert.NoError(t, err)
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
assert.Equal(t, 5, len(currentRound.OpenPositionOrders))
})
}

type MockQueryOrders struct {
OpenOrders []types.Order
ClosedOrders []types.Order
Expand Down
Loading