Skip to content

Commit

Permalink
xfunding: reset stats when direction changed
Browse files Browse the repository at this point in the history
  • Loading branch information
c9s committed Mar 23, 2023
1 parent 7ba7eb8 commit b5f69e7
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 50 deletions.
58 changes: 8 additions & 50 deletions pkg/strategy/xfunding/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -347,56 +347,6 @@ func (s *Strategy) queryAndDetectPremiumIndex(ctx context.Context, binanceFuture
}
}

// TODO: replace type binance.Exchange with an interface
func (s *Strategy) transferIn(ctx context.Context, ex *binance.Exchange, trade types.Trade) error {
currency := s.spotMarket.BaseCurrency

// base asset needs BUY trades
if trade.Side == types.SideTypeSell {
return nil
}

balances, err := ex.QueryAccountBalances(ctx)
if err != nil {
return err
}

b, ok := balances[currency]
if !ok {
return fmt.Errorf("%s balance not found", currency)
}

// TODO: according to the fee, we might not be able to get enough balance greater than the trade quantity, we can adjust the quantity here
if b.Available.Compare(trade.Quantity) < 0 {
log.Infof("adding to pending base transfer: %s %s", trade.Quantity, currency)
s.State.PendingBaseTransfer = s.State.PendingBaseTransfer.Add(trade.Quantity)
return nil
}

amount := s.State.PendingBaseTransfer.Add(trade.Quantity)

pos := s.SpotPosition.GetBase()
rest := pos.Sub(s.State.TotalBaseTransfer)

if rest.Sign() < 0 {
return nil
}

amount = fixedpoint.Min(rest, amount)

log.Infof("transfering futures account asset %s %s", amount, currency)
if err := ex.TransferFuturesAccountAsset(ctx, currency, amount, types.TransferIn); err != nil {
return err
}

// reset pending transfer
s.State.PendingBaseTransfer = fixedpoint.Zero

// record the transfer in the total base transfer
s.State.TotalBaseTransfer = s.State.TotalBaseTransfer.Add(amount)
return nil
}

func (s *Strategy) triggerPositionAction(ctx context.Context) {
switch s.positionAction {
case PositionOpening:
Expand Down Expand Up @@ -622,9 +572,17 @@ func (s *Strategy) detectPremiumIndex(premiumIndex *types.PremiumIndex) (changed

s.positionAction = PositionOpening
s.positionType = types.PositionShort

// reset the transfer stats
s.State.PendingBaseTransfer = fixedpoint.Zero
s.State.TotalBaseTransfer = fixedpoint.Zero
changed = true
} else if fundingRate.Compare(s.ShortFundingRate.Low) <= 0 {
s.positionAction = PositionClosing

// reset the transfer stats
s.State.PendingBaseTransfer = fixedpoint.Zero
s.State.TotalBaseTransfer = fixedpoint.Zero
changed = true
}
}
Expand Down
112 changes: 112 additions & 0 deletions pkg/strategy/xfunding/transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package xfunding

import (
"context"
"fmt"

"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)

type FuturesTransfer interface {
TransferFuturesAccountAsset(ctx context.Context, asset string, amount fixedpoint.Value, io types.TransferDirection) error
QueryAccountBalances(ctx context.Context) (types.BalanceMap, error)
}

func (s *Strategy) transferOut(ctx context.Context, ex FuturesTransfer, trade types.Trade) error {
currency := s.spotMarket.BaseCurrency

// base asset needs BUY trades
if trade.Side == types.SideTypeBuy {
return nil
}

balances, err := ex.QueryAccountBalances(ctx)
if err != nil {
return err
}

b, ok := balances[currency]
if !ok {
return fmt.Errorf("%s balance not found", currency)
}

// TODO: according to the fee, we might not be able to get enough balance greater than the trade quantity, we can adjust the quantity here
if b.Available.Compare(trade.Quantity) < 0 {
log.Infof("adding to pending base transfer: %s %s", trade.Quantity, currency)
s.State.PendingBaseTransfer = s.State.PendingBaseTransfer.Add(trade.Quantity)
return nil
}

amount := s.State.PendingBaseTransfer.Add(trade.Quantity)

pos := s.SpotPosition.GetBase()
rest := pos.Sub(s.State.TotalBaseTransfer)

if rest.Sign() < 0 {
return nil
}

amount = fixedpoint.Min(rest, amount)

log.Infof("transfering out futures account asset %s %s", amount, currency)
if err := ex.TransferFuturesAccountAsset(ctx, currency, amount, types.TransferOut); err != nil {
return err
}

// reset pending transfer
s.State.PendingBaseTransfer = fixedpoint.Zero

// record the transfer in the total base transfer
s.State.TotalBaseTransfer = s.State.TotalBaseTransfer.Add(amount)
return nil
}

func (s *Strategy) transferIn(ctx context.Context, ex FuturesTransfer, trade types.Trade) error {
currency := s.spotMarket.BaseCurrency

// base asset needs BUY trades
if trade.Side == types.SideTypeSell {
return nil
}

balances, err := ex.QueryAccountBalances(ctx)
if err != nil {
return err
}

b, ok := balances[currency]
if !ok {
return fmt.Errorf("%s balance not found", currency)
}

// TODO: according to the fee, we might not be able to get enough balance greater than the trade quantity, we can adjust the quantity here
if b.Available.Compare(trade.Quantity) < 0 {
log.Infof("adding to pending base transfer: %s %s", trade.Quantity, currency)
s.State.PendingBaseTransfer = s.State.PendingBaseTransfer.Add(trade.Quantity)
return nil
}

amount := s.State.PendingBaseTransfer.Add(trade.Quantity)

pos := s.SpotPosition.GetBase()
rest := pos.Sub(s.State.TotalBaseTransfer)

if rest.Sign() < 0 {
return nil
}

amount = fixedpoint.Min(rest, amount)

log.Infof("transfering in futures account asset %s %s", amount, currency)
if err := ex.TransferFuturesAccountAsset(ctx, currency, amount, types.TransferIn); err != nil {
return err
}

// reset pending transfer
s.State.PendingBaseTransfer = fixedpoint.Zero

// record the transfer in the total base transfer
s.State.TotalBaseTransfer = s.State.TotalBaseTransfer.Add(amount)
return nil
}

0 comments on commit b5f69e7

Please sign in to comment.