From e9f20aa0fc81bb649c985ff067f3f2e1f837ede8 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:32:50 +0800 Subject: [PATCH 1/5] 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 6ae2780b51..0a7700cf2e 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 819edf519a..ba73b1d930 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 1b60bf1662ff7c39f1506fed56c60b48c2db8048 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:38:56 +0800 Subject: [PATCH 2/5] 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 ba73b1d930..c3ea73c4fa 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 ed0f40e47a08423fd87aacbd94e125d5fd55bcf6 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 7 Mar 2024 13:41:06 +0800 Subject: [PATCH 3/5] 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 c3ea73c4fa..b6b476c552 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 37b1d395a5d0feba1eec68448061e971ae04a854 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 3 Jan 2024 18:07:20 +0800 Subject: [PATCH 4/5] 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 0000000000..703e308db7 --- /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 0000000000..0f1dc6708a --- /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 From ab03f080a178fc29d4b7de5f514591fdc7a774f7 Mon Sep 17 00:00:00 2001 From: c9s Date: Thu, 21 Mar 2024 16:27:54 +0800 Subject: [PATCH 5/5] xfunding: use fixed sync range --- pkg/strategy/xfunding/strategy.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/strategy/xfunding/strategy.go b/pkg/strategy/xfunding/strategy.go index b6b476c552..71c6bf8359 100644 --- a/pkg/strategy/xfunding/strategy.go +++ b/pkg/strategy/xfunding/strategy.go @@ -378,7 +378,8 @@ func (s *Strategy) CrossRun( bbgo.Notify("State: %s", s.State.PositionState.String()) // sync funding fee txns - s.syncFundingFeeRecords(ctx, time.Now().Add(-5*24*time.Hour)) + syncFrom, _ := time.Parse(time.RFC3339, "2024-01-01T00:00:00Z") + s.syncFundingFeeRecords(ctx, syncFrom) bbgo.Notify(s.ProfitStats)