Merge pull request #559 from c9s/feature/binance-margin-api

feature: autoborrow strategy
This commit is contained in:
Yo-An Lin 2022-04-25 13:38:35 +08:00 committed by GitHub
commit a663a891bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 304 additions and 49 deletions

25
config/autoborrow.yaml Normal file
View File

@ -0,0 +1,25 @@
---
exchangeStrategies:
- on: binance
autoborrow:
interval: 30m
autoRepayWhenDeposit: true
# minMarginRatio for triggering auto borrow
# we trigger auto borrow only when the margin ratio is above the number
minMarginRatio: 1.5
# maxMarginRatio for stop auto-repay
# if the margin ratio is high enough, we don't have the urge to repay
maxMarginRatio: 10.0
assets:
- asset: ETH
low: 3.0
maxQuantityPerBorrow: 1.0
maxTotalBorrow: 10.0
- asset: USDT
low: 1000.0
maxQuantityPerBorrow: 100.0
maxTotalBorrow: 10.0
minMarginRatio: 1.3

View File

@ -114,7 +114,7 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
}
message := "Your balances\n"
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
for _, balance := range balances {
if balance.Total().IsZero() {
continue

View File

@ -136,7 +136,7 @@ type BasicRiskController struct {
// 2. Decrease the quantity by risk controls
// 3. If the quantity does not meet minimal requirement, we should ignore the submit order.
func (c *BasicRiskController) ProcessOrders(session *ExchangeSession, orders ...types.SubmitOrder) (outOrders []types.SubmitOrder, errs []error) {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
addError := func(err error) {
errs = append(errs, err)

View File

@ -282,6 +282,13 @@ func NewExchangeSession(name string, exchange types.Exchange) *ExchangeSession {
return session
}
func (session *ExchangeSession) GetAccount() (a *types.Account) {
session.accountMutex.Lock()
a = session.Account
session.accountMutex.Unlock()
return a
}
// UpdateAccount locks the account mutex and update the account object
func (session *ExchangeSession) UpdateAccount(ctx context.Context) error {
account, err := session.Exchange.QueryAccount(ctx)
@ -641,7 +648,7 @@ func (session *ExchangeSession) UpdatePrices(ctx context.Context) (err error) {
return nil
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
var symbols []string
for _, b := range balances {
@ -681,7 +688,7 @@ func (session *ExchangeSession) FindPossibleSymbols() (symbols []string, err err
}, nil
}
var balances = session.Account.Balances()
var balances = session.GetAccount().Balances()
var fiatAssets []string
for _, currency := range types.FiatCurrencies {

View File

@ -161,13 +161,13 @@ func (e *TwapExecution) newBestPriceOrder() (orderForm types.SubmitOrder, err er
switch e.Side {
case types.SideTypeSell:
// check base balance for sell, try to sell as more as possible
if b, ok := e.Session.Account.Balance(e.market.BaseCurrency); ok {
if b, ok := e.Session.GetAccount().Balance(e.market.BaseCurrency); ok {
orderQuantity = fixedpoint.Min(b.Available, orderQuantity)
}
case types.SideTypeBuy:
// check base balance for sell, try to sell as more as possible
if b, ok := e.Session.Account.Balance(e.market.QuoteCurrency); ok {
if b, ok := e.Session.GetAccount().Balance(e.market.QuoteCurrency); ok {
orderQuantity = AdjustQuantityByMaxAmount(orderQuantity, newPrice, b.Available)
}
}

View File

@ -380,7 +380,7 @@ var BacktestCmd = &cobra.Command{
report.Print()
initBalances := userConfig.Backtest.Account[exchangeName].Balances.BalanceMap()
finalBalances := session.Account.Balances()
finalBalances := session.GetAccount().Balances()
log.Infof("INITIAL BALANCES:")
initBalances.Print()

View File

@ -2,6 +2,7 @@ package cmd
// import built-in strategies
import (
_ "github.com/c9s/bbgo/pkg/strategy/autoborrow"
_ "github.com/c9s/bbgo/pkg/strategy/bollgrid"
_ "github.com/c9s/bbgo/pkg/strategy/bollmaker"
_ "github.com/c9s/bbgo/pkg/strategy/emastop"

View File

@ -249,6 +249,7 @@ func (e *Exchange) RepayMarginAsset(ctx context.Context, asset string, amount fi
req.IsolatedSymbol(e.IsolatedMarginSymbol)
}
log.Infof("repaying margin asset %s amount %f", asset, amount.Float64())
resp, err := req.Do(ctx)
log.Debugf("margin repayed %f %s, transaction id = %d", amount.Float64(), asset, resp.TranID)
return err
@ -262,6 +263,7 @@ func (e *Exchange) BorrowMarginAsset(ctx context.Context, asset string, amount f
req.IsolatedSymbol(e.IsolatedMarginSymbol)
}
log.Infof("borrowing margin asset %s amount %f", asset, amount.Float64())
resp, err := req.Do(ctx)
log.Debugf("margin borrowed %f %s, transaction id = %d", amount.Float64(), asset, resp.TranID)
return err

View File

@ -380,7 +380,7 @@ func (s *Server) getSessionAccount(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"account": session.Account})
c.JSON(http.StatusOK, gin.H{"account": session.GetAccount()})
}
func (s *Server) getSessionAccountBalance(c *gin.Context) {
@ -397,7 +397,7 @@ func (s *Server) getSessionAccountBalance(c *gin.Context) {
return
}
c.JSON(http.StatusOK, gin.H{"balances": session.Account.Balances()})
c.JSON(http.StatusOK, gin.H{"balances": session.GetAccount().Balances()})
}
func (s *Server) listSessionOpenOrders(c *gin.Context) {
@ -458,7 +458,7 @@ func (s *Server) listAssets(c *gin.Context) {
totalAssets := types.AssetMap{}
for _, session := range s.Environ.Sessions() {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
if err := session.UpdatePrices(c); err != nil {
logrus.WithError(err).Error("price update failed")

View File

@ -0,0 +1,215 @@
package autoborrow
import (
"context"
"fmt"
"time"
"github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/exchange/binance"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
const ID = "autoborrow"
var log = logrus.WithField("strategy", ID)
func init() {
bbgo.RegisterStrategy(ID, &Strategy{})
}
/**
- on: binance
autoborrow:
interval: 30m
repayWhenDeposit: true
# minMarginRatio for triggering auto borrow
minMarginRatio: 1.5
assets:
- asset: ETH
low: 3.0
maxQuantityPerBorrow: 1.0
maxTotalBorrow: 10.0
- asset: USDT
low: 1000.0
maxQuantityPerBorrow: 100.0
maxTotalBorrow: 10.0
*/
type MarginAsset struct {
Asset string `json:"asset"`
Low fixedpoint.Value `json:"low"`
MaxTotalBorrow fixedpoint.Value `json:"maxTotalBorrow"`
MaxQuantityPerBorrow fixedpoint.Value `json:"maxQuantityPerBorrow"`
MinQuantityPerBorrow fixedpoint.Value `json:"minQuantityPerBorrow"`
}
type Strategy struct {
Interval types.Interval `json:"interval"`
MinMarginRatio fixedpoint.Value `json:"minMarginRatio"`
MaxMarginRatio fixedpoint.Value `json:"maxMarginRatio"`
AutoRepayWhenDeposit bool `json:"autoRepayWhenDeposit"`
Assets []MarginAsset `json:"assets"`
ExchangeSession *bbgo.ExchangeSession
marginBorrowRepay types.MarginBorrowRepay
}
func (s *Strategy) ID() string {
return ID
}
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
// session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: "1m"})
}
func (s *Strategy) checkAndBorrow(ctx context.Context) {
if s.MinMarginRatio.IsZero() {
return
}
if err := s.ExchangeSession.UpdateAccount(ctx) ; err != nil {
log.WithError(err).Errorf("can not update account")
return
}
// if margin ratio is too low, do not borrow
if s.ExchangeSession.GetAccount().MarginRatio.Compare(s.MinMarginRatio) < 0 {
return
}
balances := s.ExchangeSession.GetAccount().Balances()
for _, marginAsset := range s.Assets {
if marginAsset.Low.IsZero() {
log.Warnf("margin asset low balance is not set: %+v", marginAsset)
continue
}
b, ok := balances[marginAsset.Asset]
if ok {
toBorrow := marginAsset.Low.Sub(b.Total())
if toBorrow.Sign() < 0 {
log.Debugf("no need to borrow asset %+v", marginAsset)
continue
}
if !marginAsset.MaxQuantityPerBorrow.IsZero() {
toBorrow = fixedpoint.Min(toBorrow, marginAsset.MaxQuantityPerBorrow)
}
if !marginAsset.MaxTotalBorrow.IsZero() {
// check if we over borrow
if toBorrow.Add(b.Borrowed).Compare(marginAsset.MaxTotalBorrow) > 0 {
toBorrow = toBorrow.Sub( toBorrow.Add(b.Borrowed).Sub(marginAsset.MaxTotalBorrow) )
if toBorrow.Sign() < 0 {
log.Warnf("margin asset %s is over borrowed, skip", marginAsset.Asset)
continue
}
}
toBorrow = fixedpoint.Min(toBorrow.Add(b.Borrowed), marginAsset.MaxTotalBorrow)
}
s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow)
} else {
// available balance is less than marginAsset.Low, we should trigger borrow
toBorrow := marginAsset.Low
if !marginAsset.MaxQuantityPerBorrow.IsZero() {
toBorrow = fixedpoint.Min(toBorrow, marginAsset.MaxQuantityPerBorrow)
}
s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow)
}
}
}
func (s *Strategy) run(ctx context.Context, interval time.Duration) {
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
}
}
}
func (s *Strategy) handleBalanceUpdate(balances types.BalanceMap) {
if s.MinMarginRatio.IsZero() {
return
}
if s.ExchangeSession.GetAccount().MarginRatio.Compare(s.MinMarginRatio) > 0 {
return
}
for _, b := range balances {
if b.Available.IsZero() && b.Borrowed.IsZero() {
continue
}
}
}
func (s *Strategy) handleBinanceBalanceUpdateEvent(event *binance.BalanceUpdateEvent) {
if s.MinMarginRatio.IsZero() {
return
}
if s.ExchangeSession.GetAccount().MarginRatio.Compare(s.MinMarginRatio) > 0 {
return
}
delta := fixedpoint.MustNewFromString(event.Delta)
// ignore outflow
if delta.Sign() < 0 {
return
}
if b, ok := s.ExchangeSession.GetAccount().Balance(event.Asset); ok {
if b.Available.IsZero() || b.Borrowed.IsZero() {
return
}
if err := s.marginBorrowRepay.RepayMarginAsset(context.Background(), event.Asset, b.Available); err != nil {
log.WithError(err).Errorf("margin repay error")
}
}
}
// This strategy simply spent all available quote currency to buy the symbol whenever kline gets closed
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
if s.MinMarginRatio.IsZero() {
log.Warnf("minMarginRatio is 0, you should configure this minimal margin ratio for controlling the liquidation risk")
}
marginBorrowRepay, ok := session.Exchange.(types.MarginBorrowRepay)
if !ok {
return fmt.Errorf("exchange %s does not implement types.MarginBorrowRepay", session.ExchangeName)
}
s.marginBorrowRepay = marginBorrowRepay
if s.AutoRepayWhenDeposit {
binanceStream, ok := session.UserDataStream.(*binance.Stream)
if ok {
binanceStream.OnBalanceUpdateEvent(s.handleBinanceBalanceUpdateEvent)
} else {
session.UserDataStream.OnBalanceUpdate(s.handleBalanceUpdate)
}
}
go s.run(ctx, s.Interval.Duration())
return nil
}

View File

@ -116,7 +116,7 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
}
func (s *Strategy) generateGridBuyOrders(session *bbgo.ExchangeSession) ([]types.SubmitOrder, error) {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
quoteBalance := balances[s.Market.QuoteCurrency].Available
if quoteBalance.Sign() <= 0 {
return nil, fmt.Errorf("quote balance %s is zero: %v", s.Market.QuoteCurrency, quoteBalance)
@ -181,7 +181,7 @@ func (s *Strategy) generateGridBuyOrders(session *bbgo.ExchangeSession) ([]types
}
func (s *Strategy) generateGridSellOrders(session *bbgo.ExchangeSession) ([]types.SubmitOrder, error) {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
baseBalance := balances[s.Market.BaseCurrency].Available
if baseBalance.Sign() <= 0 {
return nil, fmt.Errorf("base balance %s is zero: %+v", s.Market.BaseCurrency, baseBalance)
@ -288,7 +288,7 @@ func (s *Strategy) updateOrders(orderExecutor bbgo.OrderExecutor, session *bbgo.
}
func (s *Strategy) submitReverseOrder(order types.Order, session *bbgo.ExchangeSession) {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
var side = order.Side.Reverse()
var price = order.Price

View File

@ -354,7 +354,7 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec
askPrice := midPrice.Mul(fixedpoint.One.Add(askSpread))
bidPrice := midPrice.Mul(fixedpoint.One.Sub(bidSpread))
base := s.state.Position.GetBase()
balances := s.session.Account.Balances()
balances := s.session.GetAccount().Balances()
log.Infof("mid price:%v spread: %s ask:%v bid: %v position: %s",
midPrice,

View File

@ -138,7 +138,7 @@ func (s *Strategy) place(ctx context.Context, orderExecutor bbgo.OrderExecutor,
quantity := s.Quantity
if s.BalancePercentage.Sign() > 0 {
if balance, ok := session.Account.Balance(market.BaseCurrency); ok {
if balance, ok := session.GetAccount().Balance(market.BaseCurrency); ok {
quantity = balance.Available.Mul(s.BalancePercentage)
}
}

View File

@ -2,10 +2,12 @@ package etf
import (
"context"
"github.com/c9s/bbgo/pkg/fixedpoint"
"time"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"time"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/types"
@ -73,7 +75,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
quantity := askPrice.Div(amount)
// execute orders
quoteBalance, ok := session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
break
}

View File

@ -394,7 +394,7 @@ func (s *Strategy) validateOrder(order *types.SubmitOrder) bool {
return false
}
if order.Side == types.SideTypeSell {
baseBalance, ok := s.Session.Account.Balance(s.Market.BaseCurrency)
baseBalance, ok := s.Session.GetAccount().Balance(s.Market.BaseCurrency)
if !ok {
return false
}
@ -416,7 +416,7 @@ func (s *Strategy) validateOrder(order *types.SubmitOrder) bool {
}
return true
} else if order.Side == types.SideTypeBuy {
quoteBalance, ok := s.Session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := s.Session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
return false
}
@ -492,7 +492,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
log.Errorf("cannot get last price")
return
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
baseBalance := balances[s.Market.BaseCurrency].Available
quoteBalance := balances[s.Market.QuoteCurrency].Available
/*if buyPrice.IsZero() {
@ -580,7 +580,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
buyall = true
}
if sellall {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
baseBalance := balances[s.Market.BaseCurrency].Available.Mul(modifier)
order := types.SubmitOrder{
Symbol: s.Symbol,
@ -602,7 +602,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
}
if buyall {
quoteBalance, ok := session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
return
}
@ -664,7 +664,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} else {
price = kline.Low
}
quoteBalance, ok := session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
return
}
@ -691,7 +691,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} else {
price = kline.High
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
baseBalance := balances[s.Market.BaseCurrency].Available.Mul(modifier)
order := types.SubmitOrder{
Symbol: s.Symbol,

View File

@ -71,7 +71,7 @@ func (s *Strategy) updateOrders(orderExecutor bbgo.OrderExecutor, session *bbgo.
func (s *Strategy) updateBidOrders(orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) {
quoteCurrency := s.Market.QuoteCurrency
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
balance, ok := balances[quoteCurrency]
if !ok || balance.Available.Sign() <= 0 {

View File

@ -4,10 +4,12 @@ import (
"context"
"errors"
"fmt"
"strings"
"github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/exchange/binance"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/sirupsen/logrus"
"strings"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/types"
@ -178,7 +180,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
)
s.Notifiability.Notify(kline)
baseBalance, ok := session.Account.Balance(s.Market.BaseCurrency)
baseBalance, ok := session.GetAccount().Balance(s.Market.BaseCurrency)
if !ok {
return
}

View File

@ -167,7 +167,7 @@ func (s *Strategy) generateGridSellOrders(session *bbgo.ExchangeSession) ([]type
s.UpperPrice)
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
baseBalance, ok := balances[s.Market.BaseCurrency]
if !ok {
return nil, fmt.Errorf("base balance %s not found", s.Market.BaseCurrency)
@ -268,7 +268,7 @@ func (s *Strategy) generateGridBuyOrders(session *bbgo.ExchangeSession) ([]types
s.UpperPrice)
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
balance, ok := balances[s.Market.QuoteCurrency]
if !ok {
return nil, fmt.Errorf("quote balance %s not found", s.Market.QuoteCurrency)

View File

@ -91,7 +91,7 @@ func (s *Strategy) rebalance(ctx context.Context, orderExecutor bbgo.OrderExecut
return
}
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
quantities := s.getQuantities(balances)
marketValues := prices.Mul(quantities)

View File

@ -140,7 +140,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
// execute orders
switch side {
case types.SideTypeBuy:
quoteBalance, ok := session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
log.Errorf("can not place scheduled %s order, quote balance %s is empty", s.Symbol, s.Market.QuoteCurrency)
return
@ -153,7 +153,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
}
case types.SideTypeSell:
baseBalance, ok := session.Account.Balance(s.Market.BaseCurrency)
baseBalance, ok := session.GetAccount().Balance(s.Market.BaseCurrency)
if !ok {
log.Errorf("can not place scheduled %s order, base balance %s is empty", s.Symbol, s.Market.BaseCurrency)
return

View File

@ -41,7 +41,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return nil
}
callback := func(kline types.KLine) {
quoteBalance, ok := session.Account.Balance(market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(market.QuoteCurrency)
if !ok {
return
}

View File

@ -388,7 +388,7 @@ func (s *Strategy) calculateQuantity(session *bbgo.ExchangeSession, side types.S
quantity = fixedpoint.NewFromFloat(q)
}
baseBalance, _ := session.Account.Balance(s.Market.BaseCurrency)
baseBalance, _ := session.GetAccount().Balance(s.Market.BaseCurrency)
if side == types.SideTypeSell {
// quantity = bbgo.AdjustQuantityByMaxAmount(quantity, closePrice, quota)
if s.MinBaseAssetBalance.Sign() > 0 &&
@ -404,7 +404,7 @@ func (s *Strategy) calculateQuantity(session *bbgo.ExchangeSession, side types.S
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, closePrice, quota)
}
quoteBalance, ok := session.Account.Balance(s.Market.QuoteCurrency)
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
if !ok {
return fixedpoint.Zero, fmt.Errorf("quote balance %s not found", s.Market.QuoteCurrency)
}

View File

@ -7,14 +7,15 @@ import (
"sync"
"time"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/slack-go/slack"
"github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/service"
"github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
"github.com/slack-go/slack"
)
const ID = "xbalance"
@ -174,7 +175,7 @@ func (s *Strategy) checkBalance(ctx context.Context, sessions map[string]*bbgo.E
var total fixedpoint.Value
for _, session := range sessions {
if b, ok := session.Account.Balance(s.Asset); ok {
if b, ok := session.GetAccount().Balance(s.Asset); ok {
total = total.Add(b.Total())
}
}
@ -296,7 +297,7 @@ func (s *Strategy) findHighestBalanceLevelSession(sessions map[string]*bbgo.Exch
return nil, balance, fmt.Errorf("session %s does not exist", sessionID)
}
if b, ok := session.Account.Balance(s.Asset); ok {
if b, ok := session.GetAccount().Balance(s.Asset); ok {
if b.Available.Sub(requiredAmount).Compare(s.Low) > 0 && b.Available.Compare(maxBalanceLevel) > 0 {
maxBalanceLevel = b.Available
maxBalanceSession = session
@ -316,7 +317,7 @@ func (s *Strategy) findLowBalanceLevelSession(sessions map[string]*bbgo.Exchange
return nil, balance, fmt.Errorf("session %s does not exist", sessionID)
}
balance, ok = session.Account.Balance(s.Asset)
balance, ok = session.GetAccount().Balance(s.Asset)
if ok {
if balance.Available.Compare(s.Low) <= 0 {
return session, balance, nil

View File

@ -316,7 +316,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
log.Infof("mid price %v", midPrice)
var balances = s.tradingSession.Account.Balances()
var balances = s.tradingSession.GetAccount().Balances()
var quantity = s.tradingMarket.MinQuantity
if s.Quantity.Sign() > 0 {

View File

@ -209,7 +209,7 @@ func (s *Strategy) updateQuote(ctx context.Context, orderExecutionRouter bbgo.Or
// check maker's balance quota
// we load the balances from the account while we're generating the orders,
// the balance may have a chance to be deducted by other strategies or manual orders submitted by the user
makerBalances := s.makerSession.Account.Balances()
makerBalances := s.makerSession.GetAccount().Balances()
makerQuota := &bbgo.QuotaTransaction{}
if b, ok := makerBalances[s.makerMarket.BaseCurrency]; ok {
if b.Available.Compare(s.makerMarket.MinQuantity) > 0 {
@ -227,7 +227,7 @@ func (s *Strategy) updateQuote(ctx context.Context, orderExecutionRouter bbgo.Or
}
}
hedgeBalances := s.sourceSession.Account.Balances()
hedgeBalances := s.sourceSession.GetAccount().Balances()
hedgeQuota := &bbgo.QuotaTransaction{}
if b, ok := hedgeBalances[s.sourceMarket.BaseCurrency]; ok {
// to make bid orders, we need enough base asset in the foreign exchange,
@ -503,7 +503,7 @@ func (s *Strategy) Hedge(ctx context.Context, pos fixedpoint.Value) {
}
// adjust quantity according to the balances
account := s.sourceSession.Account
account := s.sourceSession.GetAccount()
switch side {
case types.SideTypeBuy:

View File

@ -79,7 +79,7 @@ func (s *Strategy) recordNetAssetValue(ctx context.Context, sessions map[string]
totalBalances := types.BalanceMap{}
lastPrices := map[string]fixedpoint.Value{}
for _, session := range sessions {
balances := session.Account.Balances()
balances := session.GetAccount().Balances()
if err := session.UpdatePrices(ctx); err != nil {
log.WithError(err).Error("price update failed")
return

View File

@ -49,12 +49,12 @@ type MarginExchange interface {
UseMargin()
UseIsolatedMargin(symbol string)
GetMarginSettings() MarginSettings
// QueryMarginAccount(ctx context.Context) (*binance.MarginAccount, error)
}
type MarginBorrowRepay interface {
RepayMarginAsset(ctx context.Context, asset string, amount fixedpoint.Value) error
BorrowMarginAsset(ctx context.Context, asset string, amount fixedpoint.Value) error
QueryMarginAssetMaxBorrowable(ctx context.Context, asset string) (amount fixedpoint.Value, err error)
}
type MarginSettings struct {