mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 08:15:15 +00:00
FEATURE: remove Short
This commit is contained in:
parent
e35795943d
commit
57282c30d2
|
@ -15,12 +15,12 @@ type cancelOrdersByGroupIDApi interface {
|
||||||
|
|
||||||
func (s *Strategy) placeOpenPositionOrders(ctx context.Context) error {
|
func (s *Strategy) placeOpenPositionOrders(ctx context.Context) error {
|
||||||
s.logger.Infof("[DCA] start placing open position orders")
|
s.logger.Infof("[DCA] start placing open position orders")
|
||||||
price, err := getBestPriceUntilSuccess(ctx, s.Session.Exchange, s.Symbol, s.Short)
|
price, err := getBestPriceUntilSuccess(ctx, s.Session.Exchange, s.Symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
orders, err := generateOpenPositionOrders(s.Market, s.Short, s.Budget, price, s.PriceDeviation, s.MaxOrderNum, s.OrderGroupID)
|
orders, err := generateOpenPositionOrders(s.Market, s.Budget, price, s.PriceDeviation, s.MaxOrderNum, s.OrderGroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -35,24 +35,17 @@ func (s *Strategy) placeOpenPositionOrders(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getBestPriceUntilSuccess(ctx context.Context, ex types.Exchange, symbol string, short bool) (fixedpoint.Value, error) {
|
func getBestPriceUntilSuccess(ctx context.Context, ex types.Exchange, symbol string) (fixedpoint.Value, error) {
|
||||||
ticker, err := retry.QueryTickerUntilSuccessful(ctx, ex, symbol)
|
ticker, err := retry.QueryTickerUntilSuccessful(ctx, ex, symbol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fixedpoint.Zero, err
|
return fixedpoint.Zero, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if short {
|
|
||||||
return ticker.Buy, nil
|
|
||||||
} else {
|
|
||||||
return ticker.Sell, nil
|
return ticker.Sell, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func generateOpenPositionOrders(market types.Market, short bool, budget, price, priceDeviation fixedpoint.Value, maxOrderNum int64, orderGroupID uint32) ([]types.SubmitOrder, error) {
|
func generateOpenPositionOrders(market types.Market, budget, price, priceDeviation fixedpoint.Value, maxOrderNum int64, orderGroupID uint32) ([]types.SubmitOrder, error) {
|
||||||
factor := fixedpoint.One.Sub(priceDeviation)
|
factor := fixedpoint.One.Sub(priceDeviation)
|
||||||
if short {
|
|
||||||
factor = fixedpoint.One.Add(priceDeviation)
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate all valid prices
|
// calculate all valid prices
|
||||||
var prices []fixedpoint.Value
|
var prices []fixedpoint.Value
|
||||||
|
@ -68,15 +61,12 @@ func generateOpenPositionOrders(market types.Market, short bool, budget, price,
|
||||||
prices = append(prices, price)
|
prices = append(prices, price)
|
||||||
}
|
}
|
||||||
|
|
||||||
notional, orderNum := calculateNotionalAndNum(market, short, budget, prices)
|
notional, orderNum := calculateNotionalAndNum(market, budget, prices)
|
||||||
if orderNum == 0 {
|
if orderNum == 0 {
|
||||||
return nil, fmt.Errorf("failed to calculate notional and num of open position orders, price: %s, budget: %s", price, budget)
|
return nil, fmt.Errorf("failed to calculate notional and num of open position orders, price: %s, budget: %s", price, budget)
|
||||||
}
|
}
|
||||||
|
|
||||||
side := types.SideTypeBuy
|
side := types.SideTypeBuy
|
||||||
if short {
|
|
||||||
side = types.SideTypeSell
|
|
||||||
}
|
|
||||||
|
|
||||||
var submitOrders []types.SubmitOrder
|
var submitOrders []types.SubmitOrder
|
||||||
for i := 0; i < orderNum; i++ {
|
for i := 0; i < orderNum; i++ {
|
||||||
|
@ -99,7 +89,7 @@ func generateOpenPositionOrders(market types.Market, short bool, budget, price,
|
||||||
|
|
||||||
// calculateNotionalAndNum calculates the notional and num of open position orders
|
// calculateNotionalAndNum calculates the notional and num of open position orders
|
||||||
// DCA2 is notional-based, every order has the same notional
|
// DCA2 is notional-based, every order has the same notional
|
||||||
func calculateNotionalAndNum(market types.Market, short bool, budget fixedpoint.Value, prices []fixedpoint.Value) (fixedpoint.Value, int) {
|
func calculateNotionalAndNum(market types.Market, budget fixedpoint.Value, prices []fixedpoint.Value) (fixedpoint.Value, int) {
|
||||||
for num := len(prices); num > 0; num-- {
|
for num := len(prices); num > 0; num-- {
|
||||||
notional := budget.Div(fixedpoint.NewFromInt(int64(num)))
|
notional := budget.Div(fixedpoint.NewFromInt(int64(num)))
|
||||||
if notional.Compare(market.MinNotional) < 0 {
|
if notional.Compare(market.MinNotional) < 0 {
|
||||||
|
@ -107,9 +97,6 @@ func calculateNotionalAndNum(market types.Market, short bool, budget fixedpoint.
|
||||||
}
|
}
|
||||||
|
|
||||||
maxPriceIdx := 0
|
maxPriceIdx := 0
|
||||||
if short {
|
|
||||||
maxPriceIdx = num - 1
|
|
||||||
}
|
|
||||||
quantity := market.TruncateQuantity(notional.Div(prices[maxPriceIdx]))
|
quantity := market.TruncateQuantity(notional.Div(prices[maxPriceIdx]))
|
||||||
if quantity.Compare(market.MinQuantity) < 0 {
|
if quantity.Compare(market.MinQuantity) < 0 {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -36,7 +36,6 @@ func newTestStrategy(va ...string) *Strategy {
|
||||||
logger: logrus.NewEntry(logrus.New()),
|
logger: logrus.NewEntry(logrus.New()),
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Market: market,
|
Market: market,
|
||||||
Short: false,
|
|
||||||
TakeProfitRatio: Number("10%"),
|
TakeProfitRatio: Number("10%"),
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
@ -51,7 +50,7 @@ func TestGenerateOpenPositionOrders(t *testing.T) {
|
||||||
budget := Number("10500")
|
budget := Number("10500")
|
||||||
askPrice := Number("30000")
|
askPrice := Number("30000")
|
||||||
margin := Number("0.05")
|
margin := Number("0.05")
|
||||||
submitOrders, err := generateOpenPositionOrders(strategy.Market, false, budget, askPrice, margin, 4, strategy.OrderGroupID)
|
submitOrders, err := generateOpenPositionOrders(strategy.Market, budget, askPrice, margin, 4, strategy.OrderGroupID)
|
||||||
if !assert.NoError(err) {
|
if !assert.NoError(err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,14 +39,14 @@ func (s *Strategy) recover(ctx context.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRound, err := getCurrentRoundOrders(s.Short, openOrders, closedOrders, s.OrderGroupID)
|
currentRound, err := getCurrentRoundOrders(openOrders, closedOrders, s.OrderGroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
debugRoundOrders(s.logger, "current", currentRound)
|
debugRoundOrders(s.logger, "current", currentRound)
|
||||||
|
|
||||||
// recover state
|
// recover state
|
||||||
state, err := recoverState(ctx, s.Symbol, s.Short, int(s.MaxOrderNum), openOrders, currentRound, s.OrderExecutor.ActiveMakerOrders(), s.OrderExecutor.OrderStore(), s.OrderGroupID)
|
state, err := recoverState(ctx, s.Symbol, int(s.MaxOrderNum), openOrders, currentRound, s.OrderExecutor.ActiveMakerOrders(), s.OrderExecutor.OrderStore(), s.OrderGroupID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ func (s *Strategy) recover(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// recover state
|
// recover state
|
||||||
func recoverState(ctx context.Context, symbol string, short bool, maxOrderNum int, openOrders []types.Order, currentRound Round, activeOrderBook *bbgo.ActiveOrderBook, orderStore *core.OrderStore, groupID uint32) (State, error) {
|
func recoverState(ctx context.Context, symbol string, maxOrderNum int, openOrders []types.Order, currentRound Round, activeOrderBook *bbgo.ActiveOrderBook, orderStore *core.OrderStore, groupID uint32) (State, error) {
|
||||||
if len(currentRound.OpenPositionOrders) == 0 {
|
if len(currentRound.OpenPositionOrders) == 0 {
|
||||||
// new strategy
|
// new strategy
|
||||||
return WaitToOpenPosition, nil
|
return WaitToOpenPosition, nil
|
||||||
|
@ -225,15 +225,10 @@ type Round struct {
|
||||||
TakeProfitOrder types.Order
|
TakeProfitOrder types.Order
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentRoundOrders(short bool, openOrders, closedOrders []types.Order, groupID uint32) (Round, error) {
|
func getCurrentRoundOrders(openOrders, closedOrders []types.Order, groupID uint32) (Round, error) {
|
||||||
openPositionSide := types.SideTypeBuy
|
openPositionSide := types.SideTypeBuy
|
||||||
takeProfitSide := types.SideTypeSell
|
takeProfitSide := types.SideTypeSell
|
||||||
|
|
||||||
if short {
|
|
||||||
openPositionSide = types.SideTypeSell
|
|
||||||
takeProfitSide = types.SideTypeBuy
|
|
||||||
}
|
|
||||||
|
|
||||||
var allOrders []types.Order
|
var allOrders []types.Order
|
||||||
allOrders = append(allOrders, openOrders...)
|
allOrders = append(allOrders, openOrders...)
|
||||||
allOrders = append(allOrders, closedOrders...)
|
allOrders = append(allOrders, closedOrders...)
|
||||||
|
|
|
@ -39,7 +39,7 @@ func Test_GetCurrenctAndLastRoundOrders(t *testing.T) {
|
||||||
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-5*time.Second)),
|
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-5*time.Second)),
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRound, err := getCurrentRoundOrders(false, openOrders, closedOrders, 0)
|
currentRound, err := getCurrentRoundOrders(openOrders, closedOrders, 0)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
|
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
|
||||||
|
@ -72,7 +72,7 @@ func Test_GetCurrenctAndLastRoundOrders(t *testing.T) {
|
||||||
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-17*time.Second)),
|
generateTestOrder(types.SideTypeBuy, types.OrderStatusFilled, now.Add(-17*time.Second)),
|
||||||
}
|
}
|
||||||
|
|
||||||
currentRound, err := getCurrentRoundOrders(false, openOrders, closedOrders, 0)
|
currentRound, err := getCurrentRoundOrders(openOrders, closedOrders, 0)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
|
assert.NotEqual(t, 0, currentRound.TakeProfitOrder.OrderID)
|
||||||
|
@ -101,7 +101,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
currentRound := Round{}
|
currentRound := Round{}
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, WaitToOpenPosition, state)
|
assert.Equal(t, WaitToOpenPosition, state)
|
||||||
})
|
})
|
||||||
|
@ -120,7 +120,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionReady, state)
|
assert.Equal(t, OpenPositionReady, state)
|
||||||
})
|
})
|
||||||
|
@ -144,7 +144,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrderFilled, state)
|
assert.Equal(t, OpenPositionOrderFilled, state)
|
||||||
})
|
})
|
||||||
|
@ -165,7 +165,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
assert.Equal(t, OpenPositionOrdersCancelling, state)
|
||||||
})
|
})
|
||||||
|
@ -184,7 +184,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, OpenPositionOrdersCancelled, state)
|
assert.Equal(t, OpenPositionOrdersCancelled, state)
|
||||||
})
|
})
|
||||||
|
@ -206,7 +206,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, TakeProfitReady, state)
|
assert.Equal(t, TakeProfitReady, state)
|
||||||
})
|
})
|
||||||
|
@ -226,7 +226,7 @@ func Test_RecoverState(t *testing.T) {
|
||||||
}
|
}
|
||||||
orderStore := core.NewOrderStore(symbol)
|
orderStore := core.NewOrderStore(symbol)
|
||||||
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
activeOrderBook := bbgo.NewActiveOrderBook(symbol)
|
||||||
state, err := recoverState(context.Background(), symbol, false, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
state, err := recoverState(context.Background(), symbol, 5, openOrders, currentRound, activeOrderBook, orderStore, 0)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, WaitToOpenPosition, state)
|
assert.Equal(t, WaitToOpenPosition, state)
|
||||||
})
|
})
|
||||||
|
|
|
@ -178,12 +178,11 @@ func (s *Strategy) runOpenPositionOrdersCancelled(ctx context.Context, next Stat
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) runTakeProfitReady(_ context.Context, next State) {
|
func (s *Strategy) runTakeProfitReady(_ context.Context, next State) {
|
||||||
|
// wait 3 seconds to avoid position not update
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
s.logger.Info("[State] TakeProfitReady - start reseting position and calculate budget for next round")
|
s.logger.Info("[State] TakeProfitReady - start reseting position and calculate budget for next round")
|
||||||
if s.Short {
|
|
||||||
s.Budget = s.Budget.Add(s.Position.Base)
|
|
||||||
} else {
|
|
||||||
s.Budget = s.Budget.Add(s.Position.Quote)
|
s.Budget = s.Budget.Add(s.Position.Quote)
|
||||||
}
|
|
||||||
|
|
||||||
// reset position
|
// reset position
|
||||||
s.Position.Reset()
|
s.Position.Reset()
|
||||||
|
|
|
@ -34,7 +34,6 @@ type Strategy struct {
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
|
|
||||||
// setting
|
// setting
|
||||||
Short bool `json:"short"`
|
|
||||||
Budget fixedpoint.Value `json:"budget"`
|
Budget fixedpoint.Value `json:"budget"`
|
||||||
MaxOrderNum int64 `json:"maxOrderNum"`
|
MaxOrderNum int64 `json:"maxOrderNum"`
|
||||||
PriceDeviation fixedpoint.Value `json:"priceDeviation"`
|
PriceDeviation fixedpoint.Value `json:"priceDeviation"`
|
||||||
|
@ -122,10 +121,6 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
||||||
s.logger.Infof("[DCA] FILLED ORDER: %s", o.String())
|
s.logger.Infof("[DCA] FILLED ORDER: %s", o.String())
|
||||||
openPositionSide := types.SideTypeBuy
|
openPositionSide := types.SideTypeBuy
|
||||||
takeProfitSide := types.SideTypeSell
|
takeProfitSide := types.SideTypeSell
|
||||||
if s.Short {
|
|
||||||
openPositionSide = types.SideTypeSell
|
|
||||||
takeProfitSide = types.SideTypeBuy
|
|
||||||
}
|
|
||||||
|
|
||||||
switch o.Side {
|
switch o.Side {
|
||||||
case openPositionSide:
|
case openPositionSide:
|
||||||
|
@ -145,7 +140,7 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
||||||
|
|
||||||
compRes := kline.Close.Compare(s.takeProfitPrice)
|
compRes := kline.Close.Compare(s.takeProfitPrice)
|
||||||
// price doesn't hit the take profit price
|
// price doesn't hit the take profit price
|
||||||
if (s.Short && compRes > 0) || (!s.Short && compRes < 0) {
|
if compRes < 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,9 +188,6 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
||||||
|
|
||||||
func (s *Strategy) updateTakeProfitPrice() {
|
func (s *Strategy) updateTakeProfitPrice() {
|
||||||
takeProfitRatio := s.TakeProfitRatio
|
takeProfitRatio := s.TakeProfitRatio
|
||||||
if s.Short {
|
|
||||||
takeProfitRatio = takeProfitRatio.Neg()
|
|
||||||
}
|
|
||||||
s.takeProfitPrice = s.Market.TruncatePrice(s.Position.AverageCost.Mul(fixedpoint.One.Add(takeProfitRatio)))
|
s.takeProfitPrice = s.Market.TruncatePrice(s.Position.AverageCost.Mul(fixedpoint.One.Add(takeProfitRatio)))
|
||||||
s.logger.Infof("[DCA] cost: %s, ratio: %s, price: %s", s.Position.AverageCost, takeProfitRatio, s.takeProfitPrice)
|
s.logger.Infof("[DCA] cost: %s, ratio: %s, price: %s", s.Position.AverageCost, takeProfitRatio, s.takeProfitPrice)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
|
|
||||||
func (s *Strategy) placeTakeProfitOrders(ctx context.Context) error {
|
func (s *Strategy) placeTakeProfitOrders(ctx context.Context) error {
|
||||||
s.logger.Info("[DCA] start placing take profit orders")
|
s.logger.Info("[DCA] start placing take profit orders")
|
||||||
order := generateTakeProfitOrder(s.Market, s.Short, s.TakeProfitRatio, s.Position, s.OrderGroupID)
|
order := generateTakeProfitOrder(s.Market, s.TakeProfitRatio, s.Position, s.OrderGroupID)
|
||||||
createdOrders, err := s.OrderExecutor.SubmitOrders(ctx, order)
|
createdOrders, err := s.OrderExecutor.SubmitOrders(ctx, order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -22,12 +22,8 @@ func (s *Strategy) placeTakeProfitOrders(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateTakeProfitOrder(market types.Market, short bool, takeProfitRatio fixedpoint.Value, position *types.Position, orderGroupID uint32) types.SubmitOrder {
|
func generateTakeProfitOrder(market types.Market, takeProfitRatio fixedpoint.Value, position *types.Position, orderGroupID uint32) types.SubmitOrder {
|
||||||
side := types.SideTypeSell
|
side := types.SideTypeSell
|
||||||
if short {
|
|
||||||
takeProfitRatio = takeProfitRatio.Neg()
|
|
||||||
side = types.SideTypeBuy
|
|
||||||
}
|
|
||||||
takeProfitPrice := market.TruncatePrice(position.AverageCost.Mul(fixedpoint.One.Add(takeProfitRatio)))
|
takeProfitPrice := market.TruncatePrice(position.AverageCost.Mul(fixedpoint.One.Add(takeProfitRatio)))
|
||||||
return types.SubmitOrder{
|
return types.SubmitOrder{
|
||||||
Symbol: market.Symbol,
|
Symbol: market.Symbol,
|
||||||
|
|
|
@ -24,7 +24,7 @@ func TestGenerateTakeProfitOrder(t *testing.T) {
|
||||||
FeeCurrency: strategy.Market.BaseCurrency,
|
FeeCurrency: strategy.Market.BaseCurrency,
|
||||||
})
|
})
|
||||||
|
|
||||||
o := generateTakeProfitOrder(strategy.Market, false, strategy.TakeProfitRatio, position, strategy.OrderGroupID)
|
o := generateTakeProfitOrder(strategy.Market, strategy.TakeProfitRatio, position, strategy.OrderGroupID)
|
||||||
assert.Equal(Number("31397.09"), o.Price)
|
assert.Equal(Number("31397.09"), o.Price)
|
||||||
assert.Equal(Number("0.9985"), o.Quantity)
|
assert.Equal(Number("0.9985"), o.Quantity)
|
||||||
assert.Equal(types.SideTypeSell, o.Side)
|
assert.Equal(types.SideTypeSell, o.Side)
|
||||||
|
@ -38,7 +38,7 @@ func TestGenerateTakeProfitOrder(t *testing.T) {
|
||||||
Fee: Number("0.00075"),
|
Fee: Number("0.00075"),
|
||||||
FeeCurrency: strategy.Market.BaseCurrency,
|
FeeCurrency: strategy.Market.BaseCurrency,
|
||||||
})
|
})
|
||||||
o = generateTakeProfitOrder(strategy.Market, false, strategy.TakeProfitRatio, position, strategy.OrderGroupID)
|
o = generateTakeProfitOrder(strategy.Market, strategy.TakeProfitRatio, position, strategy.OrderGroupID)
|
||||||
assert.Equal(Number("30846.26"), o.Price)
|
assert.Equal(Number("30846.26"), o.Price)
|
||||||
assert.Equal(Number("1.49775"), o.Quantity)
|
assert.Equal(Number("1.49775"), o.Quantity)
|
||||||
assert.Equal(types.SideTypeSell, o.Side)
|
assert.Equal(types.SideTypeSell, o.Side)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user