From dbd54575e6c27a220d2a38c43f7b02ad2eaa6f96 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:32:50 +0800 Subject: [PATCH 1/4] xfunding: improve funding fee guard --- pkg/strategy/xfunding/profitstats.go | 22 ++++++++++++++++------ pkg/strategy/xfunding/strategy.go | 6 +----- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pkg/strategy/xfunding/profitstats.go b/pkg/strategy/xfunding/profitstats.go index 6ae2780b5..0a7700cf2 100644 --- a/pkg/strategy/xfunding/profitstats.go +++ b/pkg/strategy/xfunding/profitstats.go @@ -17,8 +17,13 @@ type ProfitStats struct { FundingFeeCurrency string `json:"fundingFeeCurrency"` TotalFundingFee fixedpoint.Value `json:"totalFundingFee"` FundingFeeRecords []FundingFee `json:"fundingFeeRecords"` - LastFundingFeeTxn int64 `json:"lastFundingFeeTxn"` - LastFundingFeeTime time.Time `json:"lastFundingFeeTime"` + + // Fees map[string] + Last *FundingFee `json:"last"` + + LastFundingFeeTime time.Time `json:"lastFundingFeeTime"` + + txns map[int64]struct{} } func (s *ProfitStats) SlackAttachment() slack.Attachment { @@ -31,24 +36,29 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { // Pretext: "", // Text: text, Fields: fields, - Footer: fmt.Sprintf("Last Funding Fee Transation ID: %d Last Funding Fee Time %s", s.LastFundingFeeTxn, s.LastFundingFeeTime.Format(time.RFC822)), + Footer: fmt.Sprintf("Last Funding Fee Transation ID: %d Last Funding Fee Time %s", s.Last.Txn, s.Last.Time.Format(time.RFC822)), } } func (s *ProfitStats) AddFundingFee(fee FundingFee) error { + if s.txns == nil { + s.txns = make(map[int64]struct{}) + } + 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) } - if s.LastFundingFeeTxn == fee.Txn { + if _, ok := s.txns[fee.Txn]; ok { return errDuplicatedFundingFeeTxnId } s.FundingFeeRecords = append(s.FundingFeeRecords, fee) s.TotalFundingFee = s.TotalFundingFee.Add(fee.Amount) - s.LastFundingFeeTxn = fee.Txn - s.LastFundingFeeTime = fee.Time + s.Last = &fee + + s.txns[fee.Txn] = struct{}{} return nil } diff --git a/pkg/strategy/xfunding/strategy.go b/pkg/strategy/xfunding/strategy.go index 50d1b392b..7cb444a75 100644 --- a/pkg/strategy/xfunding/strategy.go +++ b/pkg/strategy/xfunding/strategy.go @@ -298,7 +298,6 @@ func (s *Strategy) CrossRun( FundingFeeCurrency: s.futuresMarket.QuoteCurrency, TotalFundingFee: fixedpoint.Zero, FundingFeeRecords: nil, - LastFundingFeeTime: time.Time{}, } } @@ -379,10 +378,7 @@ func (s *Strategy) CrossRun( bbgo.Notify("State: %s", s.State.PositionState.String()) // sync funding fee txns - s.syncFundingFeeRecords(ctx, s.ProfitStats.LastFundingFeeTime) - - // TEST CODE: - // s.syncFundingFeeRecords(ctx, time.Now().Add(-3*24*time.Hour)) + s.syncFundingFeeRecords(ctx, time.Now().Add(-5*24*time.Hour)) switch s.State.PositionState { case PositionClosed: From e41f349fe7fadbc29a68216b57b9d7e05fcf9f5f Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:38:56 +0800 Subject: [PATCH 2/4] xfunding: remove debug code --- pkg/strategy/xfunding/strategy.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/pkg/strategy/xfunding/strategy.go b/pkg/strategy/xfunding/strategy.go index 7cb444a75..f4b8c9c72 100644 --- a/pkg/strategy/xfunding/strategy.go +++ b/pkg/strategy/xfunding/strategy.go @@ -829,9 +829,6 @@ func (s *Strategy) syncFuturesPosition(ctx context.Context) { bbgo.Notify("SpotPosition", s.SpotPosition) bbgo.Notify("FuturesPosition", s.FuturesPosition) bbgo.Notify("NeutralPosition", s.NeutralPosition) - - // DEBUG CODE - triggering closing position automatically - // s.startClosingPosition() return } From 665d4ed94bed96b7e8c57dd9d54f17eb690bc345 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:41:06 +0800 Subject: [PATCH 3/4] xfunding: notify profit stats --- pkg/strategy/xfunding/strategy.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/strategy/xfunding/strategy.go b/pkg/strategy/xfunding/strategy.go index f4b8c9c72..ddc85f5d6 100644 --- a/pkg/strategy/xfunding/strategy.go +++ b/pkg/strategy/xfunding/strategy.go @@ -380,6 +380,8 @@ func (s *Strategy) CrossRun( // sync funding fee txns s.syncFundingFeeRecords(ctx, time.Now().Add(-5*24*time.Hour)) + bbgo.Notify(s.ProfitStats) + switch s.State.PositionState { case PositionClosed: // adjust QuoteInvestment according to the available quote balance From ed6a401dec1301260788e8caa9aee80afc485514 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 3 Jan 2024 18:07:20 +0800 Subject: [PATCH 4/4] add funding_fees table migrations --- .../20240103175426_add_funding_fees_table.sql | 31 +++++++++++++++++++ .../20240103175426_add_funding_fees_table.sql | 31 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 migrations/mysql/20240103175426_add_funding_fees_table.sql create mode 100644 migrations/sqlite3/20240103175426_add_funding_fees_table.sql diff --git a/migrations/mysql/20240103175426_add_funding_fees_table.sql b/migrations/mysql/20240103175426_add_funding_fees_table.sql new file mode 100644 index 000000000..703e308db --- /dev/null +++ b/migrations/mysql/20240103175426_add_funding_fees_table.sql @@ -0,0 +1,31 @@ +-- +up +-- +begin +CREATE TABLE `funding_fees` +( + `gid` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + + -- transaction id + `txn_id` BIGINT UNSIGNED NOT NULL, + + -- for exchange + `exchange` VARCHAR(24) NOT NULL DEFAULT '', + + -- asset name, BTC, MAX, USDT ... etc + `asset` VARCHAR(5) NOT NULL, + + -- the amount of the funding fee + `amount` DECIMAL(16, 8) NOT NULL, + + `funded_at` DATETIME NOT NULL, + + PRIMARY KEY (`gid`), + + UNIQUE KEY `txn_id` (`txn_id`, `exchange`) +); +-- +end + +-- +down + +-- +begin +DROP TABLE `funding_fees`; +-- +end diff --git a/migrations/sqlite3/20240103175426_add_funding_fees_table.sql b/migrations/sqlite3/20240103175426_add_funding_fees_table.sql new file mode 100644 index 000000000..0f1dc6708 --- /dev/null +++ b/migrations/sqlite3/20240103175426_add_funding_fees_table.sql @@ -0,0 +1,31 @@ +-- +up +-- +begin +CREATE TABLE `funding_fees` +( + `gid` INTEGER PRIMARY KEY AUTOINCREMENT, + + -- transaction id + `txn_id` INTEGER NOT NULL, + + -- for exchange + `exchange` VARCHAR(24) NOT NULL DEFAULT '', + + -- asset name, BTC, MAX, USDT ... etc + `asset` VARCHAR(5) NOT NULL, + + -- the amount of the funding fee + `amount` DECIMAL(16, 8) NOT NULL, + + `funded_at` DATETIME NOT NULL, + + PRIMARY KEY (`gid`), + + UNIQUE KEY `txn_id` (`txn_id`, `exchange`) +); +-- +end + +-- +down + +-- +begin +DROP TABLE `funding_fees`; +-- +end