xfunding: callcate funding fee

This commit is contained in:
c9s 2023-03-26 01:54:39 +08:00
parent f127a530b7
commit ba0dd68be0
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 67 additions and 3 deletions

View File

@ -1 +1,32 @@
package xfunding package xfunding
import (
"fmt"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
type FundingFee struct {
Asset string `json:"asset"`
Amount fixedpoint.Value `json:"amount"`
}
type ProfitStats struct {
*types.ProfitStats
FundingFeeCurrency string `json:"fundingFeeCurrency"`
TotalFundingFee fixedpoint.Value `json:"totalFundingFee"`
FundingFeeRecords []FundingFee `json:"fundingFeeRecords"`
}
func (s *ProfitStats) AddFundingFee(fee FundingFee) error {
s.FundingFeeRecords = append(s.FundingFeeRecords, fee)
s.TotalFundingFee = s.TotalFundingFee.Add(fee.Amount)
if s.FundingFeeCurrency == "" {
s.FundingFeeCurrency = fee.Asset
} else if s.FundingFeeCurrency != fee.Asset {
return fmt.Errorf("unexpected error, funding fee currency is not matched, given: %s, wanted: %s", fee.Asset, s.FundingFeeCurrency)
}
return nil
}

View File

@ -119,7 +119,7 @@ type Strategy struct {
FuturesSession string `json:"futuresSession"` FuturesSession string `json:"futuresSession"`
Reset bool `json:"reset"` Reset bool `json:"reset"`
ProfitStats *types.ProfitStats `persistence:"profit_stats"` ProfitStats *ProfitStats `persistence:"profit_stats"`
// SpotPosition is used for the spot position (usually long position) // SpotPosition is used for the spot position (usually long position)
// so that we know how much spot we have bought and the average cost of the spot. // so that we know how much spot we have bought and the average cost of the spot.
@ -260,7 +260,12 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
} }
if s.ProfitStats == nil || s.Reset { if s.ProfitStats == nil || s.Reset {
s.ProfitStats = types.NewProfitStats(s.Market) s.ProfitStats = &ProfitStats{
ProfitStats: types.NewProfitStats(s.Market),
// when receiving funding fee, the funding fee asset is the quote currency of that market.
FundingFeeCurrency: s.futuresMarket.QuoteCurrency,
}
} }
if s.SpotPosition == nil || s.Reset { if s.SpotPosition == nil || s.Reset {
@ -373,7 +378,35 @@ func (s *Strategy) CrossRun(ctx context.Context, orderExecutionRouter bbgo.Order
case binance.AccountUpdateEventReasonWithdraw: case binance.AccountUpdateEventReasonWithdraw:
case binance.AccountUpdateEventReasonFundingFee: case binance.AccountUpdateEventReasonFundingFee:
// EventBase:{
// Event:ACCOUNT_UPDATE
// Time:1679760000932
// }
// Transaction:1679760000927
// AccountUpdate:{
// EventReasonType:FUNDING_FEE
// Balances:[{
// Asset:USDT
// WalletBalance:56.64251742
// CrossWalletBalance:56.64251742
// BalanceChange:-0.00037648
// }]
// }
// }
for _, b := range e.AccountUpdate.Balances {
if b.Asset != s.ProfitStats.FundingFeeCurrency {
continue
}
err := s.ProfitStats.AddFundingFee(FundingFee{
Asset: b.Asset,
Amount: b.BalanceChange,
})
if err != nil {
log.WithError(err).Error("unable to add funding fee to profitStats")
}
}
bbgo.Sync(ctx, s)
} }
}) })
} }
@ -840,6 +873,6 @@ func (s *Strategy) allocateOrderExecutor(ctx context.Context, session *bbgo.Exch
orderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) { orderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) {
bbgo.Sync(ctx, s) bbgo.Sync(ctx, s)
}) })
orderExecutor.BindProfitStats(s.ProfitStats) orderExecutor.BindProfitStats(s.ProfitStats.ProfitStats)
return orderExecutor return orderExecutor
} }