Compare commits

...

5 Commits

Author SHA1 Message Date
c9s
1673778300
Merge ed6a401dec into 8e91a023ca 2024-08-28 23:03:59 +07:00
c9s
ed6a401dec
add funding_fees table migrations 2024-03-21 14:37:19 +08:00
c9s
665d4ed94b
xfunding: notify profit stats 2024-03-21 14:37:19 +08:00
c9s
e41f349fe7
xfunding: remove debug code 2024-03-21 14:37:18 +08:00
c9s
dbd54575e6
xfunding: improve funding fee guard 2024-03-21 14:37:18 +08:00
4 changed files with 80 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -17,8 +17,13 @@ type ProfitStats struct {
FundingFeeCurrency string `json:"fundingFeeCurrency"` FundingFeeCurrency string `json:"fundingFeeCurrency"`
TotalFundingFee fixedpoint.Value `json:"totalFundingFee"` TotalFundingFee fixedpoint.Value `json:"totalFundingFee"`
FundingFeeRecords []FundingFee `json:"fundingFeeRecords"` 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 { func (s *ProfitStats) SlackAttachment() slack.Attachment {
@ -31,24 +36,29 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment {
// Pretext: "", // Pretext: "",
// Text: text, // Text: text,
Fields: fields, 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 { func (s *ProfitStats) AddFundingFee(fee FundingFee) error {
if s.txns == nil {
s.txns = make(map[int64]struct{})
}
if s.FundingFeeCurrency == "" { if s.FundingFeeCurrency == "" {
s.FundingFeeCurrency = fee.Asset s.FundingFeeCurrency = fee.Asset
} else if 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 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 return errDuplicatedFundingFeeTxnId
} }
s.FundingFeeRecords = append(s.FundingFeeRecords, fee) s.FundingFeeRecords = append(s.FundingFeeRecords, fee)
s.TotalFundingFee = s.TotalFundingFee.Add(fee.Amount) s.TotalFundingFee = s.TotalFundingFee.Add(fee.Amount)
s.LastFundingFeeTxn = fee.Txn s.Last = &fee
s.LastFundingFeeTime = fee.Time
s.txns[fee.Txn] = struct{}{}
return nil return nil
} }

View File

@ -298,7 +298,6 @@ func (s *Strategy) CrossRun(
FundingFeeCurrency: s.futuresMarket.QuoteCurrency, FundingFeeCurrency: s.futuresMarket.QuoteCurrency,
TotalFundingFee: fixedpoint.Zero, TotalFundingFee: fixedpoint.Zero,
FundingFeeRecords: nil, FundingFeeRecords: nil,
LastFundingFeeTime: time.Time{},
} }
} }
@ -379,10 +378,9 @@ func (s *Strategy) CrossRun(
bbgo.Notify("State: %s", s.State.PositionState.String()) bbgo.Notify("State: %s", s.State.PositionState.String())
// sync funding fee txns // sync funding fee txns
s.syncFundingFeeRecords(ctx, s.ProfitStats.LastFundingFeeTime) s.syncFundingFeeRecords(ctx, time.Now().Add(-5*24*time.Hour))
// TEST CODE: bbgo.Notify(s.ProfitStats)
// s.syncFundingFeeRecords(ctx, time.Now().Add(-3*24*time.Hour))
switch s.State.PositionState { switch s.State.PositionState {
case PositionClosed: case PositionClosed:
@ -833,9 +831,6 @@ func (s *Strategy) syncFuturesPosition(ctx context.Context) {
bbgo.Notify("SpotPosition", s.SpotPosition) bbgo.Notify("SpotPosition", s.SpotPosition)
bbgo.Notify("FuturesPosition", s.FuturesPosition) bbgo.Notify("FuturesPosition", s.FuturesPosition)
bbgo.Notify("NeutralPosition", s.NeutralPosition) bbgo.Notify("NeutralPosition", s.NeutralPosition)
// DEBUG CODE - triggering closing position automatically
// s.startClosingPosition()
return return
} }