diff --git a/trader/hyperliquid/order_sync.go b/trader/hyperliquid/order_sync.go index eff95452..1dbb66b4 100644 --- a/trader/hyperliquid/order_sync.go +++ b/trader/hyperliquid/order_sync.go @@ -20,13 +20,16 @@ func (t *HyperliquidTrader) SyncOrdersFromHyperliquid(traderID string, exchangeI return fmt.Errorf("store is nil") } - // Get recent trades (last 24 hours) - startTime := time.Now().Add(-24 * time.Hour) + // Look back 7 days. GetTrades now pulls up to 2000 recent fills (UserFills) + // and filters to this window, so a wide lookback backfills any fills missed + // during past outages/gaps without dropping recent ones. Dedup by trade ID + // keeps re-processing idempotent. + startTime := time.Now().Add(-7 * 24 * time.Hour) logger.Infof("🔄 Syncing Hyperliquid trades from: %s", startTime.Format(time.RFC3339)) // Use GetTrades method to fetch trade records - trades, err := t.GetTrades(startTime, 1000) + trades, err := t.GetTrades(startTime, 2000) if err != nil { return fmt.Errorf("failed to get trades: %w", err) } diff --git a/trader/hyperliquid/trader_account.go b/trader/hyperliquid/trader_account.go index 6215516a..0e53231a 100644 --- a/trader/hyperliquid/trader_account.go +++ b/trader/hyperliquid/trader_account.go @@ -11,6 +11,8 @@ import ( "strconv" "strings" "time" + + hl "github.com/sonirico/go-hyperliquid" ) // GetBalance gets account balance @@ -548,15 +550,23 @@ func (t *HyperliquidTrader) GetClosedPnL(startTime time.Time, limit int) ([]type // GetTrades retrieves trade history from Hyperliquid func (t *HyperliquidTrader) GetTrades(startTime time.Time, limit int) ([]types.TradeRecord, error) { - // Use UserFillsByTime API + // Use UserFills (returns up to 2000 recent fills) rather than + // UserFillsByTime, which is hard-capped at 100 fills per response. At + // this trading frequency the account exceeds 100 fills/24h, so + // UserFillsByTime silently dropped ~20% of fills — skewing recorded PnL + // and fees away from the exchange truth. 2000 recent fills covers many + // days of history; we filter to startTime client-side. startTimeMs := startTime.UnixMilli() - fills, err := t.exchange.Info().UserFillsByTime(t.ctx, t.walletAddr, startTimeMs, nil, nil) + fills, err := t.exchange.Info().UserFills(t.ctx, hl.UserFillsParams{Address: t.walletAddr}) if err != nil { return nil, fmt.Errorf("failed to get user fills: %w", err) } var trades []types.TradeRecord for _, fill := range fills { + if fill.Time < startTimeMs { + continue + } price, _ := strconv.ParseFloat(fill.Price, 64) qty, _ := strconv.ParseFloat(fill.Size, 64) fee, _ := strconv.ParseFloat(fill.Fee, 64)