Merge pull request #1185 from c9s/c9s/fix-autoborrow

FIX: [autoborrow] add max borrowable check and add more notifications
This commit is contained in:
Yo-An Lin 2023-06-01 21:24:34 +08:00 committed by GitHub
commit c0bb953019
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 142 additions and 94 deletions

View File

@ -7,6 +7,7 @@ import (
"time"
"github.com/adshao/go-binance/v2/futures"
"github.com/slack-go/slack"
"github.com/adshao/go-binance/v2"
"github.com/valyala/fastjson"
@ -21,43 +22,42 @@ type EventBase struct {
}
/*
executionReport
{
"e": "executionReport", // Event type
"E": 1499405658658, // Event time
"s": "ETHBTC", // Symbol
"c": "mUvoqJxFIILMdfAW5iGSOW", // Client order ID
"S": "BUY", // Side
"o": "LIMIT", // Order type
"f": "GTC", // Time in force
"q": "1.00000000", // Order quantity
"p": "0.10264410", // Order price
"P": "0.00000000", // Stop price
"F": "0.00000000", // Iceberg quantity
"g": -1, // OrderListId
"C": null, // Original client order ID; This is the ID of the order being canceled
"x": "NEW", // Current execution type
"X": "NEW", // Current order status
"r": "NONE", // Order reject reason; will be an error code.
"i": 4293153, // Order ID
"l": "0.00000000", // Last executed quantity
"z": "0.00000000", // Cumulative filled quantity
"L": "0.00000000", // Last executed price
"n": "0", // Commission amount
"N": null, // Commission asset
"T": 1499405658657, // Transaction time
"t": -1, // Trade ID
"I": 8641984, // Ignore
"w": true, // Is the order on the book?
"m": false, // Is this trade the maker side?
"M": false, // Ignore
"O": 1499405658657, // Order creation time
"Z": "0.00000000", // Cumulative quote asset transacted quantity
"Y": "0.00000000", // Last quote asset transacted quantity (i.e. lastPrice * lastQty)
"Q": "0.00000000" // Quote Order Quantity
}
{
"e": "executionReport", // Event type
"E": 1499405658658, // Event time
"s": "ETHBTC", // Symbol
"c": "mUvoqJxFIILMdfAW5iGSOW", // Client order ID
"S": "BUY", // Side
"o": "LIMIT", // Order type
"f": "GTC", // Time in force
"q": "1.00000000", // Order quantity
"p": "0.10264410", // Order price
"P": "0.00000000", // Stop price
"F": "0.00000000", // Iceberg quantity
"g": -1, // OrderListId
"C": null, // Original client order ID; This is the ID of the order being canceled
"x": "NEW", // Current execution type
"X": "NEW", // Current order status
"r": "NONE", // Order reject reason; will be an error code.
"i": 4293153, // Order ID
"l": "0.00000000", // Last executed quantity
"z": "0.00000000", // Cumulative filled quantity
"L": "0.00000000", // Last executed price
"n": "0", // Commission amount
"N": null, // Commission asset
"T": 1499405658657, // Transaction time
"t": -1, // Trade ID
"I": 8641984, // Ignore
"w": true, // Is the order on the book?
"m": false, // Is this trade the maker side?
"M": false, // Ignore
"O": 1499405658657, // Order creation time
"Z": "0.00000000", // Cumulative quote asset transacted quantity
"Y": "0.00000000", // Last quote asset transacted quantity (i.e. lastPrice * lastQty)
"Q": "0.00000000" // Quote Order Quantity
}
*/
type ExecutionReportEvent struct {
EventBase
@ -165,71 +165,100 @@ func (e *ExecutionReportEvent) Trade() (*types.Trade, error) {
}
/*
balanceUpdate
event: balanceUpdate
{
"e": "balanceUpdate", //KLineEvent Type
"E": 1573200697110, //KLineEvent Time
"a": "BTC", //Asset
"d": "100.00000000", //Balance Delta
"T": 1573200697068 //Clear Time
}
Balance Update occurs during the following:
Deposits or withdrawals from the account
Transfer of funds between accounts (e.g. Spot to Margin)
{
"e": "balanceUpdate", //KLineEvent Type
"E": 1573200697110, //KLineEvent Time
"a": "BTC", //Asset
"d": "100.00000000", //Balance Delta
"T": 1573200697068 //Clear Time
}
This event is only for Spot
*/
type BalanceUpdateEvent struct {
EventBase
Asset string `json:"a"`
Delta string `json:"d"`
ClearTime int64 `json:"T"`
Asset string `json:"a"`
Delta fixedpoint.Value `json:"d"`
ClearTime types.MillisecondTimestamp `json:"T"`
}
func (e *BalanceUpdateEvent) SlackAttachment() slack.Attachment {
return slack.Attachment{
Title: "Binance Balance Update Event",
Color: "warning",
Fields: []slack.AttachmentField{
{
Title: "Asset",
Value: e.Asset,
Short: true,
},
{
Title: "Delta",
Value: e.Delta.String(),
Short: true,
},
{
Title: "Time",
Value: e.ClearTime.String(),
Short: true,
},
},
}
}
/*
outboundAccountInfo
{
"e": "outboundAccountInfo", // KLineEvent type
"E": 1499405658849, // KLineEvent time
"m": 0, // Maker commission rate (bips)
"t": 0, // Taker commission rate (bips)
"b": 0, // Buyer commission rate (bips)
"s": 0, // Seller commission rate (bips)
"T": true, // Can trade?
"W": true, // Can withdraw?
"D": true, // Can deposit?
"u": 1499405658848, // Time of last account update
"B": [ // AccountBalances array
{
"a": "LTC", // Asset
"f": "17366.18538083", // Free amount
"l": "0.00000000" // Locked amount
},
{
"a": "BTC",
"f": "10537.85314051",
"l": "2.19464093"
},
{
"a": "ETH",
"f": "17902.35190619",
"l": "0.00000000"
},
{
"a": "BNC",
"f": "1114503.29769312",
"l": "0.00000000"
},
{
"a": "NEO",
"f": "0.00000000",
"l": "0.00000000"
}
],
"P": [ // Account Permissions
"SPOT"
]
}
{
"e": "outboundAccountInfo", // KLineEvent type
"E": 1499405658849, // KLineEvent time
"m": 0, // Maker commission rate (bips)
"t": 0, // Taker commission rate (bips)
"b": 0, // Buyer commission rate (bips)
"s": 0, // Seller commission rate (bips)
"T": true, // Can trade?
"W": true, // Can withdraw?
"D": true, // Can deposit?
"u": 1499405658848, // Time of last account update
"B": [ // AccountBalances array
{
"a": "LTC", // Asset
"f": "17366.18538083", // Free amount
"l": "0.00000000" // Locked amount
},
{
"a": "BTC",
"f": "10537.85314051",
"l": "2.19464093"
},
{
"a": "ETH",
"f": "17902.35190619",
"l": "0.00000000"
},
{
"a": "BNC",
"f": "1114503.29769312",
"l": "0.00000000"
},
{
"a": "NEO",
"f": "0.00000000",
"l": "0.00000000"
}
],
"P": [ // Account Permissions
"SPOT"
]
}
*/
type Balance struct {
Asset string `json:"a"`

View File

@ -247,9 +247,9 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
if !marginAsset.MaxTotalBorrow.IsZero() {
// check if we over borrow
newBorrow := toBorrow.Add(b.Borrowed)
if newBorrow.Compare(marginAsset.MaxTotalBorrow) > 0 {
toBorrow = toBorrow.Sub(newBorrow.Sub(marginAsset.MaxTotalBorrow))
newTotalBorrow := toBorrow.Add(b.Borrowed)
if newTotalBorrow.Compare(marginAsset.MaxTotalBorrow) > 0 {
toBorrow = toBorrow.Sub(newTotalBorrow.Sub(marginAsset.MaxTotalBorrow))
if toBorrow.Sign() < 0 {
log.Warnf("margin asset %s is over borrowed, skip", marginAsset.Asset)
continue
@ -257,6 +257,22 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
}
}
maxBorrowable, err2 := s.marginBorrowRepay.QueryMarginAssetMaxBorrowable(ctx, marginAsset.Asset)
if err2 != nil {
log.WithError(err).Errorf("max borrowable query error")
continue
}
if toBorrow.Compare(maxBorrowable) > 0 {
bbgo.Notify("Trying to borrow %f %s, which is greater than the max borrowable amount %f, will adjust borrow amount to %f",
toBorrow.Float64(),
marginAsset.Asset,
maxBorrowable.Float64(),
maxBorrowable.Float64())
toBorrow = fixedpoint.Min(maxBorrowable, toBorrow)
}
if toBorrow.IsZero() {
continue
}
@ -350,16 +366,19 @@ func (s *Strategy) handleBalanceUpdate(balances types.BalanceMap) {
}
func (s *Strategy) handleBinanceBalanceUpdateEvent(event *binance.BalanceUpdateEvent) {
bbgo.Notify(event)
if s.MinMarginLevel.IsZero() {
return
}
account := s.ExchangeSession.GetAccount()
if account.MarginLevel.Compare(s.MinMarginLevel) > 0 {
bbgo.Notify("account margin level %f is greater than minimal margin level %f, skip", account.MarginLevel.Float64(), s.MinMarginLevel.Float64())
return
}
delta := fixedpoint.MustNewFromString(event.Delta)
delta := event.Delta
// ignore outflow
if delta.Sign() < 0 {