Skip to content

Fix: bitget position sync bug#1371

Open
Fumeng24 wants to merge 2 commits intoNoFxAiOS:devfrom
Fumeng24:fix/bitget-position-sync-bug
Open

Fix: bitget position sync bug#1371
Fumeng24 wants to merge 2 commits intoNoFxAiOS:devfrom
Fumeng24:fix/bitget-position-sync-bug

Conversation

@Fumeng24
Copy link

@Fumeng24 Fumeng24 commented Feb 1, 2026

Pull Request

📝 Description

Fix critical bug in Bitget exchange integration where short positions were not being recorded to the database.

Root Cause: In Bitget one-way position mode, the OrderSync logic incorrectly mapped sell_single trades to close_long action always. This caused:

  1. New short positions to be misidentified as closing long trades
  2. PositionBuilder to fail finding a matching LONG position to close
  3. Positions table to remain empty even though short positions were open in Bitget

Solution: Use the profit field to distinguish between opening and closing trades:

  • profit != 0: closing trade (has realized PnL)
  • profit == 0: opening trade (no realized PnL yet)

Also fixed GetOpenPositionBySymbol to match both exact side and BOTH side (used in one-way mode).

Verification: ETH short position opened at 22:46 is now correctly recorded:

123|ETHUSDT|SHORT|OPEN|0.26|2351.81|2026-02-01 22:46:19

🎯 Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📝 Documentation update
  • 🎨 Code style update
  • ♻️ Refactoring
  • ⚡ Performance improvement
  • ✅ Test update
  • 🔧 Build/config change
  • 🔒 Security fix

🔗 Related Issues

  • Fixes: Platform not recording closed/opened positions to database after executing trades on Bitget

📋 Changes Made

  1. order_sync.go - Fix trade action detection

    • Modified GetTrades() to use profit field for distinguishing open/close trades
    • sell_single now correctly maps to open_short when profit == 0
    • buy_single now correctly maps to open_long when profit == 0
    • Added debug logging to show trade classification
  2. store/position.go - Fix position lookup for one-way mode

    • Updated GetOpenPositionBySymbol() to match both exact side and BOTH side
    • One-way positions use side='BOTH' but need to be found when searching for specific directions
    • Query now: (side = ? OR side = 'BOTH')

🧪 Testing

  • Tested locally
  • Tests pass
  • Verified no existing functionality broke
  • ETH short position now correctly recorded to trader_positions table
  • Historical trades synced correctly with proper action classification

✅ Checklist

Code Quality

  • Code follows project style
  • Self-review completed
  • Comments added for complex logic

Documentation

  • Updated relevant documentation (commit messages)

Git

  • Commits follow conventional format (fix: ...)
  • Rebased on latest dev branch
  • No merge conflicts

📚 Additional Notes

This fix addresses a critical data integrity issue where positions opened via Bitget were not persisted to the local database. The system would show positions as open in memory/Bitget API but they would be missing from the database, causing:

  • Position history to be incomplete
  • Risk management calculations to be incorrect
  • Frontend displays to be inaccurate

The fix has been tested with actual ETH short position and verified in the database.


By submitting this PR, I confirm:

  • I have read the Contributing Guidelines
  • I agree to the Code of Conduct
  • My contribution is licensed under AGPL-3.0

🌟 Thank you for your contribution!

In Bitget one-way position mode (buy_single/sell_single):
- sell_single can be either open_short (profit=0) or close_long (profit!=0)
- buy_single can be either open_long (profit=0) or close_short (profit!=0)

The previous logic incorrectly mapped sell_single → close_long always,
which caused new short positions to be misidentified as closing long trades.

This fix uses the profit field to distinguish:
- profit != 0: closing trade (has realized PnL)
- profit == 0: opening trade (no realized PnL yet)

Fixes issue where ETH short positions were not recorded to database.
In Bitget one-way position mode, positions are stored with side='BOTH'
instead of LONG/SHORT. The GetOpenPositionBySymbol function only matched
exact side values, causing it to fail when trying to find positions to close.

This fix updates the query to match both the specified side and 'BOTH':
  (side = ? OR side = 'BOTH')

This ensures positions in one-way mode can be found and properly closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant