Merge pull request #1638 from c9s/kbearXD/dca2/store-open-position-pqs

FEATURE: [dca2] store price quantity pairs of the open-position order…
This commit is contained in:
kbearXD 2024-05-22 11:34:39 +08:00 committed by GitHub
commit 5f1ece2a4b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 19 additions and 100 deletions

View File

@ -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

View File

@ -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"
@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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