2023-12-07 06:38:13 +00:00
|
|
|
package dca2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-04-15 08:25:34 +00:00
|
|
|
"fmt"
|
2023-12-07 06:38:13 +00:00
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
"github.com/c9s/bbgo/pkg/types"
|
2024-04-15 08:25:34 +00:00
|
|
|
"github.com/pkg/errors"
|
2023-12-07 06:38:13 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func (s *Strategy) placeTakeProfitOrders(ctx context.Context) error {
|
2024-03-12 06:29:36 +00:00
|
|
|
s.logger.Info("start placing take profit orders")
|
2024-04-16 05:37:53 +00:00
|
|
|
currentRound, err := s.collector.CollectCurrentRound(ctx)
|
2024-04-22 05:46:28 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to place the take-profit order when collecting current round")
|
|
|
|
}
|
|
|
|
|
2024-04-15 08:25:34 +00:00
|
|
|
if currentRound.TakeProfitOrder.OrderID != 0 {
|
|
|
|
return fmt.Errorf("there is a take-profit order before placing the take-profit order, please check it")
|
|
|
|
}
|
|
|
|
|
2024-04-16 05:37:53 +00:00
|
|
|
trades, err := s.collector.CollectRoundTrades(ctx, currentRound)
|
2024-04-15 08:25:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "failed to place the take-profit order when collecting round trades")
|
|
|
|
}
|
|
|
|
|
2024-04-15 09:27:56 +00:00
|
|
|
roundPosition := types.NewPositionFromMarket(s.Market)
|
2024-04-15 08:25:34 +00:00
|
|
|
|
|
|
|
for _, trade := range trades {
|
2024-04-16 08:52:50 +00:00
|
|
|
s.logger.Infof("add trade into the position of this round %s", trade.String())
|
2024-04-15 08:25:34 +00:00
|
|
|
if trade.FeeProcessing {
|
|
|
|
return fmt.Errorf("failed to place the take-profit order because there is a trade's fee not ready")
|
|
|
|
}
|
|
|
|
|
2024-04-15 09:27:56 +00:00
|
|
|
roundPosition.AddTrade(trade)
|
2024-04-15 08:25:34 +00:00
|
|
|
}
|
|
|
|
|
2024-04-15 09:27:56 +00:00
|
|
|
s.logger.Infof("position of this round before place the take-profit order: %s", roundPosition.String())
|
2024-04-15 08:25:34 +00:00
|
|
|
|
2024-04-15 09:27:56 +00:00
|
|
|
order := generateTakeProfitOrder(s.Market, s.TakeProfitRatio, roundPosition, s.OrderGroupID)
|
2023-12-07 06:38:13 +00:00
|
|
|
createdOrders, err := s.OrderExecutor.SubmitOrders(ctx, order)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, createdOrder := range createdOrders {
|
|
|
|
s.logger.Info("SUBMIT TAKE PROFIT ORDER ", createdOrder.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-12-22 07:50:48 +00:00
|
|
|
func generateTakeProfitOrder(market types.Market, takeProfitRatio fixedpoint.Value, position *types.Position, orderGroupID uint32) types.SubmitOrder {
|
2023-12-07 06:38:13 +00:00
|
|
|
side := types.SideTypeSell
|
|
|
|
takeProfitPrice := market.TruncatePrice(position.AverageCost.Mul(fixedpoint.One.Add(takeProfitRatio)))
|
|
|
|
return types.SubmitOrder{
|
|
|
|
Symbol: market.Symbol,
|
|
|
|
Market: market,
|
|
|
|
Type: types.OrderTypeLimit,
|
|
|
|
Price: takeProfitPrice,
|
|
|
|
Side: side,
|
|
|
|
TimeInForce: types.TimeInForceGTC,
|
|
|
|
Quantity: position.GetBase().Abs(),
|
|
|
|
Tag: orderTag,
|
|
|
|
GroupID: orderGroupID,
|
|
|
|
}
|
|
|
|
}
|